diff options
Diffstat (limited to 'system/doc/reference_manual')
-rw-r--r-- | system/doc/reference_manual/Makefile | 6 | ||||
-rw-r--r-- | system/doc/reference_manual/character_set.xml | 56 | ||||
-rw-r--r-- | system/doc/reference_manual/code_loading.xml | 8 | ||||
-rw-r--r-- | system/doc/reference_manual/data_types.xml | 93 | ||||
-rw-r--r-- | system/doc/reference_manual/distributed.xml | 8 | ||||
-rw-r--r-- | system/doc/reference_manual/expressions.xml | 815 | ||||
-rw-r--r-- | system/doc/reference_manual/features.xml | 20 | ||||
-rw-r--r-- | system/doc/reference_manual/introduction.xml | 9 | ||||
-rw-r--r-- | system/doc/reference_manual/macros.xml | 19 | ||||
-rw-r--r-- | system/doc/reference_manual/modules.xml | 33 | ||||
-rw-r--r-- | system/doc/reference_manual/opaques.xml | 91 | ||||
-rw-r--r-- | system/doc/reference_manual/ports.xml | 9 | ||||
-rw-r--r-- | system/doc/reference_manual/processes.xml | 5 | ||||
-rw-r--r-- | system/doc/reference_manual/records.xml | 22 | ||||
-rw-r--r-- | system/doc/reference_manual/typespec.xml | 37 |
15 files changed, 859 insertions, 372 deletions
diff --git a/system/doc/reference_manual/Makefile b/system/doc/reference_manual/Makefile index 2e0cb4fbc2..c51496ca5d 100644 --- a/system/doc/reference_manual/Makefile +++ b/system/doc/reference_manual/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2003-2020. All Rights Reserved. +# Copyright Ericsson AB 2003-2023. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ XMLDIR := $(XMLDIR)/reference_manual # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- -RELSYSDIR = "$(RELEASE_PATH)/doc/reference_manual" +RELSYSDIR = $(RELEASE_PATH)/doc/reference_manual # ---------------------------------------------------- # Target Specs @@ -102,7 +102,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_html_spec: html $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTMLDIR)/*.html \ - $(RELSYSDIR) + "$(RELSYSDIR)" release_docs_spec: $(DOC_TARGETS:%=release_%_spec) diff --git a/system/doc/reference_manual/character_set.xml b/system/doc/reference_manual/character_set.xml index 6d37700da3..ec8e8c2c52 100644 --- a/system/doc/reference_manual/character_set.xml +++ b/system/doc/reference_manual/character_set.xml @@ -41,7 +41,7 @@ shown without the escape backslash convention.</p> </item> <item> - <p>Atoms and variables can use all Latin-1 letters.</p> + <p>Unquoted atoms and variables can use all Latin-1 letters.</p> </item> </list> <table> @@ -101,17 +101,35 @@ </row> <tcaption>Character Classes</tcaption> </table> - <p>In Erlang/OTP R16B the syntax of Erlang tokens was extended to - handle Unicode. The support was limited to - string literals and comments. - More about the usage of Unicode in Erlang source files - can be found in <seeguide - marker="stdlib:unicode_usage#unicode_in_erlang">STDLIB's User's - Guide</seeguide>.</p> - <p>From Erlang/OTP 20, atoms and function names are also allowed - to contain Unicode characters outside the ISO-Latin-1 range. - Module names, application names, and node names are still - restricted to the ISO-Latin-1 range.</p> + + <p>The following tokens are allowed to also use Unicode characters + outside of the Latin-1 range:</p> + + <list type="bulleted"> + <item> + <p>String literals. Example: <c>"√π"</c></p> + </item> + <item> + <p>Character literals. Example: <c>$∑</c></p> + </item> + <item> + <p>Comments in code.</p> + </item> + <item> + <p>Quoted atoms. Example: <c>'μs'</c></p> + </item> + <item> + <p>Function names. Example: <c>'s_to_μs'(S) -> S * 1_000_000.</c></p> + </item> + </list> + + <p>Atoms used as module names, application names, and node names are + restricted to the Latin-1 range.</p> + + <change><p>Support for Unicode in string literals, character literals, + and comments was introduced in Erlang/OTP R16B. Support for Unicode in + atom and function names was introduced in Erlang/OTP 20.</p> + </change> </section> <section> <title>Source File Encoding</title> @@ -123,15 +141,17 @@ the matching string is an invalid encoding, it is ignored. The valid encodings are <c>Latin-1</c> and <c>UTF-8</c>, where the case of the characters can be chosen freely.</p> - <p>The following example selects UTF-8 as default encoding:</p> - <pre> -%% coding: utf-8</pre> - <p>Two more examples, both selecting Latin-1 as default encoding:</p> + + <p>The default Erlang source file encoding if no valid + <c>coding</c> comment is present is UTF-8.</p> + + <p>Two examples, both selecting Latin-1 as the source file encoding:</p> <pre> %% For this file we have chosen encoding = Latin-1</pre> <pre> %% -*- coding: latin-1 -*-</pre> - <p>The default encoding for Erlang source files is changed from - Latin-1 to UTF-8 since Erlang/OTP 17.0.</p> + + <change><p>The default encoding for Erlang source files was changed from + Latin-1 to UTF-8 in Erlang/OTP 17.0.</p></change> </section> </chapter> diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml index b64b2eecf9..c43f92ea31 100644 --- a/system/doc/reference_manual/code_loading.xml +++ b/system/doc/reference_manual/code_loading.xml @@ -157,12 +157,12 @@ loop() -> before the <c>on_load</c> function has finished will be suspended until the <c>on_load</c> function have finished.</p> - <note> - <p>Before OTP 19, if the <c>on_load</c> function failed, any + <change> + <p>Before Erlang/OTP 19, if the <c>on_load</c> function failed, any previously current code would become old, essentially leaving the system without any working and reachable instance of the - module. That problem has been eliminated in OTP 19.</p> - </note> + module.</p> + </change> <p>In embedded mode, first all modules are loaded. Then all <c>on_load</c> functions are called. The system is diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml index 1a4bdc5680..206f7c8a4a 100644 --- a/system/doc/reference_manual/data_types.xml +++ b/system/doc/reference_manual/data_types.xml @@ -305,9 +305,10 @@ adam in STDLIB.</p> <p>Read more about maps in <seeguide marker="expressions#map_expressions"> Map Expressions</seeguide>.</p> - <note> - <p>Maps are considered to be experimental during Erlang/OTP R17.</p> - </note> + <change> + <p>Maps were introduced as an experimental feature in Erlang/OTP R17. Their + functionality was extended and became fully supported in Erlang/OTP 18.</p> + </change> </section> <section> @@ -421,75 +422,109 @@ true</pre> <cell align="left" valign="middle"><em>Description</em></cell> </row> <row> - <cell align="left" valign="middle">\b</cell> - <cell align="left" valign="middle">Backspace</cell> + <cell align="left" valign="middle"><c>\b</c></cell> + <cell align="left" valign="middle">Backspace (ASCII code 8)</cell> </row> <row> - <cell align="left" valign="middle">\d</cell> - <cell align="left" valign="middle">Delete</cell> + <cell align="left" valign="middle"><c>\d</c></cell> + <cell align="left" valign="middle">Delete (ASCII code 127)</cell> </row> <row> - <cell align="left" valign="middle">\e</cell> - <cell align="left" valign="middle">Escape</cell> + <cell align="left" valign="middle"><c>\e</c></cell> + <cell align="left" valign="middle">Escape (ASCII code 27)</cell> </row> <row> - <cell align="left" valign="middle">\f</cell> - <cell align="left" valign="middle">Form feed</cell> + <cell align="left" valign="middle"><c>\f</c></cell> + <cell align="left" valign="middle">Form Feed (ASCII code 12)</cell> </row> <row> - <cell align="left" valign="middle">\n</cell> - <cell align="left" valign="middle">Newline</cell> + <cell align="left" valign="middle"><c>\n</c></cell> + <cell align="left" valign="middle">Line Feed/Newline (ASCII code 10)</cell> </row> <row> - <cell align="left" valign="middle">\r</cell> - <cell align="left" valign="middle">Carriage return</cell> + <cell align="left" valign="middle"><c>\r</c></cell> + <cell align="left" valign="middle">Carriage Return (ASCII code 13)</cell> </row> <row> - <cell align="left" valign="middle">\s</cell> - <cell align="left" valign="middle">Space</cell> + <cell align="left" valign="middle"><c>\s</c></cell> + <cell align="left" valign="middle">Space (ASCII code 32)</cell> </row> <row> - <cell align="left" valign="middle">\t</cell> - <cell align="left" valign="middle">Tab</cell> + <cell align="left" valign="middle"><c>\t</c></cell> + <cell align="left" valign="middle">(Horizontal) Tab (ASCII code 9)</cell> </row> <row> - <cell align="left" valign="middle">\v</cell> - <cell align="left" valign="middle">Vertical tab</cell> + <cell align="left" valign="middle"><c>\v</c></cell> + <cell align="left" valign="middle">Vertical Tab (ASCII code 11)</cell> </row> <row> - <cell align="left" valign="middle">\XYZ, \YZ, \Z</cell> + <cell align="left" valign="middle"><c>\</c>XYZ, <c>\</c>YZ, <c>\</c>Z</cell> <cell align="left" valign="middle">Character with octal representation XYZ, YZ or Z</cell> </row> <row> - <cell align="left" valign="middle">\xXY</cell> + <cell align="left" valign="middle"><c>\xXY</c></cell> <cell align="left" valign="middle">Character with hexadecimal representation XY</cell> </row> <row> - <cell align="left" valign="middle">\x{X...}</cell> + <cell align="left" valign="middle"><c>\x{</c>X...<c>}</c></cell> <cell align="left" valign="middle">Character with hexadecimal representation; X... is one or more hexadecimal characters</cell> </row> <row> - <cell align="left" valign="middle">\^a...\^z <br></br> -\^A...\^Z</cell> + <cell align="left" valign="middle"><c>\^a</c>...<c>\^z</c> <br></br> +<c>\^A</c>...<c>\^Z</c></cell> <cell align="left" valign="middle">Control A to control Z</cell> </row> <row> - <cell align="left" valign="middle">\'</cell> + <cell align="left" valign="middle"><c>\^@</c></cell> + <cell align="left" valign="middle">NUL (ASCII code 0)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^[</c></cell> + <cell align="left" valign="middle">Escape (ASCII code 27)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^\</c></cell> + <cell align="left" valign="middle">File Separator (ASCII code 28)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^]</c></cell> + <cell align="left" valign="middle">Group Separator (ASCII code 29)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^^</c></cell> + <cell align="left" valign="middle">Record Separator (ASCII code 30)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^_</c></cell> + <cell align="left" valign="middle">Unit Separator (ASCII code 31)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\^?</c></cell> + <cell align="left" valign="middle">Delete (ASCII code 127)</cell> + </row> + <row> + <cell align="left" valign="middle"><c>\'</c></cell> <cell align="left" valign="middle">Single quote</cell> </row> <row> - <cell align="left" valign="middle">\"</cell> + <cell align="left" valign="middle"><c>\"</c></cell> <cell align="left" valign="middle">Double quote</cell> </row> <row> - <cell align="left" valign="middle">\\</cell> + <cell align="left" valign="middle"><c>\\</c></cell> <cell align="left" valign="middle">Backslash</cell> </row> <tcaption>Recognized Escape Sequences</tcaption> </table> + + + <change><p>As of Erlang/OTP 26, the value of <c>$\^?</c> has been + changed to be 127 (Delete), instead of 31. Previous releases + would allow any character following <c>$\^</c>; as of Erlang/OTP + 26, only the documented characters are allowed.</p></change> </section> <section> diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml index f8fb159be3..6e4c28d3e2 100644 --- a/system/doc/reference_manual/distributed.xml +++ b/system/doc/reference_manual/distributed.xml @@ -167,14 +167,14 @@ dilbert@uab</pre> can be made to get a new dynamic node name. The node name may change if the distribution is dropped and then set up again. </p> - <note> + <change> <p> - The <em>dynamic node name</em> feature is supported from OTP 23. + The <em>dynamic node name</em> feature is supported from Erlang/OTP 23. Both the temporary client node and the first connected peer node - (supplying the dynamic node name) must be at least OTP 23 for it to + (supplying the dynamic node name) must be at least Erlang/OTP 23 for it to work. </p> - </note> + </change> </section> <section> diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml index af143ad4d5..34e622a67e 100644 --- a/system/doc/reference_manual/expressions.xml +++ b/system/doc/reference_manual/expressions.xml @@ -138,18 +138,22 @@ member(_Elem, []) -> 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> + <p>Patterns are allowed in clause heads, + <seeguide marker="#case">case expressions</seeguide>, + <seeguide marker="#receive">receive expressions</seeguide>, + and + <seeguide marker="#match_operator">match expressions</seeguide>.</p> <section> - <title>Match Operator = in Patterns</title> + <marker id="compound_pattern_operator"></marker> + <title>The Compound Pattern Operator</title> <p>If <c>Pattern1</c> and <c>Pattern2</c> are valid patterns, 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> are matched against the term. The idea - behind this feature is to avoid reconstruction of terms.</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) -> @@ -163,6 +167,11 @@ f({connect,_,To,_,_} = Signal, To) -> ...; f(Signal, To) -> ignore.</pre> + + <p>The compound pattern operator does not imply that its operands + are matched in any particular order. That means that it is not + legal to bind a variable in <c>Pattern1</c> and use it in <c>Pattern2</c>, + or vice versa.</p> </section> <section> @@ -192,22 +201,121 @@ case {Value, Result} of </section> <section> - <title>Match</title> - <p>The following matches <c>Expr1</c>, a pattern, against - <c>Expr2</c>:</p> + <marker id="match_operator"></marker> + <title>The Match Operator</title> + <p>The following matches <c>Pattern</c> against + <c>Expr</c>:</p> <pre> -Expr1 = Expr2</pre> +Pattern = Expr</pre> <p>If the matching succeeds, any unbound variable in the pattern - becomes bound and the value of <c>Expr2</c> is returned.</p> + becomes bound and the value of <c>Expr</c> is returned.</p> + <p>If multiple match operators are applied in sequence, they will be + evaluated from right to left.</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> +1> <input>{A, B} = T = {answer, 42}.</input> {answer,42} 2> <input>A.</input> answer -3> <input>{C, D} = [1, 2].</input> +3> <input>B.</input> +42 +4> <input>T.</input> +{answer,42} +5> <input>{C, D} = [1, 2].</input> ** exception error: no match of right-hand side value [1,2]</pre> + + <p>Because multiple match operators are evaluated from right to left, + it means that:</p> + + <pre> +Pattern1 = Pattern2 = . . . = PatternN = Expression</pre> + + <p>is equivalent to:</p> + <pre> +Temporary = Expression, +PatternN = Temporary, + . + . + ., +Pattern2 = Temporary, +Pattern = Temporary</pre> + </section> + + <section> + <title>The Match Operator and the Compound Pattern Operator</title> + <note><p>This is an advanced section, which references to topics not + yet introduced. It can safely be skipped on a first + reading.</p></note> + + <p>The <c>=</c> character is used to denote two similar but + distinct operators: the match operator and the compound pattern + operator. Which one is meant is determined by context.</p> + + <p>The <em>compound pattern operator</em> is used to construct a + compound pattern from two patterns. Compound patterns are accepted + everywhere a pattern is accepted. A compound pattern matches if + all of its constituent patterns match. It is not legal for a + pattern that is part of a compound pattern to use variables (as + keys in map patterns or sizes in binary patterns) bound in other + sub patterns of the same compound pattern.</p> + <p><em>Examples:</em></p> + + <pre> +1> <input>fun(#{Key := Value} = #{key := Key}) -> Value end.</input> +* 1:7: variable 'Key' is unbound +2> <input>F = fun({A, B} = E) -> {E, A + B} end, F({1,2}).</input> +{{1,2},3} +3> <input>G = fun(<<A:8,B:8>> = <<C:16>>) -> {A, B, C} end, G(<<42,43>>).</input> +{42,43,10795}</pre> + + <p>The <em>match operator</em> is allowed everywhere an expression + is allowed. It is used to match the value of an expression to a pattern. + If multiple match operators are applied in sequence, they will be + evaluated from right to left.</p> + + <p><em>Examples:</em></p> + <pre> +1> <input>M = #{key => key2, key2 => value}.</input> +#{key => key2,key2 => value} +2> <input>f(Key), #{Key := Value} = #{key := Key} = M, Value.</input> +value +3> <input>f(Key), #{Key := Value} = (#{key := Key} = M), Value.</input> +value +4> <input>f(Key), (#{Key := Value} = #{key := Key}) = M, Value.</input> +* 1:12: variable 'Key' is unbound +5> <input><<X:Y>> = begin Y = 8, <<42:8>> end, X.</input> +42</pre> + + <p>The expression at prompt <em>2></em> first matches the value of + variable <c>M</c> against pattern <c>#{key := Key}</c>, binding + variable <c>Key</c>. It then matches the value of <c>M</c> against + pattern <c>#{Key := Value}</c> using variable <c>Key</c> as the + key, binding variable <c>Value</c>.</p> + + <p>The expression at prompt <em>3></em> matches expression + <c>(#{key := Key} = M)</c> against pattern <c>#{Key := + Value}</c>. The expression inside the parentheses is evaluated + first. That is, <c>M</c> is matched against <c>#{key := Key}</c>, + and then the value of <c>M</c> is matched against pattern <c>#{Key + := Value}</c>. That is the same evaluation order as in <em>2</em>; + therefore, the parentheses are redundant.</p> + + <p>In the expression at prompt <em>4></em> the expression <c>M</c> + is matched against a pattern inside parentheses. Since the + construct inside the parentheses is a pattern, the <c>=</c> that + separates the two patterns is the compound pattern operator + (<em>not</em> the match operator). The match fails because the two + sub patterns are matched at the same time, and the variable + <c>Key</c> is therefore not bound when matching against pattern + <c>#{Key := Value}</c>.</p> + + <p>In the expression at prompt <em>5></em> the expressions + inside the <seeguide marker="#block_expressions">block + expression</seeguide> are evaluated first, binding variable + <c>Y</c> and creating a binary. The binary is then matched + against pattern <c><<X:Y>></c> using the value of + <c>Y</c> as the size of the segment.</p> </section> <section> @@ -268,13 +376,13 @@ spawn(m, init, [])</code> being auto-imported. In certain situations, such a compile-directive is mandatory.</p> - <warning><p>Before OTP R14A (ERTS version 5.8), an implicitly + <change><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 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> + of old code.</p></change> <p>However, to avoid that old (pre R14) code changed its behavior when compiled with OTP version R14A or later, the @@ -284,7 +392,7 @@ spawn(m, init, [])</code> 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 get a compilation - error. See the following example:</p> </warning> + error. See the following example:</p> <code type="none"> -export([length/1,f/1]). @@ -397,14 +505,13 @@ is_valid_signal(Signal) -> <section> <marker id="maybe"></marker> <title>Maybe</title> - <note><p><c>maybe</c> is an experimental new <seeguide + <change><p><c>maybe</c> is an experimental <seeguide marker="system/reference_manual:features#features">feature</seeguide> - introduced in OTP 25. By default, it is disabled. To enable + introduced in Erlang/OTP 25. By default, it is disabled. To enable <c>maybe</c>, either use the <c>-feature(maybe_expr,enable)</c> directive (from within source code), or the compiler option - <c>{feature,maybe_expr,enable}</c>. The feature must also be enabled - in runtime using the <c>-enable-feature</c> option to <c>erl</c>.</p> - </note> + <c>{feature,maybe_expr,enable}</c>.</p> + </change> <code type="erl"><![CDATA[ maybe @@ -937,16 +1044,21 @@ case A >= -1.0 andalso math:sqrt(A+1) > B of</pre> OnlyOne = is_atom(L) orelse (is_list(L) andalso length(L) == 1),</pre> - <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 Erlang/OTP R13A and later:</p> + <p><c>Expr2</c> is not required to evaluate to a Boolean + value. Because of that, <c>andalso</c> and <c>orelse</c> are + tail-recursive.</p> + <p><em>Example 3 (tail-recursive function):</em></p> <pre> all(Pred, [Hd|Tail]) -> Pred(Hd) andalso all(Pred, Tail); all(_, []) -> true.</pre> + + <change><p>Before Erlang/OTP R13A, <c>Expr2</c> was required to + evaluate to a Boolean value, and as consequence, <c>andalso</c> + and <c>orelse</c> were <strong>not</strong> + tail-recursive.</p></change> </section> <section> @@ -1066,7 +1178,7 @@ M4 = #{{"w", 1} => f()}. % compound key associated with an evaluated expression </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> + of type <c>badkey</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> @@ -1126,9 +1238,9 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code> 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> - <note><p>Before OTP 23, the expression defining the key + <change><p>Before Erlang/OTP 23, the expression defining the key <c>K</c> was restricted to be either a single variable or a - literal.</p></note> + literal.</p></change> <p><em>Example:</em></p> <pre> 1> <input>M = #{"tuple" => {1,2}}.</input> @@ -1236,38 +1348,52 @@ handle_call(change, From, #{ state := start } = S) -> <section> <marker id="bit_syntax"></marker> <title>Bit Syntax Expressions</title> - <code type="none"><![CDATA[<<>> + <p> + The bit syntax operates on <em>bit strings</em>. + A bit string is a sequence of bits ordered + from the most significant bit to the least significant bit. + </p> + <code type="none"><![CDATA[<<>> % The empty bit string, zero length +<<E1>> <<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> + <p> + Each element <c>Ei</c> specifies a <em>segment</em> of + the bit string. The segments are ordered left to right + from the most significant bit to the least significant bit + of the bit string. + </p> + <p> + Each segment specification <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 + <p>When used in a bit string construction, <c>Value</c> is an expression 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, + <p>When used in a bit string matching, <c>Value</c> must be a variable, or an integer, float, or string.</p> <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 + <p>When used in a bit string construction, <c>Size</c> is an expression that is to evaluate to an integer.</p> - <p>Used in a bit string matching, <c>Size</c> must be a + <p>When used in a bit string matching, <c>Size</c> must be a <seeguide marker="#guard_expressions">guard expression</seeguide> that evaluates to an integer. All variables in the guard expression must be already bound.</p> - <note><p>Before OTP 23, <c>Size</c> was restricted to be an - integer or a variable bound to an integer.</p></note> + <change><p>Before Erlang/OTP 23, <c>Size</c> was restricted to be an + integer or a variable bound to an integer.</p></change> <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 @@ -1278,14 +1404,45 @@ Ei = Value | <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>In matching, the default value for a binary or bit string + segment is only valid for the last element. All other bit string + or binary elements in the matching must have a size + specification.</p> + + <marker id="binaries"></marker> + <p><strong>Binaries</strong></p> + <p> + A bit string with a length that is a multiple of 8 bits + is known as a <em>binary</em>, which is the most + common and useful type of bit string. + </p> + <p> + A binary has a canonical representation in memory. + Here follows a sequence of bytes where each byte's + value is its sequence number: + </p> + <pre><<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>></pre> + <p> + Bit strings are a later generalization of binaries, + so many texts and much information about binaries + apply just as well for bit strings. + </p> + + <p><strong>Example:</strong></p> + <pre> +1> <input><<A/binary, B/binary>> = <<"abcde">>.</input> +* 1:3: a binary field without size is only allowed at the end of a binary pattern +2> <input><<A:3/binary, B/binary>> = <<"abcde">>.</input> +<<"abcde">> +3> <input>A.</input> +<<"abc">> +4> <input>B.</input> +<<"de">></pre> <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> @@ -1303,68 +1460,172 @@ 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 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>, - <c>utf16</c>, <c>utf32</c>, or <c>float</c>. The default is <c>big</c>. - </item> + <item> + Specifies byte level (octet level) endianness (byte order). + 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>, + <c>utf16</c>, <c>utf32</c>, or <c>float</c>. The default is <c>big</c>. + <pre><<16#1234:16/little>> = <<16#3412:16>> = <<16#34:8, 16#12:8>></pre> + </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> + <item>The allowed range is 1 through 256. Defaults to 1 for <c>integer</c>, + <c>float</c>, and <c>bitstring</c>, and to 8 for <c>binary</c>. + For types <c>bitstring</c>, <c>bits</c>, and <c>bytes</c>, it is not allowed + to specify a unit value different from the default value. + 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. For a segment of type <c>float</c> - the size must be either 64, 32, or 16.</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 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, - and UTF-32, respectively.</p> - - <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 - 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 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 can be given followed - by one of the UTF types, for example: <c><![CDATA[<<"abc"/utf8>>]]></c> - which is syntactic sugar for - <c><![CDATA[<<$a/utf8,$b/utf8,$c/utf8>>]]></c>.</p> + <section> + <title>Integer segments</title> + <p>The value of <c>Size</c> multiplied with the unit gives the + size of the segment in bits.</p> + + <p>When constructing bit strings, 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 are silently discarded and only the <c>N</c> least + significant bits are put into the bit string. For example, <c><<16#ff:4>></c> + will result in the bit string <c><<15:4>></c>.</p> + </section> - <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 fails if the returned value falls outside those ranges.</p> + <section> + <title>Float segments</title> + <p>The value of <c>Size</c> multiplied with the unit gives + the size of the segment in bits. The size of a float segment in bits must be + one of 16, 32, or 64.</p> + + <p>When constructing bit strings, if the size of a float segment is too small + to contain the representation of the given float value, an exception is raised.</p> - <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>When matching bit strings, matching of float segments fails if the bits of the segment + does not contain the representation of a finite floating point value.</p> + </section> - <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> + <section> + <title>Binary segments</title> + <p>In this section, the phrase "binary segment" refers to any + one of the segment types <c>binary</c>, <c>bitstring</c>, + <c>bytes</c>, and <c>bits</c>.</p> + + <p> + See also the paragraphs about + <seeguide marker="#binaries">Binaries</seeguide>. + </p> - <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>When constructing binaries and no size is specified for a + binary segment, the entire binary value is interpolated into the + binary being constructed. However, the size in bits of the + binary being interpolated must be evenly divisible by the unit + value for the segment; otherwise an exception is raised.</p> + + <p>For example, the following examples all succeed:</p> + + <pre> +1> <input><<(<<"abc">>)/bitstring>>.</input> +<<"abc">> +2> <input><<(<<"abc">>)/binary-unit:1>>.</input> +<<"abc">> +3> <input><<(<<"abc">>)/binary>>.</input> +<<"abc">></pre> + + <p>The first two examples have a unit value of 1 for the segment, + while the third segment has a unit value of 8.</p> + + <p>Attempting to interpolate a bit string of size 1 into a + binary segment with unit 8 (the default unit for <c>binary</c>) + fails as shown in this example:</p> + + <pre> +<input>1> <<(<<1:1>>)/binary>>.</input> +** exception error: bad argument</pre> + + <p>For the construction to succeed, the unit value of the + segment must be 1:</p> + + <pre> +2> <input><<(<<1:1>>)/bitstring>>.</input> +<<1:1>> +3> <input><<(<<1:1>>)/binary-unit:1>>.</input> +<<1:1>></pre> + + <p>Similarly, when matching a binary segment with no size + specified, the match succeeds if and only if the size in bits of + the rest of the binary is evenly divisible by the unit + value:</p> + + <pre> +1> <input><<_/binary-unit:16>> = <<"">>.</input> +<<>> +2> <input><<_/binary-unit:16>> = <<"a">>.</input> +** exception error: no match of right hand side value <<"a">> +3> <input><<_/binary-unit:16>> = <<"ab">>.</input> +<<"ab">> +4> <input><<_/binary-unit:16>> = <<"abc">>.</input> +** exception error: no match of right hand side value <<"abc">> +5> <input><<_/binary-unit:16>> = <<"abcd">>.</input> +<<"abcd">></pre> + + <p>When a size is explicitly specified for a binary segment, + the segment size in bits is the value of <c>Size</c> multiplied + by the default or explicit unit value.</p> + + <p>When constructing binaries, the size of the binary being interpolated + into the constructed binary must be at least as large as the size of + the binary segment.</p> + + <p><strong>Examples:</strong></p> + <pre> +1> <input><<(<<"abc">>):2/binary>>.</input> +<<"ab">> +2> <input><<(<<"a">>):2/binary>>.</input> +** exception error: construction of binary failed + *** segment 1 of type 'binary': the value <<"a">> is shorter than the size of the segment</pre> + </section> + + <section> + <title>Unicode segments</title> + <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 the range 0 through 16#D7FF + or 16#E000 through 16#10FFFF. Construction fails with a + <c>badarg</c> exception if <c>Value</c> is outside the allowed + ranges. The sizes of the encoded values are as follows:</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 encoded in 4 bytes.</item> + </list> + + <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 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 + in an integer in the range 0 through 16#D7FF or 16#E000 through 16#10FFFF. + The match fails if the returned value falls outside those ranges.</p> + + <p>A segment of type <c>utf8</c> matches 1-4 bytes in the bit string, + if the bit string 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> can match 2 or 4 bytes in the bit string. + The match fails if the bit string 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> can match 4 bytes in the bit string 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 + previously mentioned.</p> + </section> <p><em>Examples:</em></p> <pre> @@ -1372,6 +1633,7 @@ Ei = Value | <<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> @@ -1392,8 +1654,14 @@ Ei = Value | <<1,17,2,10:4>> 12> <input>J.</input> <<17,2,10:4>> + 13> <input><<1024/utf8>>.</input> <<208,128>> + +14> <input><<1:1,0:7>>.</input> +<<128>> +15> <input><<16#123:12/little>> = <<16#231:12>> = <<2:4, 3:4, 1:4>>.</input> +<<35,1:4>> </pre> <p>Notice that bit string patterns cannot be nested.</p> <p>Notice also that "<c><![CDATA[B=<<1>>]]></c>" is interpreted as @@ -1448,14 +1716,15 @@ 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 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 is not dependent on - the code for the module in which it is defined. - </p> + <p>In <c>Module:Name/Arity</c>, <c>Module</c>, and <c>Name</c> are + atoms and <c>Arity</c> is an integer. <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 is not dependent on the code for the module in which it + is defined.</p> + <change><p>Before Erlang/OTP R15, <c>Module</c>, <c>Name</c>, and <c>Arity</c> were + not allowed to be variables.</p></change> <p>More examples are provided in <seeguide marker="system/programming_examples:funs"> Programming Examples</seeguide>.</p> @@ -1492,10 +1761,27 @@ catch Expr</code> returns the value <c>Any</c>.</p> <p><em>Example:</em></p> <pre> -5> <input>catch throw(hello).</input> +3> <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 occurs.</p> + + <change><p>Before Erlang/OTP 24, the <c>catch</c> operator had + the lowest precedence, making it necessary to add parentheses when + combining it with the <c>match</c> operator:</p> + <pre> +1> <input>A = (catch 42).</input> +42 +2> <input>A.</input> +42</pre> + + <p>Starting from Erlang/OTP 24, the parentheses can be omitted:</p> + <pre> +1> <input>A = catch 42.</input> +42 +2> <input>A.</input> +42</pre> + </change> </section> <section> @@ -1669,6 +1955,7 @@ end</code> </section> <section> + <marker id="block_expressions"></marker> <title>Block Expressions</title> <pre> begin @@ -1683,107 +1970,204 @@ end</pre> <section> <marker id="lcs"></marker> - <title>List Comprehensions</title> - <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 - 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> + <title>Comprehensions</title> + <p>Comprehensions provide a succinct notation for iterating over + one or more terms and constructing a new term. Comprehensions come + in three different flavors, depending on the type of term they + build.</p> + <p>List comprehensions construct lists. They have the following syntax:</p> + <pre> +[Expr || Qualifier1, . . ., QualifierN]</pre> <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 - 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>, or a - <seeguide marker="#guard_expressions">guard expression</seeguide>. - If the filter is not a guard expression and evaluates - to a non-Boolean value <c>Val</c>, an exception - <c>{bad_filter, Val}</c> is triggered at runtime.</item> - </list> + <c>Qualifier</c> is either a <strong>generator</strong> or a + <strong>filter</strong>.</p> + + <p>Bit string comprehensions construct bit strings or binaries. + They have the following syntax:</p> + <pre> +<< BitStringExpr || Qualifier1, . . ., QualifierN >></pre> + + <p><c>BitStringExpr</c> is an expression that evaluates 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 + <strong>generator</strong> or a <strong>filter</strong>.</p> + + <p>Map comprehensions construct maps. They have the following syntax:</p> + <pre> +#{KeyExpr => ValueExpr || Qualifier1, . . ., QualifierN}</pre> + <p>Here, <c>KeyExpr</c> and <c>ValueExpr</c> are arbitrary + expressions, and each <c>Qualifier</c> is either a + <strong>generator</strong> or a <strong>filter</strong>.</p> + + <change><p>Map comprehensions and map generators were introduced + in Erlang/OTP 26.</p></change> + + <p>There are three kinds of generators.</p> + + <p>A <em>list generator</em> has the following syntax:</p> + +<pre> +Pattern <- ListExpr</pre> + + <p>where <c>ListExpr</c> is an expression that evaluates to a + list of terms.</p> + + <p>A <em>bit string generator</em> has the following syntax:</p> + + <pre> +BitstringPattern <= BitStringExpr</pre> + + <p>where <c>BitStringExpr</c> is an expression that evaluates to a + bit string.</p> + + <p>A <em>map generator</em> has the following syntax:</p> + + <pre> +KeyPattern := ValuePattern <- MapExpression</pre> + + <p>where <c>MapExpr</c> is an expression that evaluates to a map, + or a map iterator obtained by calling <seemfa + marker="stdlib:maps#iterator/1">maps:iterator/1</seemfa> or + <seemfa + marker="stdlib:maps#iterator/2">maps:iterator/2</seemfa>.</p> + + <p>A <em>filter</em> is an expression that evaluates to + <c>true</c> or <c>false</c>.</p> + <p>The variables in the generator patterns shadow previously bound variables, including variables bound in a previous generator pattern.</p> - <p>A list comprehension returns a list, where the elements are the + + <p>Variables bound in a generator expression are not visible outside the expression:</p> + + <pre> +1> <input>[{E,L} || E <- L=[1,2,3]].</input> +* 1:5: variable 'L' is unbound</pre> + + <p>A <strong>list comprehension</strong> returns a list, where the list elements are the result of evaluating <c>Expr</c> for each combination of generator - list elements and bit string generator elements, for which all + elements for which all filters are true.</p> + + <p>A <strong>bit string comprehension</strong> returns a bit string, which is + created by concatenating the results of evaluating <c>BitStringExpr</c> for + each combination of bit string generator elements for which all filters are true.</p> - <p><em>Example:</em></p> + + <p>A <strong>map comprehension</strong> returns a map, where the + map elements are the result of evaluating <c>KeyExpr</c> and + <c>ValueExpr</c> for each combination of generator elements for + which all filters are true. If the key expressions are not unique, + the last occurrence is stored in the map.</p> + + <p><strong>Examples:</strong></p> + + <p>Multiplying each element in a list by two:</p> <pre> 1> <input>[X*2 || X <- [1,2,3]].</input> [2,4,6]</pre> - <p>When there are no generators or bit string generators, a list comprehension - returns either a list with one element (the result of evaluating <c>Expr</c>) - if all filters are true or an empty list otherwise.</p> + + <p>Multiplying each byte in a binary by two, returning a list:</p> + <pre> +1> <input>[X*2 || <<X>> <= <<1,2,3>> >>.</input> +[2,4,6]</pre> + + <p>Multiplying each byte in a binary by two:</p> + + <pre> +1> <input><< <<(X*2)>> || <<X>> <= <<1,2,3>> >>.</input> +<<2,4,6>></pre> + + <p>Multiplying each element in a list by two, returning a binary:</p> + + <pre> +1> <input><< <<(X*2)>> || X <- [1,2,3]].</input> +<<2,4,6>></pre> + + <p>Creating a mapping from an integer to its square:</p> + <pre> +1> <input>#{X => X*X || X <- [1,2,3]}.</input> +#{1 => 1,2 => 4,3 => 9}</pre> + + <p>Multiplying the value of each element in a map by two:</p> + <pre> +1> <input>#{K => 2*V || K := V <- #{a => 1,b => 2,c => 3}}.</input> +#{a => 2,b => 4,c => 6}</pre> + + <p>Filtering a list, keeping odd numbers:</p> + <pre> +1> <input>[X || X <- [1,2,3,4,5], X rem 2 =:= 1].</input> +[1,3,5]</pre> + + <p>Filtering a list, keeping only elements that match:</p> + <pre> +1> <input>[X || {_,_}=X <- [{a,b}, [a], {x,y,z}, {1,2}]].</input> +[{a,b},{1,2}]</pre> + + <p>Combining elements from two list generators:</p> + <pre> +1> <input>[{P,Q} || P <- [a,b,c], Q <- [1,2]].</input> +[{a,1},{a,2},{b,1},{b,2},{c,1},{c,2}] +</pre> + + <p>More examples are provided in + <seeguide marker="system/programming_examples:list_comprehensions"> + Programming Examples.</seeguide></p> + + <p>When there are no generators, a comprehension returns either a + term constructed from a single element (the result of evaluating + <c>Expr</c>) if all filters are true, or a term constructed from + no elements (that is, <c>[]</c> for list comprehension, + <c><<>></c> for a bit string comprehension, and + <c>#{}</c> for a map comprehension).</p> <p><em>Example:</em></p> <pre> 1> <input>[2 || is_integer(2)].</input> [2] 2> <input>[x || is_integer(x)].</input> []</pre> - <p>More examples are provided in - <seeguide marker="system/programming_examples:list_comprehensions"> - Programming Examples.</seeguide></p> - </section> + <p>What happens when the filter expression does not evaluate to + a boolean value depends on the expression:</p> -<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> -<< BitStringExpr || Qualifier1,...,QualifierN >></pre> - <p><c>BitStringExpr</c> is an expression that evaluates 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 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 that evaluates to a - bitstring.</item> - <item>A <em>filter</em> is an expression, which evaluates to - <c>true</c> or <c>false</c>, or a - <seeguide marker="#guard_expressions">guard expression</seeguide>. - If the filter is not a guard expression and evaluates - to a non-Boolean value <c>Val</c>, an exception - <c>{bad_filter, Val}</c> is triggered at runtime.</item> + <list> + <item><p>If the expression is a <seeguide + marker="#guard_expressions">guard expression</seeguide>, failure + to evaluate or evaluating to a non-boolean value is equivalent + to evaluating to <c>false</c>.</p></item> + + <item><p>If the expression is not a guard expression and + evaluates to a non-Boolean value <c>Val</c>, an exception + <c>{bad_filter, Val}</c> is triggered at runtime. If the + evaluation of the expression raises an exception, it is not + caught by the comprehension.</p></item> </list> - <p>The variables in the generator patterns shadow previously bound variables, - including variables bound in a previous generator pattern.</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><em>Example:</em></p> + + <p><strong>Examples</strong> (using a guard expression as filter):</p> + <pre> -1> <input><< << (X*2) >> || -<<X>> <= << 1,2,3 >> >>.</input> -<<2,4,6>></pre> - <p>More examples are provided in - <seeguide marker="system/programming_examples:bit_syntax"> - Programming Examples.</seeguide></p> +1> <input>List = [1,2,a,b,c,3,4].</input> +[1,2,a,b,c,3,4] +2> <input>[E || E <- List, E rem 2].</input> +[] +3> <input>[E || E <- List, E rem 2 =:= 0].</input> +[2,4]</pre> + + <p><strong>Examples</strong> (using a non-guard expression as filter):</p> + + <pre> +1> <input>List = [1,2,a,b,c,3,4].</input> +[1,2,a,b,c,3,4] +2> <input>FaultyIsEven = fun(E) -> E rem 2 end.</input> +#Fun<erl_eval.42.17316486> +3> <input>[E || E <- List, FaultyIsEven(E)].</input> +** exception error: bad filter 1 +4> <input>IsEven = fun(E) -> E rem 2 =:= 0 end.</input> +#Fun<erl_eval.42.17316486> +5> <input>[E || E <- List, IsEven(E)].</input> +** exception error: an error occurred when evaluating an arithmetic expression + in operator rem/2 + called as a rem 2 +6> <input>[E || E <- List, is_integer(E), IsEven(E)].</input> +[2,4]</pre> </section> <section> @@ -1915,6 +2299,12 @@ end</pre> <cell align="left" valign="middle"><c>map_size(Map)</c></cell> </row> <row> + <cell align="left" valign="middle"><c>max(A, B)</c></cell> + </row> + <row> + <cell align="left" valign="middle"><c>min(A, B)</c></cell> + </row> + <row> <cell align="left" valign="middle"><c>node()</c></cell> </row> <row> @@ -1941,6 +2331,9 @@ end</pre> <tcaption>Other BIFs Allowed in Guard Expressions</tcaption> </table> + <change><p>The <c>min/2</c> and <c>max/2</c> BIFs are allowed to be + used in guards from Erlang/OTP 26.</p></change> + <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 @@ -1952,7 +2345,7 @@ end</pre> <section> <marker id="prec"></marker> <title>Operator Precedence</title> - <p>Operator precedence in falling priority:</p> + <p>Operator precedence in descending order:</p> <table> <row> <cell align="left" valign="middle">:</cell> @@ -1968,53 +2361,69 @@ end</pre> </row> <row> <cell align="left" valign="middle">/ * div rem band and</cell> - <cell align="left" valign="middle">Left associative</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> + <cell align="left" valign="middle">Left-associative</cell> </row> <row> <cell align="left" valign="middle">++ --</cell> - <cell align="left" valign="middle">Right associative</cell> + <cell align="left" valign="middle">Right-associative</cell> </row> <row> <cell align="left" valign="middle">== /= =< < >= > =:= =/=</cell> - <cell align="left" valign="middle"> </cell> + <cell align="left" valign="middle">Non-associative</cell> </row> <row> <cell align="left" valign="middle">andalso</cell> - <cell align="left" valign="middle"> </cell> + <cell align="left" valign="middle">Left-associative</cell> </row> <row> <cell align="left" valign="middle">orelse</cell> + <cell align="left" valign="middle">Left-associative</cell> + </row> + <row> + <cell align="left" valign="middle">catch</cell> <cell align="left" valign="middle"> </cell> </row> <row> <cell align="left" valign="middle">= !</cell> - <cell align="left" valign="middle">Right associative</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">catch</cell> - <cell align="left" valign="middle"> </cell> + <cell align="left" valign="middle">Non-associative</cell> </row> <tcaption>Operator Precedence</tcaption> </table> + <change><p>Before Erlang/OTP 24, the <c>catch</c> operator had the lowest + precedence.</p></change> + <note><p>The <c>=</c> operator in the table is the + <seeguide marker="#match_operator">match operator</seeguide>. + The character <c>=</c> can also denote the + <seeguide marker="#compound_pattern_operator">compound pattern operator</seeguide>, + which can only be used in patterns.</p> + <p><c>?=</c> is restricted in that it can only be used at + the top-level inside a <c>maybe</c> block.</p> + </note> <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.</p> - <p><em>Example:</em></p> - <p>The left associative arithmetic operators are evaluated left to + precedence is evaluated first. Operators with the same precedence + are evaluated according to their associativity. Non-associative + operators cannot be combined with operators of the same precedence.</p> + <p><em>Examples:</em></p> + <p>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> + +<p>The non-associative operators cannot be combined:</p> + <pre> +1> <input>1 < X < 10.</input> +* 1:7: syntax error before: '<'</pre> </section> </chapter> diff --git a/system/doc/reference_manual/features.xml b/system/doc/reference_manual/features.xml index 882cdd2582..3beae96ba3 100644 --- a/system/doc/reference_manual/features.xml +++ b/system/doc/reference_manual/features.xml @@ -150,19 +150,13 @@ enable|disable)</c></seeguide> directive. This is the preferred method of enabling and disabling features.</item> </taglist> - <p> - Note that to load a module compiled with features enabled, the - corresponding features must be enabled in the runtime. This - is done using options <seecom - marker="erts:erl#enable-feature"><c>-enable-feature</c></seecom> - and <seecom - marker="erts:erl#disable-feature"><c>-disable-feature</c></seecom> - to <c>erl</c>. This is to allow the possibility to prevent - the use of experimental features in, e.g., production. This - will catch experimental features used in both own and third - party components. An active choice to use experimental - features must be done. - </p> + <change> + <p>In Erlang/OTP 25, in order to load a module with a feature + enabled, it was necessary to also enable the feature in the runtime. + This was done using option <seecom + marker="erts:erl#enable-feature"><c>-enable-feature</c></seecom> to + <c>erl</c>. This requirement was removed in Erlang/OTP 26.</p> + </change> </section> <section> diff --git a/system/doc/reference_manual/introduction.xml b/system/doc/reference_manual/introduction.xml index f823c6921b..d188ff8601 100644 --- a/system/doc/reference_manual/introduction.xml +++ b/system/doc/reference_manual/introduction.xml @@ -95,10 +95,15 @@ <title>Reserved Words</title> <p>The following are reserved words in Erlang:</p> <p><c>after and andalso band begin bnot bor bsl bsr bxor case catch - cond div end fun if let not of or orelse receive rem try + cond div end fun if let maybe not of or orelse receive rem try when xor</c></p> <p><strong>Note</strong>: <c>cond</c> and <c>let</c>, while reserved, - are currently not used by the language.</p> + are currently not used by the language.</p> + <change><p><c>maybe</c> is a reserved word only if feature + <c>maybe_expr</c> is enabled. In Erlang/OTP 25 and 26, + <c>maybe_expr</c> is disabled by default. Starting from + Erlang/OTP 27, <c>maybe_expr</c> is enabled by + default.</p></change> </section> </chapter> diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml index e54e0e1d30..2ebd23f23b 100644 --- a/system/doc/reference_manual/macros.xml +++ b/system/doc/reference_manual/macros.xml @@ -155,18 +155,20 @@ bar(X) -> <item>The OTP release that the currently executing ERTS application is part of, as an integer. For details, see <seemfa marker="erts:erlang#system_info/1"><c>erlang:system_info(otp_release)</c></seemfa>. - This macro was introduced in OTP release 21.</item> + <change><p>The <c>?OTP_RELEASE</c> macro was introduced in Erlang/OTP 21.</p></change></item> <tag><c>?FEATURE_AVAILABLE(Feature)</c></tag> <item>Expands to <c>true</c> if the <seeguide marker="system/reference_manual:features#features">feature</seeguide> <c>Feature</c> is available. The feature might or might not - be enabled. This macro was introduced with OTP release - 25.</item> + be enabled. + <change><p>The <c>?FEATURE_AVAILABLE()</c> macro was introduced in Erlang/OTP 25.</p></change> + </item> <tag><c>?FEATURE_ENABLED(Feature)</c></tag> <item>Expands to <c>true</c> if the <seeguide marker="system/reference_manual:features#features">feature</seeguide> - <c>Feature</c> is enabled. This macro was introduced with OTP - release 25.</item> + <c>Feature</c> is enabled. + <change><p>The <c>?FEATURE_ENABLED()</c> macro was introduced in Erlang/OTP 25.</p></change> + </item> </taglist> </section> @@ -175,7 +177,8 @@ bar(X) -> <p>It is possible to overload macros, except for predefined macros. An overloaded macro has more than one definition, each with a different number of arguments.</p> - <p>The feature was added in Erlang 5.7.5/OTP R13B04.</p> + <change><p>Support for overloading of macros was added in Erlang + 5.7.5/OTP R13B04.</p></change> <p>A macro <c>?Func(Arg1,...,ArgN)</c> with a (possibly empty) list of arguments results in an error message if there is at least one definition of <c>Func</c> with arguments, but none @@ -339,8 +342,8 @@ version() -> ?VERSION.</code> % <input>erlc t.erl</input> t.erl:5: Warning: -warning("Macro VERSION not defined -- using default version.").</pre> - <p>The <c>-error()</c> and <c>-warning()</c> directives were added - in OTP 19.</p> + <change><p>The <c>-error()</c> and <c>-warning()</c> directives were added + in Erlang/OTP 19.</p></change> </section> diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml index b373e2506b..3b888f2e1e 100644 --- a/system/doc/reference_manual/modules.xml +++ b/system/doc/reference_manual/modules.xml @@ -141,24 +141,23 @@ fact(0) -> % | <c>[Name1/Arity1, ..., NameN/ArityN]</c>, where each <c>NameI</c> is an atom and <c>ArityI</c> an integer. </p> - <note> - <p> - The <c>-nifs()</c> attribute was introduced in OTP 25.0. For older - Erlang source code without it, any functions in the module may be - loaded as NIFs. However, it is recommended to declare the NIFs with - the <c>-nifs</c> attribute. This allows the compiler to make better - decisions regarding optimizations for example. - </p> + <p>While not strictly necessary, it is recommended to use <c>-nifs()</c> + attribute in any module that load NIFs, to allow the compiler to make + better decisions regarding optimizations.</p> + <p>There is no need to add <c>-nifs([])</c> in modules that do not + load NIFs. The lack of any call to + <seemfa marker="erts:erlang#load_nif/2"><c>erlang:load_nif/2</c></seemfa>, + from within the module, is enough for the compiler to draw the + same conclusion. + </p> + <change> <p> - There is no need to add <c>-nifs([])</c> in modules that do not - load NIFs. The lack of any call to - <seemfa marker="erts:erlang#load_nif/2"><c>erlang:load_nif/2</c></seemfa>, - from within the module, is enough for the compiler to draw the - same conclusion. + The special meaning for the <c>-nifs()</c> attribute was + introduced in Erlang/OTP 25.0. In previous releases, the + <c>-nifs()</c> was accepted, but had no special meaning. </p> - </note> + </change> </item> - </taglist> </section> @@ -344,9 +343,7 @@ behaviour_info(callbacks) -> Callbacks.</pre> <tag><c>md5</c></tag> <item> - <p>Returns a binary representing the MD5 checksum of the module. - If the module has native code loaded, this will be the MD5 of the - native code, not the BEAM bytecode.</p> + <p>Returns a binary representing the MD5 checksum of the module.</p> </item> <tag><c>exports</c></tag> diff --git a/system/doc/reference_manual/opaques.xml b/system/doc/reference_manual/opaques.xml index 8fa3bae3e5..ad71ed111c 100644 --- a/system/doc/reference_manual/opaques.xml +++ b/system/doc/reference_manual/opaques.xml @@ -33,28 +33,30 @@ <section> <title>Opaque Type Aliases</title> - <p>The main use case for opacity in Erlang is to hide the implementation of a data type, enabling evolving the API while minimizing the risk of breaking consumers. The runtime does not check opacity. Dialyzer provides some opacity-checking, but the rest is up to convention. + <p>The main use case for opacity in Erlang is to hide the + implementation of a data type, enabling evolving the API while + minimizing the risk of breaking consumers. The runtime does not + check opacity. Dialyzer provides some opacity-checking, but the + rest is up to convention. </p> <p> - This document explains what Erlang opacity is (and the trade-offs involved) via the example of OTP's - <c>sets:set()</c> - data type. This type - <em>was</em> - defined in `sets` module like this: + This document explains what Erlang opacity is (and the + trade-offs involved) via the example of the <c>sets:set()</c> + data type. This type <em>was</em> defined in the <c>sets</c> + module like this: </p> <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)}.</code> - <p>OTP 24 changed the definition to the following, in - <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url> + <p>OTP 24 changed the definition to the following in + <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url>. </p> <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.</code> <p> - And this change was safer and more backwards-compatible than if the type had been defined with - <c>-type</c> - instead of - <c>-opaque</c> - . Here's why: when a module defines an - <c>-opaque</c> - , the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition. + And this change was safer and more backwards-compatible than if + the type had been defined with <c>-type</c> instead of + <c>-opaque</c>. Here is why: when a module defines an + <c>-opaque</c>, the contract is that only the defining module + should rely on the definition of the type: no other modules + should rely on the definition. </p> <p> This means that code that pattern-matched on @@ -62,8 +64,8 @@ as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of <c>set()</c> changed. Before OTP 24, this code printed - <c>ok</c> - . In OTP 24 it may error: + <c>ok</c>. + In OTP 24 it may error: </p> <code type="erl"> case sets:new() of @@ -85,12 +87,9 @@ end. Instead, use functions provided by the module for working with the type. For example, <c>sets</c> module provides - <c>sets:new/0</c> - , - <c>sets:add/2</c> - , - <c>sets:is_element/2</c> - , etc. + <c>sets:new/0</c>, + <c>sets:add/2</c>, + <c>sets:is_element/2</c>, and so on. </item> <item> <c>sets:set(a)</c> @@ -108,34 +107,40 @@ end. </p> <list type="bulleted"> <item> - Since consumers are expected to not rely on the definition of the opaque type, you must provide functions for constructing and querying/deconstructing intances of your opaque type. For example, sets can be constructed with - <c>sets:new/0</c>, <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with <c>sets:is_element/2</c>, and deconstructed with<c>sets:to_list/1</c>. + Since consumers are expected to not rely on the definition of + the opaque type, you must provide functions for constructing, + querying, and deconstructing instances of your opaque type. For + example, sets can be constructed with <c>sets:new/0</c>, + <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with + <c>sets:is_element/2</c>, and deconstructed + with<c>sets:to_list/1</c>. </item> <item> - Don't define an opaque with a type variable in parameter position. This breaks the normal and expected behavior that (for example) - <c>my_type(a)</c> is a subtype of <c>my_type(a | b)</c> + Don't define an opaque with a type variable in parameter + position. This breaks the normal and expected behavior that + (for example) <c>my_type(a)</c> is a subtype of <c>my_type(a | + b)</c> </item> <item> Add <seeguide marker="typespec">specs</seeguide> to exported functions that use the opaque type </item> </list> - <p>Note that opaques can be harder to work with for consumers, since the consumer is expected not to pattern-match and must instead use functions that the author of the opaque type provides to use instances of the type.</p> + <p>Note that opaques can be harder to work with for consumers, + since the consumer is expected not to pattern-match and must + instead use functions that the author of the opaque type provides + to use instances of the type.</p> <p> - Also, opacity in Erlang is skin-deep: the runtime does not enforce opacity-checking. So now that sets are implemented in terms of maps, an - <c>is_map</c> - check on a set - <em>will</em> - pass. The opacity rules are only enforced by convention and by additional tooling such as Dialyzer. And this enforcement is not total: For example, determined consumer of - <c>sets</c> - can still do things that reveal the structure of the set, such as by printing, serializing, or using a set as - <c>term()</c> - and then inspecting via functions like - <c>is_map</c> - or - <c>maps:get/2</c> - . And Dialyzer must make some - <url href="https://github.com/erlang/otp/issues/5118">approximations</url> - . Opacity checking has limitations, but is still a vital tool in scalable Erlang development. + Also, opacity in Erlang is skin-deep: the runtime does not + enforce opacity-checking. So now that sets are implemented in + terms of maps, an <c>is_map/1</c> check on a set <em>will</em> + pass. The opacity rules are only enforced by convention and by + additional tooling such as Dialyzer, and this enforcement is not + total. A determined consumer of <c>sets</c> can still reveal the + structure of the set, for example by printing, serializing, or + using a set as a <c>term()</c> and inspecting it via functions + like <c>is_map/1</c> or <c>maps:get/2</c>. Also, Dialyzer must make + some <url + href="https://github.com/erlang/otp/issues/5118">approximations</url>. </p> </section> </chapter> diff --git a/system/doc/reference_manual/ports.xml b/system/doc/reference_manual/ports.xml index 26ecc084c5..3da54b2018 100644 --- a/system/doc/reference_manual/ports.xml +++ b/system/doc/reference_manual/ports.xml @@ -103,12 +103,9 @@ <c>Port</c> by sending and receiving messages. (In fact, any process can send the messages to the port, but the port owner must be identified in the message).</p> - <p>As of Erlang/OTP R16, messages sent to ports are delivered truly - asynchronously. The underlying implementation previously - delivered messages to ports synchronously. Message passing has - however always been documented as an asynchronous operation. Hence, - this is not to be an issue for an Erlang program communicating - with ports, unless false assumptions about ports have been made.</p> + <p>Messages sent to ports are delivered asynchronously.</p> + <change><p>Before Erlang/OTP 16, messages to ports were + delivered synchronously.</p></change> <p>In the following tables of examples, <c>Data</c> must be an I/O list. An I/O list is a binary or a (possibly deep) list of binaries or integers in the range 0..255:</p> diff --git a/system/doc/reference_manual/processes.xml b/system/doc/reference_manual/processes.xml index 92be5b60d3..54d150bc28 100644 --- a/system/doc/reference_manual/processes.xml +++ b/system/doc/reference_manual/processes.xml @@ -700,13 +700,14 @@ spawn(Module, Name, Args) -> pid() <seecom marker="erts:erl#+zdbbl"><c>+zdbbl</c></seecom>. Note that if you do raise the limit like this, you need to take care of flow control yourself to ensure that you do not get into a - situation with excessive memory usage. As of OTP 25.3 it is + situation with excessive memory usage.</p> + <change><p>As of OTP 25.3 it is also possible to enable <i>fully asynchronous distributed signaling</i> on a per process level using <seeerl marker="erts:erlang#process_flag_async_dist"> <c>process_flag(async_dist, Bool)</c></seeerl>. Also in this case you need to take care of flow control yourself. - </p> + </p></change> </item> </taglist> <p> diff --git a/system/doc/reference_manual/records.xml b/system/doc/reference_manual/records.xml index d5712bded0..14cf781417 100644 --- a/system/doc/reference_manual/records.xml +++ b/system/doc/reference_manual/records.xml @@ -151,25 +151,23 @@ is_person(_P) -> <section> <title>Nested Records</title> - <p>Beginning with Erlang/OTP R14, parentheses when accessing or updating nested - records can be omitted. Assume the following record - definitions:</p> + <p>Assume the following record definitions:</p> <pre> -record(nrec0, {name = "nested0"}). -record(nrec1, {name = "nested1", nrec0=#nrec0{}}). -record(nrec2, {name = "nested2", nrec1=#nrec1{}}). -N2 = #nrec2{}, - </pre> - <p>Before R14, parentheses were needed as follows:</p> - <pre> -"nested0" = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name, -N0n = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = "nested0a"}, - </pre> - <p>Since R14, the following can also be written:</p> +N2 = #nrec2{},</pre> + <p>Accessing or updating nested records can be written without parentheses:</p> <pre> "nested0" = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name, -N0n = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = "nested0a"},</pre> + N0n = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = "nested0a"},</pre> + <p>which is equivalent to:</p> + <pre> +"nested0" = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name, +N0n = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = "nested0a"},</pre> + <change><p>Before Erlang/OTP R14, parentheses were necessary when accessing or updating nested + records.</p></change> </section> <section> diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index 75482e5be1..e4b9c4f62c 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -314,11 +314,6 @@ <tcaption>Additional built-in types</tcaption> </table> - <p> - Users are not allowed to define types with the same names as the - predefined or built-in ones. This is checked by the compiler and - its violation results in a compilation error. - </p> <note> <p> The following built-in list types also exist, @@ -345,7 +340,35 @@ This is described in <seeguide marker="#typeinrecords"> Type Information in Record Declarations</seeguide>. </p> + + <section> + <title>Redefining built-in types</title> + <change><p> + Starting from Erlang/OTP 26, is is permitted to define a type + having the same name as a built-in type.</p></change> + <p>It is recommended to + avoid deliberately reusing built-in names because it can be + confusing. However, when an Erlang/OTP release introduces a new + type, code that happened to define its own type having the same + name will continue to work. + </p> + + <p>As an example, imagine that the Erlang/OTP 42 release introduces + a new type <c>gadget()</c> defined like this:</p> + + <pre> + -type gadget() :: {'gadget', reference()}.</pre> + + <p>Further imagine that some code has its own (different) + definition of <c>gadget()</c>, for example:</p> + + <pre> + -type gadget() :: #{}.</pre> + + <p>Since redefinitions are allowed, the code will still compile (but + with a warning), and Dialyzer will not emit any additional warnings.</p> </section> +</section> <section> <title>Type Declarations of User-Defined Types</title> @@ -441,7 +464,7 @@ This is checked by the compiler and results in a compilation error if a violation is detected. </p> - <note> + <change> <p>Before Erlang/OTP 19, for fields without initial values, the singleton type <c>'undefined'</c> was added to all declared types. In other words, the following two record declarations had identical @@ -458,7 +481,7 @@ This is no longer the case. If you require <c>'undefined'</c> in your record field type, you must explicitly add it to the typespec, as in the 2nd example. </p> - </note> + </change> <p> Any record, containing type information or not, once defined, can be used as a type using the following syntax: |