From fbb05239aeccc400aa4e4a359a3fb81ef555e441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 18 Mar 2014 14:59:50 +0100 Subject: doc: Add Maps example for sequential programming --- system/doc/getting_started/seq_prog.xml | 123 ++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'system/doc/getting_started/seq_prog.xml') diff --git a/system/doc/getting_started/seq_prog.xml b/system/doc/getting_started/seq_prog.xml index 3830a34e5a..fd49102263 100644 --- a/system/doc/getting_started/seq_prog.xml +++ b/system/doc/getting_started/seq_prog.xml @@ -418,6 +418,129 @@ list_length([First | Rest]) -> "abc" +
+ Maps +

Maps are a set of key to value associations. These associations + are encapsulated with "#{" and "}". To create an association from + "key" to value 42, we write:

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

We will jump straight into the deep end with an example using some + interesting features.

+

The following example shows how we calculate alpha blending using + maps to reference color and alpha channels:

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

Compile (file color.erl) and test:

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

This example warrant some explanation:

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

+ First we define a macro is_channel to help with our guard tests. + This is only here for convenience and to reduce syntax cluttering. + + You can read more about Macros + in the Erlang Reference Manual. +

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

+ The function new/4 creates a new map term with and lets the keys + red, green, blue and alpha be associated + with an initial value. In this case we only allow for float + values between and including 0.0 and 1.0 as ensured by the ?is_channel/1 macro + for each argument. Only the => operator is allowed when creating a new map. +

+

+ By calling blend/2 on any color term created by new/4 we can calculate + the resulting color as determined by the two maps terms. +

+

+ The first thing blend/2 does is to calculate the resulting alpha channel. +

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

+ We fetch the value associated with key alpha for both arguments using + the := operator. Any other keys + in the map are ignored, only the key alpha is required and checked for. +

+

This is also the case for functions red/2, blue/2 and green/2.

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

+ The difference here is that we check for two keys in each map argument. The other keys + are ignored. +

+

+ Finally we return the resulting color in blend/3. +

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

+ We update the Dst map with new channel values. The syntax for updating an existing key with a new value is done with := operator. +

+
+
Standard Modules and Manual Pages

Erlang has a lot of standard modules to help you do things. For -- cgit v1.2.3