Erlang入門教程 - 6. Maps

Maps是一堆鍵值關聯對的集合。鍵值對使用 「#{」 和」}」進行封裝。要創建一個key關聯value 42可以這麼做:

> #{ "key" => 42 }.n#{"key" => 42}n

讓我們通過下面這個使用有趣特性的例子直接跳到一個深度。

下面的例子顯示了如何通過maps引用顏色和α通道進而計算α混合(alpha blending)。在color.erl文件中輸入下面代碼:

-module(color).nn-export([new/4, blend/2]).nn-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).nnnew(R,G,B,A) when ?is_channel(R), ?is_channel(G),n ?is_channel(B), ?is_channel(A) ->n #{red => R, green => G, blue => B, alpha => A}.nnblend(Src,Dst) ->n blend(Src,Dst,alpha(Src,Dst)).nnblend(Src,Dst,Alpha) when Alpha > 0.0 ->n Dst#{n red := red(Src,Dst) / Alpha,n green := green(Src,Dst) / Alpha,n blue := blue(Src,Dst) / Alpha,n alpha := Alphan };nblend(_,Dst,_) ->n Dst#{n red := 0.0,n green := 0.0,n blue := 0.0,n alpha := 0.0n }.nnalpha(#{alpha := SA}, #{alpha := DA}) ->n SA + DA*(1.0 - SA).nnred(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->n SV*SA + DV*DA*(1.0 - SA).ngreen(#{green := SV, alpha := SA}, #{green := DV, alpha := DA}) ->n SV*SA + DV*DA*(1.0 - SA).nblue(#{blue := SV, alpha := SA}, #{blue := DV, alpha := DA}) ->n SV*SA + DV*DA*(1.0 - SA).n

編譯並測試:

> c(color).n{ok,color}n> C1 = color:new(0.3,0.4,0.5,1.0).n#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}n> C2 = color:new(1.0,0.8,0.1,0.3).n#{alpha => 0.3,blue => 0.1,green => 0.8,red => 1.0}n> color:blend(C1,C2).n#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}n> color:blend(C2,C1).n#{alpha => 1.0,blue => 0.38,green => 0.52,red => 0.51}n

This example warrants some explanation:

-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).n

首先定義一個宏is_channel用於guard測試。為了方便起見這裡使用它減少語法的雜糅。關於宏的更多信息,參見Preprocessor[8]。

new(R,G,B,A) when ?is_channel(R), ?is_channel(G),n ?is_channel(B), ?is_channel(A) ->n #{red => R, green => G, blue => B, alpha => A}.n

函數new/4創建一個map並且讓鍵red,green,blue,alpha關聯一個初始值。 在這裡, 將宏?is_channel作用於每個參數,確保只有0.0到1.0之間的浮點值才被允許,只有在創建新map的時候才允許使用=>運算符。

使用new/4創建一個color,然後將colors傳遞給blend/2,它就能計算出混合後的顏色。

首先blend/2做的事是計算混合後的α通道

alpha(#{alpha := SA}, #{alpha := DA}) ->n SA + DA*(1.0 - SA).n

使用:=運算符獲取參數中鍵alpha所關聯的value。參數中的其他鍵會被忽略掉,只要求鍵alpha。

函數red/2, blue/2,green/2也是如此:

red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->n SV*SA + DV*DA*(1.0 - SA).n

這裡不同點是這幾個函數獲取參數中的兩個鍵,其它的被忽略。

最後,讓我們在blend/3中返回混合後的顏色:

blend(Src,Dst,Alpha) when Alpha > 0.0 ->n Dst#{n red := red(Src,Dst) / Alpha,n green := green(Src,Dst) / Alpha,n blue := blue(Src,Dst) / Alpha,n alpha := Alphan };n

Dst使用新通道值進行更新。更新一個已有的鍵關聯的值的語法是使用:=運算符。

推薦閱讀:

我想自學haskell無其他語言基礎 我該怎麼學 有什麼推薦的教材嗎?
Haskell 狂信徒的 Scala 入坑筆記(1)
仙境里的Haskell(之四)—— Functor類型類
函數式編程在Redux/React中的應用

TAG:Erlang编程语言 | 函数式编程 | 编程语言 |