diff options
author | Björn-Egil Dahlberg <[email protected]> | 2014-04-01 11:49:56 +0200 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-04-01 11:49:56 +0200 |
commit | ac1f6ffb557c5e702722e8b74f616c55cee2cee3 (patch) | |
tree | 1ece5d726543c0cd49d005fdb16d36b11481c5e4 /system/doc/getting_started/seq_prog.xml | |
parent | 3ccf4a77ee8ff4ca86ec2c46c2645607c094e800 (diff) | |
parent | fbb05239aeccc400aa4e4a359a3fb81ef555e441 (diff) | |
download | otp-ac1f6ffb557c5e702722e8b74f616c55cee2cee3.tar.gz otp-ac1f6ffb557c5e702722e8b74f616c55cee2cee3.tar.bz2 otp-ac1f6ffb557c5e702722e8b74f616c55cee2cee3.zip |
Merge branch 'egil/maps-doc'
* egil/maps-doc:
doc: Add Maps example for sequential programming
doc: Mention map expressions and map guards
doc: Add maps to reference manual
edoc: Add map/0 as a new predefined type
doc: Descripe Maps type syntax
doc: Clearify language of user-defined attributes
doc: Document Maps datatype in reference manual
erts: Document map guard functions
erts: Fix is_map/1 spec
Diffstat (limited to 'system/doc/getting_started/seq_prog.xml')
-rw-r--r-- | system/doc/getting_started/seq_prog.xml | 123 |
1 files changed, 123 insertions, 0 deletions
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 @@ -419,6 +419,129 @@ list_length([First | Rest]) -> </section> <section> + <title>Maps</title> + <p>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:</p> +<code type="none"> +> #{ "key" => 42 }. +#{"key" => 42}</code> + <p>We will jump straight into the deep end with an example using some + interesting features.</p> + <p>The following example shows how we calculate alpha blending using + maps to reference color and alpha channels:</p> + <code type="none"> +-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).</code> + <p>Compile (file <c>color.erl</c>) and test:</p> + <pre> +> <input>c(color).</input> +{ok,color} +> <input>C1 = color:new(0.3,0.4,0.5,1.0).</input> +#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3} +> <input>C2 = color:new(1.0,0.8,0.1,0.3).</input> +#{alpha => 0.3,blue => 0.1,green => 0.8,red => 1.0} +> <input>color:blend(C1,C2).</input> +#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3} +> <input>color:blend(C2,C1).</input> +#{alpha => 1.0,blue => 0.38,green => 0.52,red => 0.51} +</pre> + <p>This example warrant some explanation:</p> + <code type="none"> +-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).</code> + <p> + First we define a macro <c>is_channel</c> to help with our guard tests. + This is only here for convenience and to reduce syntax cluttering. + + You can read more about <seealso marker="doc/reference_manual:macros">Macros</seealso> + in the Erlang Reference Manual. + </p> + <code type="none"> +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}.</code> + <p> + The function <c>new/4</c> creates a new map term with and lets the keys + <c>red</c>, <c>green</c>, <c>blue</c> and <c>alpha</c> 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 <c>?is_channel/1</c> macro + for each argument. Only the <c>=></c> operator is allowed when creating a new map. + </p> + <p> + By calling <c>blend/2</c> on any color term created by <c>new/4</c> we can calculate + the resulting color as determined by the two maps terms. + </p> + <p> + The first thing <c>blend/2</c> does is to calculate the resulting alpha channel. + </p> + <code type="none"> +alpha(#{alpha := SA}, #{alpha := DA}) -> + SA + DA*(1.0 - SA).</code> + <p> + We fetch the value associated with key <c>alpha</c> for both arguments using + the <c>:=</c> operator. Any other keys + in the map are ignored, only the key <c>alpha</c> is required and checked for. + </p> + <p>This is also the case for functions <c>red/2</c>, <c>blue/2</c> and <c>green/2</c>.</p> + <code type="none"> +red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) -> + SV*SA + DV*DA*(1.0 - SA).</code> + <p> + The difference here is that we check for two keys in each map argument. The other keys + are ignored. + </p> + <p> + Finally we return the resulting color in <c>blend/3</c>. + </p> + <code type="none"> +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 + };</code> + <p> + We update the <c>Dst</c> map with new channel values. The syntax for updating an existing key with a new value is done with <c>:=</c> operator. + </p> + </section> + + <section> <title>Standard Modules and Manual Pages</title> <p>Erlang has a lot of standard modules to help you do things. For example, the module <c>io</c> contains a lot of functions to help |