diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /system/doc/reference_manual/expressions.xml | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'system/doc/reference_manual/expressions.xml')
-rw-r--r-- | system/doc/reference_manual/expressions.xml | 1422 |
1 files changed, 1422 insertions, 0 deletions
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml new file mode 100644 index 0000000000..fa7870d96c --- /dev/null +++ b/system/doc/reference_manual/expressions.xml @@ -0,0 +1,1422 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2003</year><year>2009</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. + + </legalnotice> + + <title>Expressions</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>expressions.xml</file> + </header> + <p>In this chapter, 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> + + <section> + <title>Expression Evaluation</title> + <p>All subexpressions are evaluated before an expression itself is + evaluated, unless explicitly stated otherwise. For example, + consider the expression:</p> + <code type="none"> +Expr1 + Expr2</code> + <p><c>Expr1</c> and <c>Expr2</c>, which are also expressions, are + evaluated first - in any order - before the addition is + 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> + </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. + The return value is the term itself.</p> + </section> + + <section> + <title>Variables</title> + <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> + <pre> +X +Name1 +PhoneNumber +Phone_number +_ +_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 + 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> + <pre> +[H|_] = [1,2,3]</pre> + <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> + <pre> +member(_, []) -> + [].</pre> + <p>can be rewritten to be more readable:</p> + <pre> +member(Elem, []) -> + [].</pre> + <p>This will however cause 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> + <pre> +{_,_} = {1,2}</pre> + <p>But this will fail:</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> + <p>For the <c>try</c> expression introduced in + 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> + </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> + <pre> +Name1 +[H|T] +{error,Reason}</pre> + <p>Patterns are allowed in clause heads, <c>case</c> and + <c>receive</c> expressions, and match expressions.</p> + + <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> + <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> + <pre> +f({connect,From,To,Number,Options}, To) -> + Signal = {connect,From,To,Number,Options}, + ...; +f(Signal, To) -> + ignore.</pre> + <p>can instead be written as</p> + <pre> +f({connect,_,To,_,_} = Signal, To) -> + ...; +f(Signal, To) -> + ignore.</pre> + </section> + + <section> + <title>String Prefix in Patterns</title> + <p>When matching strings, the following is a valid pattern:</p> + <pre> +f("prefix" ++ Str) -> ...</pre> + <p>This is syntactic sugar for the equivalent, but harder to + 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> + <pre> +case {Value, Result} of + {?THRESHOLD+1, ok} -> ...</pre> + <p>This feature was added in Erlang 5.0/OTP R7.</p> + </section> + </section> + + <section> + <title>Match</title> + <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 + 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> + <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> + </section> + + <section> + <marker id="calls"></marker> + <title>Function Calls</title> + <pre> +ExprF(Expr1,...,ExprN) +ExprM:ExprF(Expr1,...,ExprN)</pre> + <p>In the first form of function calls, + <c>ExprM:ExprF(Expr1,...,ExprN)</c>, each of <c>ExprM</c> and + <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> + <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 + using the <em>implicitly qualified function name</em>. If + <c>ExprF/N</c> is the name of a function explicitly or + automatically imported from module <c>M</c>, then the call is + short for <c>M:ExprF(Expr1,...,ExprN)</c>. Otherwise, + <c>ExprF/N</c> must be a locally defined function. Examples:</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 + +Fun2 = {lists,append} +Fun2([1,2], [3,4]) +=> [1,2,3,4] + +fun lists:append/2([1,2], [3,4]) +=> [1,2,3,4]</code> + <p>To avoid possible ambiguities, the fully qualified function + name must be used when calling a function with the same name as + a BIF, and the compiler does not allow defining a function with + the same name as an explicitly imported function.</p> + <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> + </section> + + <section> + <title>If</title> + <pre> +if + GuardSeq1 -> + Body1; + ...; + GuardSeqN -> + 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 + 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 + used in the last branch, as that guard sequence is always true.</p> + <p>Example:</p> + <pre> +is_greater_than(X, Y) -> + if + X>Y -> + true; + true -> % works as an 'else' branch + false + end</pre> + </section> + + <section> + <marker id="case"></marker> + <title>Case</title> + <pre> +case Expr of + Pattern1 [when GuardSeq1] -> + Body1; + ...; + PatternN [when GuardSeqN] -> + BodyN +end</pre> + <p>The expression <c>Expr</c> is evaluated and the patterns + <c>Pattern</c> are sequentially matched against the result. If a + match succeeds and the optional guard sequence <c>GuardSeq</c> is + true, the corresponding <c>Body</c> is evaluated.</p> + <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> + <pre> +is_valid_signal(Signal) -> + case Signal of + {signal, _What, _From, _To} -> + true; + {signal, _What, _To} -> + true; + _Else -> + false + end.</pre> + </section> + + <section> + <marker id="send"></marker> + <title>Send</title> + <pre> +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> + <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> + <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> + evaluates to a tuple <c>{Name,Node}</c> (or a pid located at + another node), also never fails.</item> + </list> + </section> + + <section> + <marker id="receive"></marker> + <title>Receive</title> + <pre> +receive + Pattern1 [when GuardSeq1] -> + Body1; + ...; + PatternN [when GuardSeqN] -> + BodyN +end</pre> + <p>Receives messages sent to the process using the send operator + (!). The patterns <c>Pattern</c> are sequentially matched + against the first message in time order in the mailbox, then + 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 + 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 + the patterns and with a true guard sequence. </p> + <p>Example:</p> + <pre> +wait_for_onhook() -> + receive + onhook -> + disconnect(), + idle(); + {connect, B} -> + B ! {busy, self()}, + wait_for_onhook() + end.</pre> + <p>It is possible to augment the <c>receive</c> expression with a + timeout:</p> + <pre> +receive + Pattern1 [when GuardSeq1] -> + Body1; + ...; + PatternN [when GuardSeqN] -> + BodyN +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. + <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> + <pre> +wait_for_onhook() -> + receive + onhook -> + disconnect(), + idle(); + {connect, B} -> + B ! {busy, self()}, + wait_for_onhook() + after + 60000 -> + disconnect(), + error() + end.</pre> + <p>It is legal to use a <c>receive..after</c> expression with no + branches:</p> + <pre> +receive +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 + used to implement simple timers.</p> + <p>Example:</p> + <pre> +timer() -> + spawn(m, timer, [self()]). + +timer(Pid) -> + receive + after + 5000 -> + Pid ! timeout + end.</pre> + <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> + <tag>0</tag> + <item>If there is no matching message in the mailbox, the timeout + will occur immediately.</item> + </taglist> + </section> + + <section> + <title>Term Comparisons</title> + <pre> +Expr1 <input>op</input> Expr2</pre> + <table> + <row> + <cell align="left" valign="middle"><em>op</em></cell> + <cell align="left" valign="middle"><em>Description</em></cell> + </row> + <row> + <cell align="left" valign="middle">==</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> + </row> + <row> + <cell align="left" valign="middle">=<</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> + </row> + <row> + <cell align="left" valign="middle">>=</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> + </row> + <row> + <cell align="left" valign="middle">=:=</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> + </row> + <tcaption>Term Comparison Operators.</tcaption> + </table> + <p>The arguments may be of different data types. The following + order is defined:</p> + <pre> +number < atom < reference < fun < port < pid < tuple < 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>If one of the compared terms is an integer and the other a + float, the integer is first converted into a float, unless the + operator is one of =:= and =/=. If the integer is too big to fit + in a float no conversion is done, but the order is determined by + inspecting the sign of the numbers.</p> + <p>Returns the Boolean value of the expression, <c>true</c> or + <c>false</c>.</p> + <p>Examples:</p> + <pre> +1> <input>1==1.0.</input> +true +2> <input>1=:=1.0.</input> +false +3> <input>1 > a.</input> +false</pre> + </section> + + <section> + <title>Arithmetic Expressions</title> + <pre> +<input>op</input> Expr +Expr1 <input>op</input> Expr2</pre> + <table> + <row> + <cell align="left" valign="middle"><em>op</em></cell> + <cell align="left" valign="middle"><em>Description</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> + </row> + <row> + <cell align="left" valign="middle">-</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"> </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> + </row> + <row> + <cell align="left" valign="middle">*</cell> + <cell align="left" valign="middle"> </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> + </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> + </row> + <row> + <cell align="left" valign="middle">div</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> + </row> + <row> + <cell align="left" valign="middle">band</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> + </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> + </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> + </row> + <row> + <cell align="left" valign="middle">bsr</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> + <pre> +1> <input>+1.</input> +1 +2> <input>-1.</input> +-1 +3> <input>1+1.</input> +2 +4> <input>4/2.</input> +2.0 +5> <input>5 div 2.</input> +2 +6> <input>5 rem 2.</input> +1 +7> <input>2#10 band 2#01.</input> +0 +8> <input>2#10 bor 2#01.</input> +3 +9> <input>a + 10.</input> +** exception error: bad argument in an arithmetic expression + in operator +/2 + called as a + 10 +10> <input>1 bsl (1 bsl 64).</input> +** exception error: a system limit has been reached + in operator bsl/2 + called as 1 bsl 18446744073709551616</pre> + </section> + + <section> + <title>Boolean Expressions</title> + <pre> +<input>op</input> Expr +Expr1 <input>op</input> Expr2</pre> + <table> + <row> + <cell align="left" valign="middle"><em>op</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> + </row> + <row> + <cell align="left" valign="middle">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> + </row> + <row> + <cell align="left" valign="middle">xor</cell> + <cell align="left" valign="middle">logical xor</cell> + </row> + <tcaption>Logical Operators.</tcaption> + </table> + <p>Examples:</p> + <pre> +1> <input>not true.</input> +false +2> <input>true and false.</input> +false +3> <input>true xor false.</input> +true +4> <input>true or garbage.</input> +** exception error: bad argument + in operator or/2 + called as true or garbage</pre> + </section> + + <section> + <title>Short-Circuit Expressions</title> + <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, + <c>true</c> or <c>false</c>) or the value of <c>Expr2</c> + (if <c>Expr2</c> was evaluated).</p> + + <p>Example 1:</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>, + since in that case, <c>math:sqrt/1</c> is never evaluated.</p> + <p>Example 2:</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> + are now tail-recursive. For instance, the following function is + tail-recursive in R13A and later:</p> + + <pre> +all(Pred, [Hd|Tail]) -> + Pred(Hd) andalso all(Pred, Tail); +all(_, []) -> + true.</pre> + </section> + + <section> + <title>List Operations</title> + <pre> +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 + occurrence of this element (if any) is removed.</p> + <p>Example:</p> + <pre> +1> <input>[1,2,3]++[4,5].</input> +[1,2,3,4,5] +2> <input>[1,2,3,2,1,2]--[2,1,2].</input> +[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 + long lists.</p></warning> + </section> + + <section> + <marker id="bit_syntax"></marker> + <title>Bit Syntax Expressions</title> + <code type="none"><![CDATA[<<>> +<<E1,...,En>>]]></code> + <p>Each element <c>Ei</c> specifies a <em>segment</em> of + the bit string. Each element <c>Ei</c> is a value, followed by an + optional <em>size expression</em> and an optional <em>type specifier list</em>.</p> + <pre> +Ei = Value | + Value:Size | + 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> + + <p>Used in a bit string matching, <c>Value</c> must be a variable, + or an integer, float or string.</p> + + <p>Note 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> + + <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 + elements in the matching must have a size specification.</p> + + <p>For the <c>utf8</c>, <c>utf16</c>, and <c>utf32</c> types, + <c>Size</c> must not be given. The size of the segment is implicitly + determined by the type and value itself.</p> + + <p><c>TypeSpecifierList</c> is a list of type specifiers, in any + order, separated by hyphens (-). Default values are used for any + omitted type specifiers.</p> + <taglist> + <tag><c>Type</c>= <c>integer</c> | <c>float</c> | <c>binary</c> | + <c>bytes</c> | <c>bitstring</c> | <c>bits</c> | + <c>utf8</c> | <c>utf16</c> | <c>utf32</c> </tag> + <item>The default is <c>integer</c>. <c>bytes</c> is a shorthand for + <c>binary</c> and <c>bits</c> is a shorthand for <c>bitstring</c>. + See below for more information about the <c>utf</c> types. + </item> + + <tag><c>Signedness</c>= <c>signed</c> | <c>unsigned</c></tag> + <item>Only matters for matching and when the type is <c>integer</c>. + 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 + 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>, + <c>utf16</c>, <c>utf32</c>, or <c>float</c>. The default is <c>big</c>. + </item> + + <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>. + No unit specifier must be given for the types + <c>utf8</c>, <c>utf16</c>, and <c>utf32</c>. + </item> + </taglist> + <p>The value of <c>Size</c> multiplied with the unit gives + the number of bits. A segment of type <c>binary</c> must have + a size that is evenly divisible by 8.</p> + + <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> + + <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, + and UTF-32, respectively.</p> + + <p>When constructing a segment of a <c>utf</c> type, <c>Value</c> + must be an integer in one of the ranges 0..16#D7FF, + 16#E000..16#FFFD, or 16#10000..16#10FFFF + (i.e. a valid Unicode code point). Construction + will fail 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> + + <p>When constructing, a literal string may be given followed + by one of the UTF types, for example: <c><![CDATA[<<"abc"/utf8>>]]></c> + which is syntatic 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 + in an integer in one of the ranges 0..16#D7FF, 16#E000..16#FFFD, + or 16#10000..16#10FFFF + (i.e. a valid Unicode code point). The match will fail if returned value + would fall outside those ranges.</p> + + <p>A segment of type <c>utf8</c> will match 1 to 4 bytes in the binary, + if the binary at the match position contains a valid UTF-8 sequence. + (See RFC-2279 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 + 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 + mentioned above.</p> + + <p>Examples:</p> + <pre> +1> <input>Bin1 = <<1,17,42>>.</input> +<<1,17,42>> +2> <input>Bin2 = <<"abc">>.</input> +<<97,98,99>> +3> <input>Bin3 = <<1,17,42:16>>.</input> +<<1,17,0,42>> +4> <input><<A,B,C:16>> = <<1,17,42:16>>.</input> +<<1,17,0,42>> +5> <input>C.</input> +42 +6> <input><<D:16,E,F>> = <<1,17,42:16>>.</input> +<<1,17,0,42>> +7> <input>D.</input> +273 +8> <input>F.</input> +42 +9> <input><<G,H/binary>> = <<1,17,42:16>>.</input> +<<1,17,0,42>> +10> <input>H.</input> +<<17,0,42>> +11> <input><<G,H/bitstring>> = <<1,17,42:12>>.</input> +<<1,17,1,10:4>> +12> <input>H.</input> +<<17,1,10:4>> +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 + "<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> + </section> + + <section> + <marker id="funs"></marker> + <title>Fun Expressions</title> + <pre> +fun + (Pattern11,...,Pattern1N) [when GuardSeq1] -> + Body1; + ...; + (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 + 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> + <p>The return value of the expression is the resulting fun.</p> + <p>Examples:</p> + <pre> +1> <input>Fun1 = fun (X) -> X+1 end.</input> +#Fun<erl_eval.6.39074546> +2> <input>Fun1(2).</input> +3 +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> + <p>The following fun expressions are also allowed:</p> + <pre> +fun Name/Arity +fun Module:Name/Arity</pre> + <p>In <c>Name/Arity</c>, <c>Name</c> is an atom and <c>Arity</c> is an integer. + <c>Name/Arity</c> must specify an existing local function. The expression is + 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. + A fun defined in this way will refer to the function <c>Name</c> + with arity <c>Arity</c> in the <em>latest</em> version of module <c>Module</c>. + </p> + <p>When applied to a number N of arguments, a tuple + <c>{Module,FunctionName}</c> is interpreted as a fun, referring + to the function <c>FunctionName</c> with arity N in the module + <c>Module</c>. The function must be exported. + <em>This usage is deprecated.</em> + See <seealso marker="#calls">Function Calls</seealso> for an example.</p> + <p>More examples can be found in <em>Programming Examples</em>.</p> + </section> + + <section> + <marker id="catch"></marker> + <title>Catch and Throw</title> + <code type="none"> +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> + <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> + <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 + subexpressions often needs to be enclosed in a block + expression or in parenthesis:</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> + <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> + </section> + + <section> + <marker id="try"></marker> + <title>Try</title> + <code type="none"> +try Exprs +catch + [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] -> + ExceptionBody1; + [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] -> + ExceptionBodyN +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 + 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 + <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 + class <c>Class</c> are sequentially matched against the caught + exception. An omitted <c>Class</c> is shorthand for <c>throw</c>. + If a match succeeds and the optional guard sequence + <c>ExceptionGuardSeq</c> is true, the corresponding + <c>ExceptionBody</c> is evaluated to become the return value.</p> + <p>If an exception occurs during evaluation of <c>Exprs</c> but + there is no matching <c>ExceptionPattern</c> of the right + <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> + it is not caught.</p> + <p>The <c>try</c> expression can have an <c>of</c> + section: + </p> + <code type="none"> +try Exprs of + Pattern1 [when GuardSeq1] -> + Body1; + ...; + PatternN [when GuardSeqN] -> + BodyN +catch + [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] -> + ExceptionBody1; + ...; + [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] -> + ExceptionBodyN +end</code> + <p>If the evaluation of <c>Exprs</c> succeeds without an exception, + 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> + <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 + <c>after</c> section, intended to be used for cleanup with side + effects:</p> + <code type="none"> +try Exprs of + Pattern1 [when GuardSeq1] -> + Body1; + ...; + PatternN [when GuardSeqN] -> + BodyN +catch + [Class1:]ExceptionPattern1 [when ExceptionGuardSeq1] -> + ExceptionBody1; + ...; + [ClassN:]ExceptionPatternN [when ExceptionGuardSeqN] -> + ExceptionBodyN +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>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 + <c>ExceptionBody</c>, <c>AfterBody</c> is evaluated. In this case + the exception is passed on after <c>AfterBody</c> has been + 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>, + 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 + 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> + expressions:</p> + <code type="none"> +try Exprs of + Pattern when GuardSeq -> + Body +after + AfterBody +end + +try Exprs +catch + ExpressionPattern -> + ExpressionBody +after + AfterBody +end + +try Exprs after AfterBody end</code> + <p>Example of using <c>after</c>, this code will close 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 + without the <c>try</c>...<c>after</c>...<c>end</c> expression:</p> + <code type="none"> +termize_file(Name) -> + {ok,F} = file:open(Name, [read,binary]), + try + {ok,Bin} = file:read(F, 1024*1024), + binary_to_term(Bin) + after + file:close(F) + end.</code> + <p>Example: Using <c>try</c> to emulate <c>catch Expr</c>.</p> + <code type="none"> +try Expr +catch + throw:Term -> Term; + exit:Reason -> {'EXIT',Reason} + error:Reason -> {'EXIT',{Reason,erlang:get_stacktrace()}} +end</code> + </section> + + <section> + <title>Parenthesized Expressions</title> + <pre> +(Expr)</pre> + <p>Parenthesized expressions are useful to override + <seealso marker="#prec">operator precedences</seealso>, + for example in arithmetic expressions:</p> + <pre> +1> <input>1 + 2 * 3.</input> +7 +2> <input>(1 + 2) * 3.</input> +9</pre> + </section> + + <section> + <title>Block Expressions</title> + <pre> +begin + Expr1, + ..., + ExprN +end</pre> + <p>Block expressions provide a way to group a sequence of + expressions, similar to a clause body. The return value is + the value of the last expression <c>ExprN</c>.</p> + </section> + + <section> + <marker id="lcs"></marker> + <title>List Comprehensions</title> + <p>List comprehensions are 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 + Zermelo-Frankel set theory and are called ZF expressions in + Miranda. They are analogous to the <c>setof</c> and + <c>findall</c> predicates in Prolog.</p> + <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 + <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 + 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 + bitstring.</item> + <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 + 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> + <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> + + + </section> + +<section> + <title>Bit String Comprehensions</title> + + <p>Bit string comprehensions are + analogous to List Comprehensions. They are used to generate bit strings + efficiently and succinctly.</p> + <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> + <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 + 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 + bitstring.</item> + <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 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 + filters are true.</p> + <p></p> + <p>Example:</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> + </section> + + <section> + <marker id="guards"></marker> + <title>Guard Sequences</title> + + <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> + <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> + <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> + <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> + </list> + <table> + <row> + <cell align="left" valign="middle"><c>is_atom/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_binary/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_bitstring/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_float/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_function/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_function/2</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_integer/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_list/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_number/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_pid/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_port/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_record/2</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_record/3</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_reference/1</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>is_tuple/1</c></cell> + </row> + <tcaption>Type Test BIFs.</tcaption> + </table> + <p>Note 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 + also only allowed at top level. For example, they are not allowed + in boolean expressions in guards.</p> + <table> + <row> + <cell align="left" valign="middle"><c>abs(Number)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>bit_size(Bitstring)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>byte_size(Bitstring)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>element(N, Tuple)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>float(Term)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>hd(List)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>length(List)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>node()</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>node(Pid|Ref|Port)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>round(Number)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>self()</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>size(Tuple|Bitstring)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>tl(List)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>trunc(Number)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>tuple_size(Tuple)</c></cell> + </row> + <tcaption>Other BIFs Allowed in Guard Expressions.</tcaption> + </table> + + <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> + + </section> + + <section> + <marker id="prec"></marker> + <title>Operator Precedence</title> + <p>Operator precedence in falling priority:</p> + <table> + <row> + <cell align="left" valign="middle">:</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">#</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">Unary + - bnot not</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">/ * div rem band and</cell> + <cell align="left" valign="middle">Left associative</cell> + </row> + <row> + <cell align="left" valign="middle">+ - bor bxor bsl bsr or xor</cell> + <cell align="left" valign="middle">Left associative</cell> + </row> + <row> + <cell align="left" valign="middle">++ --</cell> + <cell align="left" valign="middle">Right associative</cell> + </row> + <row> + <cell align="left" valign="middle">== /= =< < >= > =:= =/=</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">andalso</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">orelse</cell> + <cell align="left" valign="middle"> </cell> + </row> + <row> + <cell align="left" valign="middle">= !</cell> + <cell align="left" valign="middle">Right associative</cell> + </row> + <row> + <cell align="left" valign="middle">catch</cell> + <cell align="left" valign="middle"> </cell> + </row> + <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 + right:</p> + <pre> +<input>6 + 5 * 4 - 3 / 2</input> evaluates to +<input>6 + 20 - 1.5</input> evaluates to +<input>26 - 1.5</input> evaluates to +<input>24.5</input></pre> + </section> +</chapter> + |