diff options
author | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2017-08-30 20:55:08 +0200 |
commit | 7c67bbddb53c364086f66260701bc54a61c9659c (patch) | |
tree | 92ab0d4b91d5e2f6e7a3f9d61ea25089e8a71fe0 /system/doc/reference_manual/expressions.xml | |
parent | 97dc5e7f396129222419811c173edc7fa767b0f8 (diff) | |
parent | 3b7a6ffddc819bf305353a593904cea9e932e7dc (diff) | |
download | otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.gz otp-7c67bbddb53c364086f66260701bc54a61c9659c.tar.bz2 otp-7c67bbddb53c364086f66260701bc54a61c9659c.zip |
Merge tag 'OTP-19.0' into sverker/19/binary_to_atom-utf8-crash/ERL-474/OTP-14590
Diffstat (limited to 'system/doc/reference_manual/expressions.xml')
-rw-r--r-- | system/doc/reference_manual/expressions.xml | 939 |
1 files changed, 625 insertions, 314 deletions
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml index 357f89f731..355fd3cfef 100644 --- a/system/doc/reference_manual/expressions.xml +++ b/system/doc/reference_manual/expressions.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2012</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -28,13 +29,17 @@ <rev></rev> <file>expressions.xml</file> </header> - <p>In this chapter, all valid Erlang expressions are listed. + <p>In this section, all valid Erlang expressions are listed. When writing Erlang programs, it is also allowed to use macro- and record expressions. However, these expressions are expanded during compilation and are in that sense not true Erlang expressions. Macro- and record expressions are covered in - separate chapters: <seealso marker="macros">Macros</seealso> and - <seealso marker="records">Records</seealso>.</p> + separate sections: + </p> + <list type="bulleted"> + <item><p><seealso marker="macros">Preprocessor</seealso></p></item> + <item><p><seealso marker="records">Records</seealso></p></item> + </list> <section> <title>Expression Evaluation</title> @@ -48,15 +53,15 @@ Expr1 + Expr2</code> performed.</p> <p>Many of the operators can only be applied to arguments of a certain type. For example, arithmetic operators can only be - applied to numbers. An argument of the wrong type will cause - a <c>badarg</c> run-time error.</p> + applied to numbers. An argument of the wrong type causes + a <c>badarg</c> runtime error.</p> </section> <section> <marker id="term"></marker> <title>Terms</title> <p>The simplest form of expression is a term, that is an integer, - float, atom, string, list or tuple. + float, atom, string, list, map, or tuple. The return value is the term itself.</p> </section> @@ -65,9 +70,10 @@ Expr1 + Expr2</code> <p>A variable is an expression. If a variable is bound to a value, the return value is this value. Unbound variables are only allowed in patterns.</p> - <p>Variables start with an uppercase letter or underscore (_) - and may contain alphanumeric characters, underscore and @. - Examples:</p> + <p>Variables start with an uppercase letter or underscore (_). + Variables can contain alphanumeric characters, underscore and <c>@</c>. + </p> + <p><em>Examples:</em></p> <pre> X Name1 @@ -77,18 +83,20 @@ _ _Height</pre> <p>Variables are bound to values using <seealso marker="patterns">pattern matching</seealso>. Erlang - uses <em>single assignment</em>, a variable can only be bound + uses <em>single assignment</em>, that is, a variable can only be bound once.</p> <p>The <em>anonymous variable</em> is denoted by underscore (_) and can be used when a variable is required but its value can be - ignored. Example:</p> + ignored.</p> + <p><em>Example:</em></p> <pre> [H|_] = [1,2,3]</pre> - <p>Variables starting with underscore (_), for example + <p>Variables starting with underscore (_), for example, <c>_Height</c>, are normal variables, not anonymous. They are - however ignored by the compiler in the sense that they will not - generate any warnings for unused variables. Example: The following - code</p> + however ignored by the compiler in the sense that they do not + generate any warnings for unused variables.</p> + <p><em>Example:</em></p> + <p>The following code:</p> <pre> member(_, []) -> [].</pre> @@ -96,36 +104,37 @@ member(_, []) -> <pre> member(Elem, []) -> [].</pre> - <p>This will however cause a warning for an unused variable + <p>This causes a warning for an unused variable, <c>Elem</c>, if the code is compiled with the flag <c>warn_unused_vars</c> set. Instead, the code can be rewritten to:</p> <pre> member(_Elem, []) -> [].</pre> - <p>Note that since variables starting with an underscore are - not anonymous, this will match:</p> + <p>Notice that since variables starting with an underscore are + not anonymous, this matches:</p> <pre> {_,_} = {1,2}</pre> - <p>But this will fail:</p> + <p>But this fails:</p> <pre> {_N,_N} = {1,2}</pre> <p>The scope for a variable is its function clause. Variables bound in a branch of an <c>if</c>, <c>case</c>, or <c>receive</c> expression must be bound in all branches - to have a value outside the expression, otherwise they - will be regarded as 'unsafe' outside the expression.</p> + to have a value outside the expression. Otherwise they + are regarded as 'unsafe' outside the expression.</p> <p>For the <c>try</c> expression introduced in - Erlang 5.4/OTP-R10B, variable scoping is limited so that + Erlang 5.4/OTP R10B, variable scoping is limited so that variables bound in the expression are always 'unsafe' outside - the expression. This will be improved.</p> + the expression. This is to be improved.</p> </section> <section> <marker id="pattern"></marker> <title>Patterns</title> - <p>A pattern has the same structure as a term but may contain - unbound variables. Example:</p> + <p>A pattern has the same structure as a term but can contain + unbound variables.</p> + <p><em>Example:</em></p> <pre> Name1 [H|T] @@ -136,13 +145,13 @@ Name1 <section> <title>Match Operator = in Patterns</title> <p>If <c>Pattern1</c> and <c>Pattern2</c> are valid patterns, - then the following is also a valid pattern:</p> + the following is also a valid pattern:</p> <pre> Pattern1 = Pattern2</pre> <p>When matched against a term, both <c>Pattern1</c> and - <c>Pattern2</c> will be matched against the term. The idea - behind this feature is to avoid reconstruction of terms. - Example:</p> + <c>Pattern2</c> are matched against the term. The idea + behind this feature is to avoid reconstruction of terms.</p> + <p><em>Example:</em></p> <pre> f({connect,From,To,Number,Options}, To) -> Signal = {connect,From,To,Number,Options}, @@ -163,16 +172,20 @@ f(Signal, To) -> <pre> f("prefix" ++ Str) -> ...</pre> <p>This is syntactic sugar for the equivalent, but harder to - read</p> + read:</p> <pre> f([$p,$r,$e,$f,$i,$x | Str]) -> ...</pre> </section> <section> <title>Expressions in Patterns</title> - <p>An arithmetic expression can be used within a pattern, if - it uses only numeric or bitwise operators, and if its value - can be evaluated to a constant at compile-time. Example:</p> + <p>An arithmetic expression can be used within a pattern if + it meets both of the following two conditions:</p> + <list type="bulleted"> + <item>It uses only numeric or bitwise operators.</item> + <item>Its value can be evaluated to a constant when complied.</item> + </list> + <p><em>Example:</em></p> <pre> case {Value, Result} of {?THRESHOLD+1, ok} -> ...</pre> @@ -182,21 +195,21 @@ case {Value, Result} of <section> <title>Match</title> + <p>The following matches <c>Expr1</c>, a pattern, against + <c>Expr2</c>:</p> <pre> Expr1 = Expr2</pre> - <p>Matches <c>Expr1</c>, a pattern, against <c>Expr2</c>. - If the matching succeeds, any unbound variable in the pattern + <p>If the matching succeeds, any unbound variable in the pattern becomes bound and the value of <c>Expr2</c> is returned.</p> - <p>If the matching fails, a <c>badmatch</c> run-time error will - occur.</p> - <p>Examples:</p> + <p>If the matching fails, a <c>badmatch</c> run-time error occurs.</p> + <p><em>Examples:</em></p> <pre> 1> <input>{A, B} = {answer, 42}.</input> {answer,42} 2> <input>A.</input> answer 3> <input>{C, D} = [1, 2].</input> -** exception error: no match of right hand side value [1,2]</pre> +** exception error: no match of right-hand side value [1,2]</pre> </section> <section> @@ -210,45 +223,45 @@ ExprM:ExprF(Expr1,...,ExprN)</pre> <c>ExprF</c> must be an atom or an expression that evaluates to an atom. The function is said to be called by using the <em>fully qualified function name</em>. This is often referred - to as a <em>remote</em> or <em>external function call</em>. - Example:</p> + to as a <em>remote</em> or <em>external function call</em>.</p> + <p><em>Example:</em></p> <code type="none"> lists:keysearch(Name, 1, List)</code> <p>In the second form of function calls, <c>ExprF(Expr1,...,ExprN)</c>, <c>ExprF</c> must be an atom or evaluate to a fun.</p> - <p>If <c>ExprF</c> is an atom the function is said to be called by + <p>If <c>ExprF</c> is an atom, the function is said to be called by using the <em>implicitly qualified function name</em>. If the function <c>ExprF</c> is locally defined, it is called. - Alternatively if <c>ExprF</c> is explicitly imported from module - <c>M</c>, <c>M:ExprF(Expr1,...,ExprN)</c> is called. If + Alternatively, if <c>ExprF</c> is explicitly imported from the + <c>M</c> module, <c>M:ExprF(Expr1,...,ExprN)</c> is called. If <c>ExprF</c> is neither declared locally nor explicitly imported, <c>ExprF</c> must be the name of an automatically - imported BIF. Examples:</p> + imported BIF. </p> + <p><em>Examples:</em></p> <code type="none"> handle(Msg, State) spawn(m, init, [])</code> - <p>Examples where ExprF is a fun:</p> - <code type="none"> -Fun1 = fun(X) -> X+1 end -Fun1(3) -=> 4 - -fun lists:append/2([1,2], [3,4]) -=> [1,2,3,4]</code> - - <p>Note that when calling a local function, there is a difference - between using the implicitly or fully qualified function name, as - the latter always refers to the latest version of the module. See - <seealso marker="code_loading">Compilation and Code Loading</seealso>.</p> - - <p>See also the chapter about - <seealso marker="functions#eval">Function Evaluation</seealso>.</p> + <p><em>Examples</em> where <c>ExprF</c> is a fun:</p> + <pre> +1> <input>Fun1 = fun(X) -> X+1 end,</input> +<input>Fun1(3).</input> +4 +2> <input>fun lists:append/2([1,2], [3,4]).</input> +[1,2,3,4] +3> </pre> + + <p>Notice that when calling a local function, there is a difference + between using the implicitly or fully qualified function name. + The latter always refers to the latest version of the module. + See <seealso marker="code_loading">Compilation and Code Loading + </seealso> and <seealso marker="functions#eval"> + Function Evaluation</seealso>.</p> <section> - <title>Local Function Names Clashing With Auto-imported BIFs</title> + <title>Local Function Names Clashing With Auto-Imported BIFs</title> <p>If a local function has the same name as an auto-imported BIF, the semantics is that implicitly qualified function calls are directed to the locally defined function, not to the BIF. To avoid @@ -260,9 +273,9 @@ fun lists:append/2([1,2], [3,4]) <warning><p>Before OTP R14A (ERTS version 5.8), an implicitly qualified function call to a function having the same name as an auto-imported BIF always resulted in the BIF being called. In - newer versions of the compiler the local function is instead - called. The change is there to avoid that future additions to the - set of auto-imported BIFs does not silently change the behavior + newer versions of the compiler, the local function is called instead. + This is to avoid that future additions to the + set of auto-imported BIFs do not silently change the behavior of old code.</p> <p>However, to avoid that old (pre R14) code changed its @@ -272,8 +285,8 @@ fun lists:append/2([1,2], [3,4]) 5.8) and have an implicitly qualified call to that function in your code, you either need to explicitly remove the auto-import using a compiler directive, or replace the call with a fully - qualified function call, otherwise you will get a compilation - error. See example below:</p> </warning> + qualified function call. Otherwise you get a compilation + error. See the following example:</p> </warning> <code type="none"> -export([length/1,f/1]). @@ -283,16 +296,17 @@ fun lists:append/2([1,2], [3,4]) length([]) -> 0; length([H|T]) -> - 1 + length(T). %% Calls the local funtion length/1 + 1 + length(T). %% Calls the local function length/1 f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1, %% which is allowed in guards long.</code> <p>The same logic applies to explicitly imported functions from - other modules as to locally defined functions. To both import a + other modules, as to locally defined functions. + It is not allowed to both import a function from another module and have the function declared in the - module at the same time is not allowed.</p> + module at the same time:</p> <code type="none"> -export([f/1]). @@ -301,7 +315,7 @@ f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1, -import(mod,[length/1]). -f(X) when erlang:length(X) > 33 -> %% Calls erlang:lenght/1, +f(X) when erlang:length(X) > 33 -> %% Calls erlang:length/1, %% which is allowed in guards erlang:length(X); %% Explicit call to erlang:length in body @@ -310,10 +324,10 @@ f(X) -> length(X). %% mod:length/1 is called</code> - <p>For auto-imported BIFs added to Erlang in release R14A and thereafter, + <p>For auto-imported BIFs added in Erlang/OTP R14A and thereafter, overriding the name with a local function or explicit import is always allowed. However, if the <c>-compile({no_auto_import,[F/A])</c> - directive is not used, the compiler will issue a warning whenever + directive is not used, the compiler issues a warning whenever the function is called in the module using the implicitly qualified function name.</p> </section> @@ -330,15 +344,16 @@ if BodyN end</pre> <p>The branches of an <c>if</c>-expression are scanned sequentially - until a guard sequence <c>GuardSeq</c> which evaluates to true is + until a guard sequence <c>GuardSeq</c> that evaluates to true is found. Then the corresponding <c>Body</c> (sequence of expressions separated by ',') is evaluated.</p> <p>The return value of <c>Body</c> is the return value of the <c>if</c> expression.</p> - <p>If no guard sequence is true, an <c>if_clause</c> run-time error - will occur. If necessary, the guard expression <c>true</c> can be + <p>If no guard sequence is evaluated as true, + an <c>if_clause</c> run-time error + occurs. If necessary, the guard expression <c>true</c> can be used in the last branch, as that guard sequence is always true.</p> - <p>Example:</p> + <p><em>Example:</em></p> <pre> is_greater_than(X, Y) -> if @@ -367,8 +382,8 @@ end</pre> <p>The return value of <c>Body</c> is the return value of the <c>case</c> expression.</p> <p>If there is no matching pattern with a true guard sequence, - a <c>case_clause</c> run-time error will occur.</p> - <p>Example:</p> + a <c>case_clause</c> run-time error occurs.</p> + <p><em>Example:</em></p> <pre> is_valid_signal(Signal) -> case Signal of @@ -389,15 +404,15 @@ Expr1 ! Expr2</pre> <p>Sends the value of <c>Expr2</c> as a message to the process specified by <c>Expr1</c>. The value of <c>Expr2</c> is also the return value of the expression.</p> - <p><c>Expr1</c> must evaluate to a pid, a registered name (atom) or - a tuple <c>{Name,Node}</c>, where <c>Name</c> is an atom and - <c>Node</c> a node name, also an atom.</p> + <p><c>Expr1</c> must evaluate to a pid, a registered name (atom), or + a tuple <c>{Name,Node}</c>. <c>Name</c> is an atom and + <c>Node</c> is a node name, also an atom.</p> <list type="bulleted"> <item>If <c>Expr1</c> evaluates to a name, but this name is not - registered, a <c>badarg</c> run-time error will occur.</item> + registered, a <c>badarg</c> run-time error occurs.</item> <item>Sending a message to a pid never fails, even if the pid identifies a non-existing process.</item> - <item>Distributed message sending, that is if <c>Expr1</c> + <item>Distributed message sending, that is, if <c>Expr1</c> evaluates to a tuple <c>{Name,Node}</c> (or a pid located at another node), also never fails.</item> </list> @@ -420,14 +435,14 @@ end</pre> the second, and so on. If a match succeeds and the optional guard sequence <c>GuardSeq</c> is true, the corresponding <c>Body</c> is evaluated. The matching message is consumed, that - is removed from the mailbox, while any other messages in + is, removed from the mailbox, while any other messages in the mailbox remain unchanged.</p> <p>The return value of <c>Body</c> is the return value of the <c>receive</c> expression.</p> - <p><c>receive</c> never fails. Execution is suspended, possibly - indefinitely, until a message arrives that does match one of + <p><c>receive</c> never fails. The execution is suspended, possibly + indefinitely, until a message arrives that matches one of the patterns and with a true guard sequence. </p> - <p>Example:</p> + <p><em>Example:</em></p> <pre> wait_for_onhook() -> receive @@ -438,7 +453,7 @@ wait_for_onhook() -> B ! {busy, self()}, wait_for_onhook() end.</pre> - <p>It is possible to augment the <c>receive</c> expression with a + <p>The <c>receive</c> expression can be augmented with a timeout:</p> <pre> receive @@ -451,14 +466,14 @@ after ExprT -> BodyT end</pre> - <p><c>ExprT</c> should evaluate to an integer. The highest allowed - value is 16#ffffffff, that is, the value must fit in 32 bits. + <p><c>ExprT</c> is to evaluate to an integer. The highest allowed + value is 16#FFFFFFFF, that is, the value must fit in 32 bits. <c>receive..after</c> works exactly as <c>receive</c>, except that if no matching message has arrived within <c>ExprT</c> - milliseconds, then <c>BodyT</c> is evaluated instead and its - return value becomes the return value of the <c>receive..after</c> - expression.</p> - <p>Example:</p> + milliseconds, then <c>BodyT</c> is evaluated instead. The + return value of <c>BodyT</c> then becomes the return value + of the <c>receive..after</c> expression.</p> + <p><em>Example:</em></p> <pre> wait_for_onhook() -> receive @@ -481,10 +496,10 @@ after ExprT -> BodyT end</pre> - <p>This construction will not consume any messages, only suspend - execution in the process for <c>ExprT</c> milliseconds and can be + <p>This construction does not consume any messages, only suspends + execution in the process for <c>ExprT</c> milliseconds. This can be used to implement simple timers.</p> - <p>Example:</p> + <p><em>Example:</em></p> <pre> timer() -> spawn(m, timer, [self()]). @@ -498,12 +513,12 @@ timer(Pid) -> <p>There are two special cases for the timeout value <c>ExprT</c>:</p> <taglist> <tag><c>infinity</c></tag> - <item>The process should wait indefinitely for a matching message - -- this is the same as not using a timeout. Can be - useful for timeout values that are calculated at run-time.</item> + <item>The process is to wait indefinitely for a matching message; + this is the same as not using a timeout. This can be + useful for timeout values that are calculated at runtime.</item> <tag>0</tag> <item>If there is no matching message in the mailbox, the timeout - will occur immediately.</item> + occurs immediately.</item> </taglist> </section> @@ -518,64 +533,73 @@ Expr1 <input>op</input> Expr2</pre> </row> <row> <cell align="left" valign="middle">==</cell> - <cell align="left" valign="middle">equal to</cell> + <cell align="left" valign="middle">Equal to</cell> </row> <row> <cell align="left" valign="middle">/=</cell> - <cell align="left" valign="middle">not equal to</cell> + <cell align="left" valign="middle">Not equal to</cell> </row> <row> <cell align="left" valign="middle">=<</cell> - <cell align="left" valign="middle">less than or equal to</cell> + <cell align="left" valign="middle">Less than or equal to</cell> </row> <row> <cell align="left" valign="middle"><</cell> - <cell align="left" valign="middle">less than</cell> + <cell align="left" valign="middle">Less than</cell> </row> <row> <cell align="left" valign="middle">>=</cell> - <cell align="left" valign="middle">greater than or equal to</cell> + <cell align="left" valign="middle">Greater than or equal to</cell> </row> <row> <cell align="left" valign="middle">></cell> - <cell align="left" valign="middle">greater than</cell> + <cell align="left" valign="middle">Greater than</cell> </row> <row> <cell align="left" valign="middle">=:=</cell> - <cell align="left" valign="middle">exactly equal to</cell> + <cell align="left" valign="middle">Exactly equal to</cell> </row> <row> <cell align="left" valign="middle">=/=</cell> - <cell align="left" valign="middle">exactly not equal to</cell> + <cell align="left" valign="middle">Exactly not equal to</cell> </row> <tcaption>Term Comparison Operators.</tcaption> </table> - <p>The arguments may be of different data types. The following + <p>The arguments can be of different data types. The following order is defined:</p> <pre> -number < atom < reference < fun < port < pid < tuple < list < bit string</pre> +number < atom < reference < fun < port < pid < tuple < map < nil < list < bit string</pre> <p>Lists are compared element by element. Tuples are ordered by size, two tuples with the same size are compared element by element.</p> + <p>Maps are ordered by size, two maps with the same size are compared by keys in + ascending term order and then by values in key order. + In maps key order integers types are considered less than floats types. + </p> <p>When comparing an integer to a float, the term with the lesser - precision will be converted into the other term's type, unless the - operator is one of =:= or =/=. A float is more precise than + precision is converted into the type of the other term, unless the + operator is one of <c>=:=</c> or <c>=/=</c>. A float is more precise than an integer until all significant figures of the float are to the left of the decimal point. This happens when the float is larger/smaller than +/-9007199254740992.0. The conversion strategy is changed depending on the size of the float because otherwise comparison of large floats and integers would lose their transitivity.</p> - <p>Returns the Boolean value of the expression, <c>true</c> or - <c>false</c>.</p> - <p>Examples:</p> + <p>Term comparison operators return the Boolean value of the + expression, <c>true</c> or <c>false</c>.</p> + + <p><em>Examples:</em></p> <pre> 1> <input>1==1.0.</input> true 2> <input>1=:=1.0.</input> false 3> <input>1 > a.</input> -false</pre> +false +4> <input>#{c => 3} > #{a => 1, b => 2}.</input> +false +4> <input>#{a => 1, b => 2} == #{a => 1.0, b => 2.0}.</input> +true</pre> </section> <section> @@ -585,19 +609,19 @@ false</pre> Expr1 <input>op</input> Expr2</pre> <table> <row> - <cell align="left" valign="middle"><em>op</em></cell> + <cell align="left" valign="middle"><em>Operator</em></cell> <cell align="left" valign="middle"><em>Description</em></cell> - <cell align="left" valign="middle"><em>Argument type</em></cell> + <cell align="left" valign="middle"><em>Argument Type</em></cell> </row> <row> <cell align="left" valign="middle">+</cell> - <cell align="left" valign="middle">unary +</cell> - <cell align="left" valign="middle">number</cell> + <cell align="left" valign="middle">Unary +</cell> + <cell align="left" valign="middle">Number</cell> </row> <row> <cell align="left" valign="middle">-</cell> - <cell align="left" valign="middle">unary -</cell> - <cell align="left" valign="middle">number</cell> + <cell align="left" valign="middle">Unary -</cell> + <cell align="left" valign="middle">Number</cell> </row> <row> <cell align="left" valign="middle">+</cell> @@ -607,62 +631,62 @@ Expr1 <input>op</input> Expr2</pre> <row> <cell align="left" valign="middle">-</cell> <cell align="left" valign="middle"> </cell> - <cell align="left" valign="middle">number</cell> + <cell align="left" valign="middle">Number</cell> </row> <row> <cell align="left" valign="middle">*</cell> <cell align="left" valign="middle"> </cell> - <cell align="left" valign="middle">number</cell> + <cell align="left" valign="middle">Number</cell> </row> <row> <cell align="left" valign="middle">/</cell> - <cell align="left" valign="middle">floating point division</cell> - <cell align="left" valign="middle">number</cell> + <cell align="left" valign="middle">Floating point division</cell> + <cell align="left" valign="middle">Number</cell> </row> <row> <cell align="left" valign="middle">bnot</cell> - <cell align="left" valign="middle">unary bitwise not</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Unary bitwise NOT</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">div</cell> - <cell align="left" valign="middle">integer division</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Integer division</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">rem</cell> - <cell align="left" valign="middle">integer remainder of X/Y</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Integer remainder of X/Y</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">band</cell> - <cell align="left" valign="middle">bitwise and</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Bitwise AND</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">bor</cell> - <cell align="left" valign="middle">bitwise or</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Bitwise OR</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">bxor</cell> - <cell align="left" valign="middle">arithmetic bitwise xor</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Arithmetic bitwise XOR</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">bsl</cell> - <cell align="left" valign="middle">arithmetic bitshift left</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Arithmetic bitshift left</cell> + <cell align="left" valign="middle">Integer</cell> </row> <row> <cell align="left" valign="middle">bsr</cell> - <cell align="left" valign="middle">bitshift right</cell> - <cell align="left" valign="middle">integer</cell> + <cell align="left" valign="middle">Bitshift right</cell> + <cell align="left" valign="middle">Integer</cell> </row> <tcaption>Arithmetic Operators.</tcaption> </table> - <p>Examples:</p> + <p><em>Examples:</em></p> <pre> 1> <input>+1.</input> 1 @@ -697,28 +721,28 @@ Expr1 <input>op</input> Expr2</pre> Expr1 <input>op</input> Expr2</pre> <table> <row> - <cell align="left" valign="middle"><em>op</em></cell> + <cell align="left" valign="middle"><em>Operator</em></cell> <cell align="left" valign="middle"><em>Description</em></cell> </row> <row> <cell align="left" valign="middle">not</cell> - <cell align="left" valign="middle">unary logical not</cell> + <cell align="left" valign="middle">Unary logical NOT</cell> </row> <row> <cell align="left" valign="middle">and</cell> - <cell align="left" valign="middle">logical and</cell> + <cell align="left" valign="middle">Logical AND</cell> </row> <row> <cell align="left" valign="middle">or</cell> - <cell align="left" valign="middle">logical or</cell> + <cell align="left" valign="middle">Logical OR</cell> </row> <row> <cell align="left" valign="middle">xor</cell> - <cell align="left" valign="middle">logical xor</cell> + <cell align="left" valign="middle">Logical XOR</cell> </row> <tcaption>Logical Operators.</tcaption> </table> - <p>Examples:</p> + <p><em>Examples:</em></p> <pre> 1> <input>not true.</input> false @@ -737,28 +761,37 @@ true <pre> Expr1 orelse Expr2 Expr1 andalso Expr2</pre> - <p>Expressions where <c>Expr2</c> is evaluated only if - necessary. That is, <c>Expr2</c> is evaluated only if <c>Expr1</c> - evaluates to <c>false</c> in an <c>orelse</c> expression, or only - if <c>Expr1</c> evaluates to <c>true</c> in an <c>andalso</c> - expression. Returns either the value of <c>Expr1</c> (that is, + <p><c>Expr2</c> is evaluated only if + necessary. That is, <c>Expr2</c> is evaluated only if:</p> + <list type="bulleted"> + <item><p><c>Expr1</c> evaluates to <c>false</c> in an + <c>orelse</c> expression.</p> + </item> + </list> + <p>or</p> + <list type="bulleted"> + <item><p><c>Expr1</c> evaluates to <c>true</c> in an + <c>andalso</c> expression.</p> + </item> + </list> + <p>Returns either the value of <c>Expr1</c> (that is, <c>true</c> or <c>false</c>) or the value of <c>Expr2</c> - (if <c>Expr2</c> was evaluated).</p> + (if <c>Expr2</c> is evaluated).</p> - <p>Example 1:</p> + <p><em>Example 1:</em></p> <pre> case A >= -1.0 andalso math:sqrt(A+1) > B of</pre> - <p>This will work even if <c>A</c> is less than <c>-1.0</c>, + <p>This works even if <c>A</c> is less than <c>-1.0</c>, since in that case, <c>math:sqrt/1</c> is never evaluated.</p> - <p>Example 2:</p> + <p><em>Example 2:</em></p> <pre> OnlyOne = is_atom(L) orelse (is_list(L) andalso length(L) == 1),</pre> - <p>From R13A, <c>Expr2</c> is no longer required to evaluate to a - boolean value. As a consequence, <c>andalso</c> and <c>orelse</c> + <p>From Erlang/OTP R13A, <c>Expr2</c> is no longer required to evaluate to a + Boolean value. As a consequence, <c>andalso</c> and <c>orelse</c> are now tail-recursive. For instance, the following function is - tail-recursive in R13A and later:</p> + tail-recursive in Erlang/OTP R13A and later:</p> <pre> all(Pred, [Hd|Tail]) -> @@ -774,11 +807,11 @@ Expr1 ++ Expr2 Expr1 -- Expr2</pre> <p>The list concatenation operator <c>++</c> appends its second argument to its first and returns the resulting list.</p> - <p>The list subtraction operator <c>--</c> produces a list which - is a copy of the first argument, subjected to the following - procedure: for each element in the second argument, the first + <p>The list subtraction operator <c>--</c> produces a list that + is a copy of the first argument. The procedure is a follows: + for each element in the second argument, the first occurrence of this element (if any) is removed.</p> - <p>Example:</p> + <p><em>Example:</em></p> <pre> 1> <input>[1,2,3]++[4,5].</input> [1,2,3,4,5] @@ -786,12 +819,257 @@ Expr1 -- Expr2</pre> [3,1,2]</pre> <warning><p>The complexity of <c>A -- B</c> is - proportional to <c>length(A)*length(B)</c>, meaning that it - will be very slow if both <c>A</c> and <c>B</c> are + proportional to <c>length(A)*length(B)</c>. That is, it + becomes very slow if both <c>A</c> and <c>B</c> are long lists.</p></warning> </section> <section> + <marker id="map_expressions"></marker> + <title>Map Expressions</title> + <section> + <title>Creating Maps</title> + <p> + Constructing a new map is done by letting an expression <c>K</c> be associated with + another expression <c>V</c>: + </p> + <code>#{ K => V }</code> + <p> + New maps can include multiple associations at construction by listing every + association: + </p> + <code>#{ K1 => V1, .., Kn => Vn }</code> + <p> + An empty map is constructed by not associating any terms with each other: + </p> + <code>#{}</code> + <p> + All keys and values in the map are terms. Any expression is first evaluated and + then the resulting terms are used as <em>key</em> and <em>value</em> respectively. + </p> + <p> + Keys and values are separated by the <c>=></c> arrow and associations are + separated by a comma <c>,</c>. + </p> + + <p> + <em>Examples:</em> + </p> + <code> +M0 = #{}, % empty map +M1 = #{a => <<"hello">>}, % single association with literals +M2 = #{1 => 2, b => b}, % multiple associations with literals +M3 = #{k => {A,B}}, % single association with variables +M4 = #{{"w", 1} => f()}. % compound key associated with an evaluated expression</code> + <p> + Here, <c>A</c> and <c>B</c> are any expressions and <c>M0</c> through <c>M4</c> + are the resulting map terms. + </p> + <p> + If two matching keys are declared, the latter key takes precedence. + </p> + <p> + <em>Example:</em> + </p> + +<pre> +1> <input>#{1 => a, 1 => b}.</input> +#{1 => b } +2> <input>#{1.0 => a, 1 => b}.</input> +#{1 => b, 1.0 => a} +</pre> + <p> + The order in which the expressions constructing the keys (and their + associated values) are evaluated is not defined. The syntactic order of + the key-value pairs in the construction is of no relevance, except in + the recently mentioned case of two matching keys. + </p> + </section> + + <section> + <title>Updating Maps</title> + <p> + Updating a map has a similar syntax as constructing it. + </p> + <p> + An expression defining the map to be updated, is put in front of the expression + defining the keys to be updated and their respective values: + </p> + <code>M#{ K => V }</code> + <p> + Here <c>M</c> is a term of type map and <c>K</c> and <c>V</c> are any expression. + </p> + <p> + If key <c>K</c> does not match any existing key in the map, a new association + is created from key <c>K</c> to value <c>V</c>. + </p> + <p> If key <c>K</c> matches an existing key in map <c>M</c>, + its associated value + is replaced by the new value <c>V</c>. In both cases, the evaluated map expression + returns a new map. + </p> + <p> + If <c>M</c> is not of type map, an exception of type <c>badmap</c> is thrown. + </p> + <p> + To only update an existing value, the following syntax is used: + </p> + <code>M#{ K := V } </code> + <p> + Here <c>M</c> is a term of type map, <c>V</c> is an expression and <c>K</c> + is an expression that evaluates to an existing key in <c>M</c>. + </p> + <p> + If key <c>K</c> does not match any existing keys in map <c>M</c>, an exception + of type <c>badarg</c> is triggered at runtime. If a matching key <c>K</c> + is present in map <c>M</c>, its associated value is replaced by the new + value <c>V</c>, and the evaluated map expression returns a new map. + </p> + <p> + If <c>M</c> is not of type map, an exception of type <c>badmap</c> is thrown. + </p> + <p> + <em>Examples:</em> + </p> + <code> +M0 = #{}, +M1 = M0#{a => 0}, +M2 = M1#{a => 1, b => 2}, +M3 = M2#{"function" => fun() -> f() end}, +M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code> + <p> + Here <c>M0</c> is any map. It follows that <c>M1 .. M4</c> are maps as well. + </p> + <p> + More <em>Examples:</em> + </p> +<pre> +1> <input>M = #{1 => a}.</input> +#{1 => a } +2> <input>M#{1.0 => b}.</input> +#{1 => a, 1.0 => b}. +3> <input>M#{1 := b}.</input> +#{1 => b} +4> <input>M#{1.0 := b}.</input> +** exception error: bad argument +</pre> + <p> + As in construction, the order in which the key and value expressions + are evaluated is not defined. The + syntactic order of the key-value pairs in the update is of no + relevance, except in the case where two keys match. + In that case, the latter value is used. + </p> + </section> + + <section> + <title>Maps in Patterns</title> + <p> + Matching of key-value associations from maps is done as follows: + </p> + + <code>#{ K := V } = M</code> + <p> + Here <c>M</c> is any map. The key <c>K</c> must be an expression with bound + variables or literals. <c>V</c> can be any pattern with either bound or + unbound variables. + </p> + <p> + If the variable <c>V</c> is unbound, it becomes bound to the value associated + with the key <c>K</c>, which must exist in the map <c>M</c>. If the variable + <c>V</c> is bound, it must match the value associated with <c>K</c> in <c>M</c>. + </p> + <p><em>Example:</em></p> +<pre> +1> <input>M = #{"tuple" => {1,2}}.</input> +#{"tuple" => {1,2}} +2> <input>#{"tuple" := {1,B}} = M.</input> +#{"tuple" => {1,2}} +3> <input>B.</input> +2.</pre> + <p> + This binds variable <c>B</c> to integer <c>2</c>. + </p> + <p> + Similarly, multiple values from the map can be matched: + </p> + <code>#{ K1 := V1, .., Kn := Vn } = M</code> + <p> + Here keys <c>K1 .. Kn</c> are any expressions with literals or bound variables. If all + keys exist in map <c>M</c>, all variables in <c>V1 .. Vn</c> is matched to the + associated values of their respective keys. + </p> + <p> + If the matching conditions are not met, the match fails, either with: + </p> + <list> + <item><p>A <c>badmatch</c> exception.</p> + <p>This is if it is used in the context of the match operator + as in the example.</p> + </item> + <item><p>Or resulting in the next clause being tested in function heads and + case expressions.</p> + </item> + </list> + <p> + Matching in maps only allows for <c>:=</c> as delimiters of associations. + </p> + <p> + The order in which keys are declared in matching has no relevance. + </p> + <p> + Duplicate keys are allowed in matching and match each pattern associated + to the keys: + </p> + <code>#{ K := V1, K := V2 } = M</code> + <p> + Matching an expression against an empty map literal, matches its type but + no variables are bound: + </p> + <code>#{} = Expr</code> + <p> + This expression matches if the expression <c>Expr</c> is of type map, otherwise + it fails with an exception <c>badmatch</c>. + </p> + <section> + <title>Matching Syntax</title> + <p> + Matching of literals as keys are allowed in function heads: + </p> + <code> +%% only start if not_started +handle_call(start, From, #{ state := not_started } = S) -> +... + {reply, ok, S#{ state := start }}; + +%% only change if started +handle_call(change, From, #{ state := start } = S) -> +... + {reply, ok, S#{ state := changed }};</code> + </section> + </section> + <section> + <title>Maps in Guards</title> + <p> + Maps are allowed in guards as long as all subexpressions are valid guard expressions. + </p> + <p> + Two guard BIFs handle maps: + </p> + <list> + <item> + <seealso marker="erts:erlang#is_map/1">is_map/1</seealso> + in the <c>erlang</c> module + </item> + <item> + <seealso marker="erts:erlang#map_size/1">map_size/1</seealso> + in the <c>erlang</c> module + </item> + </list> + </section> + </section> + + <section> <marker id="bit_syntax"></marker> <title>Bit Syntax Expressions</title> <code type="none"><![CDATA[<<>> @@ -805,29 +1083,34 @@ Ei = Value | Value/TypeSpecifierList | Value:Size/TypeSpecifierList</pre> <p>Used in a bit string construction, <c>Value</c> is an expression - which should evaluate to an integer, float or bit string. If the - expression is something else than a single literal or variable, it - should be enclosed in parenthesis.</p> + that is to evaluate to an integer, float, or bit string. If the + expression is not a single literal or variable, it + is to be enclosed in parentheses.</p> <p>Used in a bit string matching, <c>Value</c> must be a variable, - or an integer, float or string.</p> + or an integer, float, or string.</p> - <p>Note that, for example, using a string literal as in + <p>Notice that, for example, using a string literal as in <c><![CDATA[<<"abc">>]]></c> is syntactic sugar for <c><![CDATA[<<$a,$b,$c>>]]></c>.</p> <p>Used in a bit string construction, <c>Size</c> is an expression - which should evaluate to an integer.</p> + that is to evaluate to an integer.</p> - <p>Used in a bit string matching, <c>Size</c> must be an integer or a + <p>Used in a bit string matching, <c>Size</c> must be an integer, or a variable bound to an integer.</p> <p>The value of <c>Size</c> specifies the size of the segment in units (see below). The default value depends on the type (see - below). For <c>integer</c> it is 8, for - <c>float</c> it is 64, for <c>binary</c> and <c>bitstring</c> it is - the whole binary or bit string. In matching, this default value is only - valid for the very last element. All other bit string or binary + below):</p> + <list type="bulleted"> + <item>For <c>integer</c> it is 8.</item> + <item>For <c>float</c> it is 64.</item> + <item>For <c>binary</c> and <c>bitstring</c> it is + the whole binary or bit string.</item> + </list> + <p>In matching, this default value is only + valid for the last element. All other bit string or binary elements in the matching must have a size specification.</p> <p>For the <c>utf8</c>, <c>utf16</c>, and <c>utf32</c> types, @@ -851,7 +1134,7 @@ Ei = Value | The default is <c>unsigned</c>.</item> <tag><c>Endianness</c>= <c>big</c> | <c>little</c> | <c>native</c></tag> - <item>Native-endian means that the endianness will be resolved at load + <item>Native-endian means that the endianness is resolved at load time to be either big-endian or little-endian, depending on what is native for the CPU that the Erlang machine is run on. Endianness only matters when the Type is either <c>integer</c>, @@ -860,7 +1143,7 @@ Ei = Value | <tag><c>Unit</c>= <c>unit:IntegerLiteral</c></tag> <item>The allowed range is 1..256. Defaults to 1 for <c>integer</c>, - <c>float</c> and <c>bitstring</c>, and to 8 for <c>binary</c>. + <c>float</c>, and <c>bitstring</c>, and to 8 for <c>binary</c>. No unit specifier must be given for the types <c>utf8</c>, <c>utf16</c>, and <c>utf32</c>. </item> @@ -871,8 +1154,8 @@ Ei = Value | <note><p>When constructing binaries, if the size <c>N</c> of an integer segment is too small to contain the given integer, the most significant - bits of the integer will be silently discarded and only the <c>N</c> least - significant bits will be put into the binary.</p></note> + bits of the integer are silently discarded and only the <c>N</c> least + significant bits are put into the binary.</p></note> <p>The types <c>utf8</c>, <c>utf16</c>, and <c>utf32</c> specifies encoding/decoding of the <em>Unicode Transformation Format</em>s UTF-8, UTF-16, @@ -881,39 +1164,39 @@ Ei = Value | <p>When constructing a segment of a <c>utf</c> type, <c>Value</c> must be an integer in the range 0..16#D7FF or 16#E000....16#10FFFF. Construction - will fail with a <c>badarg</c> exception if <c>Value</c> is + fails with a <c>badarg</c> exception if <c>Value</c> is outside the allowed ranges. The size of the resulting binary - segment depends on the type and/or <c>Value</c>. For <c>utf8</c>, - <c>Value</c> will be encoded in 1 through 4 bytes. For - <c>utf16</c>, <c>Value</c> will be encoded in 2 or 4 - bytes. Finally, for <c>utf32</c>, <c>Value</c> will always be - encoded in 4 bytes.</p> + segment depends on the type or <c>Value</c>, or both:</p> + <list type="bulleted"> + <item>For <c>utf8</c>, <c>Value</c> is encoded in 1-4 bytes.</item> + <item>For <c>utf16</c>, <c>Value</c> is encoded in 2 or 4 bytes.</item> + <item>For <c>utf32</c>, <c>Value</c> is always be encoded in 4 bytes.</item> + </list> - <p>When constructing, a literal string may be given followed + <p>When constructing, a literal string can be given followed by one of the UTF types, for example: <c><![CDATA[<<"abc"/utf8>>]]></c> - which is syntatic sugar for + which is syntactic sugar for <c><![CDATA[<<$a/utf8,$b/utf8,$c/utf8>>]]></c>.</p> - <p>A successful match of a segment of a <c>utf</c> type results + <p>A successful match of a segment of a <c>utf</c> type, results in an integer in the range 0..16#D7FF or 16#E000..16#10FFFF. - The match will fail if returned value - would fall outside those ranges.</p> + The match fails if the returned value falls outside those ranges.</p> - <p>A segment of type <c>utf8</c> will match 1 to 4 bytes in the binary, + <p>A segment of type <c>utf8</c> matches 1-4 bytes in the binary, if the binary at the match position contains a valid UTF-8 sequence. (See RFC-3629 or the Unicode standard.)</p> - <p>A segment of type <c>utf16</c> may match 2 or 4 bytes in the binary. - The match will fail if the binary at the match position does not contain + <p>A segment of type <c>utf16</c> can match 2 or 4 bytes in the binary. + The match fails if the binary at the match position does not contain a legal UTF-16 encoding of a Unicode code point. (See RFC-2781 or the Unicode standard.)</p> - <p>A segment of type <c>utf32</c> may match 4 bytes in the binary in the - same way as an <c>integer</c> segment matching 32 bits. - The match will fail if the resulting integer is outside the legal ranges + <p>A segment of type <c>utf32</c> can match 4 bytes in the binary in the + same way as an <c>integer</c> segment matches 32 bits. + The match fails if the resulting integer is outside the legal ranges mentioned above.</p> - <p>Examples:</p> + <p><em>Examples:</em></p> <pre> 1> <input>Bin1 = <<1,17,42>>.</input> <<1,17,42>> @@ -942,11 +1225,13 @@ Ei = Value | 13> <input><<1024/utf8>>.</input> <<208,128>> </pre> - <p>Note that bit string patterns cannot be nested.</p> - <p>Note also that "<c><![CDATA[B=<<1>>]]></c>" is interpreted as + <p>Notice that bit string patterns cannot be nested.</p> + <p>Notice also that "<c><![CDATA[B=<<1>>]]></c>" is interpreted as "<c><![CDATA[B =<<1>>]]></c>" which is a syntax error. The correct way is to write a space after '=': "<c><![CDATA[B= <<1>>]]></c>.</p> - <p>More examples can be found in <em>Programming Examples</em>.</p> + <p>More examples are provided in + <seealso marker="doc/programming_examples:bit_syntax"> + Programming Examples</seealso>.</p> </section> <section> @@ -954,22 +1239,23 @@ Ei = Value | <title>Fun Expressions</title> <pre> fun - (Pattern11,...,Pattern1N) [when GuardSeq1] -> - Body1; + [Name](Pattern11,...,Pattern1N) [when GuardSeq1] -> + Body1; ...; - (PatternK1,...,PatternKN) [when GuardSeqK] -> - BodyK + [Name](PatternK1,...,PatternKN) [when GuardSeqK] -> + BodyK end</pre> <p>A fun expression begins with the keyword <c>fun</c> and ends - with the keyword <c>end</c>. Between them should be a function + with the keyword <c>end</c>. Between them is to be a function declaration, similar to a - <seealso marker="functions#syntax">regular function declaration</seealso>, except that no function name is - specified.</p> - <p>Variables in a fun head shadow variables in the - function clause surrounding the fun expression, and - variables bound in a fun body are local to the fun body.</p> + <seealso marker="functions#syntax">regular function declaration</seealso>, + except that the function name is optional and is to be a variable, if + any.</p> + <p>Variables in a fun head shadow the function name and both shadow + variables in the function clause surrounding the fun expression. + Variables bound in a fun body are local to the fun body.</p> <p>The return value of the expression is the resulting fun.</p> - <p>Examples:</p> + <p><em>Examples:</em></p> <pre> 1> <input>Fun1 = fun (X) -> X+1 end.</input> #Fun<erl_eval.6.39074546> @@ -978,7 +1264,11 @@ end</pre> 3> <input>Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end.</input> #Fun<erl_eval.6.39074546> 4> <input>Fun2(7).</input> -gt</pre> +gt +5> <input>Fun3 = fun Fact(1) -> 1; Fact(X) when X > 1 -> X * Fact(X - 1) end.</input> +#Fun<erl_eval.6.39074546> +6> <input>Fun3(4).</input> +24</pre> <p>The following fun expressions are also allowed:</p> <pre> fun Name/Arity @@ -988,15 +1278,17 @@ fun Module:Name/Arity</pre> syntactic sugar for:</p> <pre> fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end</pre> - <p>In <c>Module:Name/Arity</c>, <c>Module</c> and <c>Name</c> are atoms - and <c>Arity</c> is an integer. Starting from the R15 release, - <c>Module</c>, <c>Name</c>, and <c>Arity</c> may also be variables. - A fun defined in this way will refer to the function <c>Name</c> + <p>In <c>Module:Name/Arity</c>, <c>Module</c>, and <c>Name</c> are atoms + and <c>Arity</c> is an integer. Starting from Erlang/OTP R15, + <c>Module</c>, <c>Name</c>, and <c>Arity</c> can also be variables. + A fun defined in this way refers to the function <c>Name</c> with arity <c>Arity</c> in the <em>latest</em> version of module - <c>Module</c>. A fun defined in this way will not be dependent on - the code for module in which it is defined. + <c>Module</c>. A fun defined in this way is not dependent on + the code for the module in which it is defined. </p> - <p>More examples can be found in <em>Programming Examples</em>.</p> + <p>More examples are provided in + <seealso marker="doc/programming_examples:funs"> + Programming Examples</seealso>.</p> </section> <section> @@ -1006,38 +1298,42 @@ fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end</pre> catch Expr</code> <p>Returns the value of <c>Expr</c> unless an exception occurs during the evaluation. In that case, the exception is - caught. For exceptions of class <c>error</c>, - that is run-time errors: <c>{'EXIT',{Reason,Stack}}</c> - is returned. For exceptions of class <c>exit</c>, that is - the code called <c>exit(Term)</c>: <c>{'EXIT',Term}</c> is returned. - For exceptions of class <c>throw</c>, that is - the code called <c>throw(Term)</c>: <c>Term</c> is returned.</p> + caught.</p> + <p>For exceptions of class <c>error</c>, that is, + run-time errors, + <c>{'EXIT',{Reason,Stack}}</c> is returned.</p> + <p>For exceptions of class <c>exit</c>, that is, + the code called <c>exit(Term)</c>, + <c>{'EXIT',Term}</c> is returned.</p> + <p>For exceptions of class <c>throw</c>, that is + the code called <c>throw(Term)</c>, + <c>Term</c> is returned.</p> <p><c>Reason</c> depends on the type of error that occurred, and <c>Stack</c> is the stack of recent function calls, see - <seealso marker="errors#exit_reasons">Errors and Error Handling</seealso>.</p> - <p>Examples:</p> - <p></p> + <seealso marker="errors#exit_reasons">Exit Reasons</seealso>.</p> + <p><em>Examples:</em></p> <pre> 1> <input>catch 1+2.</input> 3 2> <input>catch 1+a.</input> {'EXIT',{badarith,[...]}}</pre> - <p>Note that <c>catch</c> has low precedence and catch + <p>Notice that <c>catch</c> has low precedence and catch subexpressions often needs to be enclosed in a block - expression or in parenthesis:</p> + expression or in parentheses:</p> <pre> 3> <input>A = catch 1+2.</input> ** 1: syntax error before: 'catch' ** 4> <input>A = (catch 1+2).</input> 3</pre> <p>The BIF <c>throw(Any)</c> can be used for non-local return from - a function. It must be evaluated within a <c>catch</c>, which will - return the value <c>Any</c>. Example:</p> + a function. It must be evaluated within a <c>catch</c>, which + returns the value <c>Any</c>.</p> + <p><em>Example:</em></p> <pre> 5> <input>catch throw(hello).</input> hello</pre> <p>If <c>throw/1</c> is not evaluated within a catch, a - <c>nocatch</c> run-time error will occur.</p> + <c>nocatch</c> run-time error occurs.</p> </section> <section> @@ -1053,14 +1349,17 @@ catch end</code> <p>This is an enhancement of <seealso marker="#catch">catch</seealso> that appeared in - Erlang 5.4/OTP-R10B. It gives the possibility do distinguish - between different exception classes, and to choose to handle only - the desired ones, passing the others on to an enclosing - <c>try</c> or <c>catch</c> or to default error handling.</p> - <p>Note that although the keyword <c>catch</c> is used in + Erlang 5.4/OTP R10B. It gives the possibility to:</p> + <list type="bulleted"> + <item>Distinguish between different exception classes.</item> + <item>Choose to handle only the desired ones.</item> + <item>Passing the others on to an enclosing + <c>try</c> or <c>catch</c>, or to default error handling.</item> + </list> + <p>Notice that although the keyword <c>catch</c> is used in the <c>try</c> expression, there is not a <c>catch</c> expression within the <c>try</c> expression.</p> - <p>Returns the value of <c>Exprs</c> (a sequence of expressions + <p>It returns the value of <c>Exprs</c> (a sequence of expressions <c>Expr1, ..., ExprN</c>) unless an exception occurs during the evaluation. In that case the exception is caught and the patterns <c>ExceptionPattern</c> with the right exception @@ -1074,7 +1373,7 @@ end</code> <c>Class</c> with a true guard sequence, the exception is passed on as if <c>Exprs</c> had not been enclosed in a <c>try</c> expression.</p> - <p>If an exception occurs during evaluation of <c>ExceptionBody</c> + <p>If an exception occurs during evaluation of <c>ExceptionBody</c>, it is not caught.</p> <p>The <c>try</c> expression can have an <c>of</c> section: @@ -1097,7 +1396,7 @@ end</code> the patterns <c>Pattern</c> are sequentially matched against the result in the same way as for a <seealso marker="#case">case</seealso> expression, except that if - the matching fails, a <c>try_clause</c> run-time error will occur.</p> + the matching fails, a <c>try_clause</c> run-time error occurs.</p> <p>An exception occurring during the evaluation of <c>Body</c> is not caught.</p> <p>The <c>try</c> expression can also be augmented with an @@ -1120,7 +1419,7 @@ after AfterBody end</code> <p><c>AfterBody</c> is evaluated after either <c>Body</c> or - <c>ExceptionBody</c> no matter which one. The evaluated value of + <c>ExceptionBody</c>, no matter which one. The evaluated value of <c>AfterBody</c> is lost; the return value of the <c>try</c> expression is the same with an <c>after</c> section as without.</p> <p>Even if an exception occurs during evaluation of <c>Body</c> or @@ -1129,13 +1428,13 @@ end</code> evaluated, so the exception from the <c>try</c> expression is the same with an <c>after</c> section as without.</p> <p>If an exception occurs during evaluation of <c>AfterBody</c> - itself it is not caught, so if <c>AfterBody</c> is evaluated after - an exception in <c>Exprs</c>, <c>Body</c> or <c>ExceptionBody</c>, + itself, it is not caught. So if <c>AfterBody</c> is evaluated after + an exception in <c>Exprs</c>, <c>Body</c>, or <c>ExceptionBody</c>, that exception is lost and masked by the exception in <c>AfterBody</c>.</p> - <p>The <c>of</c>, <c>catch</c> and <c>after</c> sections are all + <p>The <c>of</c>, <c>catch</c>, and <c>after</c> sections are all optional, as long as there is at least a <c>catch</c> or an - <c>after</c> section, so the following are valid <c>try</c> + <c>after</c> section. So the following are valid <c>try</c> expressions:</p> <code type="none"> try Exprs of @@ -1154,9 +1453,9 @@ after end try Exprs after AfterBody end</code> - <p>Example of using <c>after</c>, this code will close the file + <p>Next is an example of using <c>after</c>. This closes the file, even in the event of exceptions in <c>file:read/2</c> or in - <c>binary_to_term/1</c>, and exceptions will be the same as + <c>binary_to_term/1</c>. The exceptions are the same as without the <c>try</c>...<c>after</c>...<c>end</c> expression:</p> <code type="none"> termize_file(Name) -> @@ -1167,7 +1466,7 @@ termize_file(Name) -> after file:close(F) end.</code> - <p>Example: Using <c>try</c> to emulate <c>catch Expr</c>.</p> + <p>Next is an example of using <c>try</c> to emulate <c>catch Expr</c>:</p> <code type="none"> try Expr catch @@ -1183,7 +1482,7 @@ end</code> (Expr)</pre> <p>Parenthesized expressions are useful to override <seealso marker="#prec">operator precedences</seealso>, - for example in arithmetic expressions:</p> + for example, in arithmetic expressions:</p> <pre> 1> <input>1 + 2 * 3.</input> 7 @@ -1207,7 +1506,7 @@ end</pre> <section> <marker id="lcs"></marker> <title>List Comprehensions</title> - <p>List comprehensions are a feature of many modern functional + <p>List comprehensions is a feature of many modern functional programming languages. Subject to certain rules, they provide a succinct notation for generating elements in a list.</p> <p>List comprehensions are analogous to set comprehensions in @@ -1217,32 +1516,34 @@ end</pre> <p>List comprehensions are written with the following syntax:</p> <pre> [Expr || Qualifier1,...,QualifierN]</pre> - <p><c>Expr</c> is an arbitrary expression, and each + <p>Here, <c>Expr</c> is an arbitrary expression, and each <c>Qualifier</c> is either a generator or a filter.</p> <list type="bulleted"> <item>A <em>generator</em> is written as: <br></br> <c><![CDATA[Pattern <- ListExpr]]></c>. <br></br> -<c>ListExpr</c> must be an expression which evaluates to a +<c>ListExpr</c> must be an expression, which evaluates to a list of terms.</item> <item>A <em>bit string generator</em> is written as: <br></br> <c><![CDATA[BitstringPattern <= BitStringExpr]]></c>. <br></br> -<c>BitStringExpr</c> must be an expression which evaluates to a +<c>BitStringExpr</c> must be an expression, which evaluates to a bitstring.</item> - <item>A <em>filter</em> is an expression which evaluates to + <item>A <em>filter</em> is an expression, which evaluates to <c>true</c> or <c>false</c>.</item> </list> - <p>The variables in the generator patterns shadow variables in the function - clause surrounding the list comprehensions.</p> <p>A list comprehension + <p>The variables in the generator patterns, shadow variables in the function + clause, surrounding the list comprehensions.</p> <p>A list comprehension returns a list, where the elements are the result of evaluating <c>Expr</c> for each combination of generator list elements and bit string generator - elements for which all filters are true.</p> <p></p> <p>Example:</p> + elements, for which all filters are true.</p> + <p><em>Example:</em></p> <pre> 1> <input>[X*2 || X <- [1,2,3]].</input> [2,4,6]</pre> - <p>More examples can be found in <em>Programming Examples</em>.</p> - + <p>More examples are provoded in + <seealso marker="doc/programming_examples:list_comprehensions"> + Programming Examples.</seealso></p> </section> @@ -1255,35 +1556,38 @@ end</pre> <p>Bit string comprehensions are written with the following syntax:</p> <pre> -<< BitString || Qualifier1,...,QualifierN >></pre> - <p><c>BitString</c> is a bit string expression, and each - <c>Qualifier</c> is either a generator, a bit string generator or a filter.</p> +<< BitStringExpr || Qualifier1,...,QualifierN >></pre> + <p><c>BitStringExpr</c> is an expression that evalutes to a bit + string. If <c>BitStringExpr</c> is a function call, it must be + enclosed in parentheses. Each <c>Qualifier</c> is either a + generator, a bit string generator or a filter.</p> <list type="bulleted"> <item>A <em>generator</em> is written as: <br></br> <c><![CDATA[Pattern <- ListExpr]]></c>. <br></br> - <c>ListExpr</c> must be an expression which evaluates to a + <c>ListExpr</c> must be an expression that evaluates to a list of terms.</item> <item>A <em>bit string generator</em> is written as: <br></br> <c><![CDATA[BitstringPattern <= BitStringExpr]]></c>. <br></br> -<c>BitStringExpr</c> must be an expression which evaluates to a +<c>BitStringExpr</c> must be an expression that evaluates to a bitstring.</item> - <item>A <em>filter</em> is an expression which evaluates to + <item>A <em>filter</em> is an expression that evaluates to <c>true</c> or <c>false</c>.</item> </list> - <p>The variables in the generator patterns shadow variables in - the function clause surrounding the bit string comprehensions.</p> + <p>The variables in the generator patterns, shadow variables in + the function clause, surrounding the bit string comprehensions.</p> <p>A bit string comprehension returns a bit string, which is created by concatenating the results of evaluating <c>BitString</c> - for each combination of bit string generator elements for which all + for each combination of bit string generator elements, for which all filters are true.</p> - <p></p> - <p>Example:</p> + <p><em>Example:</em></p> <pre> -1> <input><< << (X*2) >> || +1> <input><< << (X*2) >> || <<X>> <= << 1,2,3 >> >>.</input> <<2,4,6>></pre> - <p>More examples can be found in <em>Programming Examples</em>.</p> + <p>More examples are provided in + <seealso marker="doc/programming_examples:bit_syntax"> + Programming Examples.</seealso></p> </section> <section> @@ -1292,27 +1596,27 @@ end</pre> <p>A <em>guard sequence</em> is a sequence of guards, separated by semicolon (;). The guard sequence is true if at least one of - the guards is true. (The remaining guards, if any, will not be - evaluated.)<br></br> -<c>Guard1;...;GuardK</c></p> + the guards is true. (The remaining guards, if any, are not + evaluated.)</p> + <p><c>Guard1;...;GuardK</c></p> <p>A <em>guard</em> is a sequence of guard expressions, separated by comma (,). The guard is true if all guard expressions - evaluate to <c>true</c>.<br></br> -<c>GuardExpr1,...,GuardExprN</c></p> + evaluate to <c>true</c>.</p> + <p><c>GuardExpr1,...,GuardExprN</c></p> <p>The set of valid <em>guard expressions</em> (sometimes called guard tests) is a subset of the set of valid Erlang expressions. The reason for restricting the set of valid expressions is that evaluation of a guard expression must be guaranteed to be free - of side effects. Valid guard expressions are:</p> + of side effects. Valid guard expressions are the following:</p> <list type="bulleted"> - <item>the atom <c>true</c>,</item> - <item>other constants (terms and bound variables), all regarded - as false,</item> - <item>calls to the BIFs specified below,</item> - <item>term comparisons,</item> - <item>arithmetic expressions,</item> - <item>boolean expressions, and</item> - <item>short-circuit expressions (<c>andalso</c>/<c>orelse</c>).</item> + <item>The atom <c>true</c></item> + <item>Other constants (terms and bound variables), all regarded + as false</item> + <item>Calls to the BIFs specified in table <c>Type Test BIFs</c></item> + <item>Term comparisons</item> + <item>Arithmetic expressions</item> + <item>Boolean expressions</item> + <item>Short-circuit expressions (<c>andalso</c>/<c>orelse</c>)</item> </list> <table> <row> @@ -1343,6 +1647,9 @@ end</pre> <cell align="left" valign="middle"><c>is_list/1</c></cell> </row> <row> + <cell align="left" valign="middle"><c>is_map/1</c></cell> + </row> + <row> <cell align="left" valign="middle"><c>is_number/1</c></cell> </row> <row> @@ -1363,13 +1670,13 @@ end</pre> <row> <cell align="left" valign="middle"><c>is_tuple/1</c></cell> </row> - <tcaption>Type Test BIFs.</tcaption> + <tcaption>Type Test BIFs</tcaption> </table> - <p>Note that most type test BIFs have older equivalents, without + <p>Notice that most type test BIFs have older equivalents, without the <c>is_</c> prefix. These old BIFs are retained for backwards - compatibility only and should not be used in new code. They are + compatibility only and are not to be used in new code. They are also only allowed at top level. For example, they are not allowed - in boolean expressions in guards.</p> + in Boolean expressions in guards.</p> <table> <row> <cell align="left" valign="middle"><c>abs(Number)</c></cell> @@ -1393,6 +1700,9 @@ end</pre> <cell align="left" valign="middle"><c>length(List)</c></cell> </row> <row> + <cell align="left" valign="middle"><c>map_size(Map)</c></cell> + </row> + <row> <cell align="left" valign="middle"><c>node()</c></cell> </row> <row> @@ -1416,14 +1726,14 @@ end</pre> <row> <cell align="left" valign="middle"><c>tuple_size(Tuple)</c></cell> </row> - <tcaption>Other BIFs Allowed in Guard Expressions.</tcaption> + <tcaption>Other BIFs Allowed in Guard Expressions</tcaption> </table> - <p>If an arithmetic expression, a boolean expression, a + <p>If an arithmetic expression, a Boolean expression, a short-circuit expression, or a call to a guard BIF fails (because of invalid arguments), the entire guard fails. If the guard was part of a guard sequence, the next guard in the sequence (that is, - the guard following the next semicolon) will be evaluated.</p> + the guard following the next semicolon) is evaluated.</p> </section> @@ -1476,12 +1786,13 @@ end</pre> <cell align="left" valign="middle">catch</cell> <cell align="left" valign="middle"> </cell> </row> - <tcaption>Operator Precedence.</tcaption> + <tcaption>Operator Precedence</tcaption> </table> <p>When evaluating an expression, the operator with the highest priority is evaluated first. Operators with the same priority - are evaluated according to their associativity. Example: - The left associative arithmetic operators are evaluated left to + are evaluated according to their associativity.</p> + <p><em>Example:</em></p> + <p>The left associative arithmetic operators are evaluated left to right:</p> <pre> <input>6 + 5 * 4 - 3 / 2</input> evaluates to |