diff options
Diffstat (limited to 'lib/stdlib/doc')
-rw-r--r-- | lib/stdlib/doc/src/beam_lib.xml | 46 | ||||
-rw-r--r-- | lib/stdlib/doc/src/erl_tar.xml | 4 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gen_event.xml | 18 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gen_fsm.xml | 1090 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gen_server.xml | 19 | ||||
-rw-r--r-- | lib/stdlib/doc/src/gen_statem.xml | 201 | ||||
-rw-r--r-- | lib/stdlib/doc/src/io.xml | 6 | ||||
-rw-r--r-- | lib/stdlib/doc/src/io_lib.xml | 17 | ||||
-rw-r--r-- | lib/stdlib/doc/src/proc_lib.xml | 2 | ||||
-rw-r--r-- | lib/stdlib/doc/src/rand.xml | 155 | ||||
-rw-r--r-- | lib/stdlib/doc/src/re.xml | 320 | ||||
-rw-r--r-- | lib/stdlib/doc/src/sets.xml | 2 | ||||
-rw-r--r-- | lib/stdlib/doc/src/shell.xml | 25 | ||||
-rw-r--r-- | lib/stdlib/doc/src/string.xml | 741 | ||||
-rw-r--r-- | lib/stdlib/doc/src/supervisor.xml | 6 | ||||
-rw-r--r-- | lib/stdlib/doc/src/sys.xml | 28 | ||||
-rw-r--r-- | lib/stdlib/doc/src/unicode.xml | 179 | ||||
-rw-r--r-- | lib/stdlib/doc/src/unicode_usage.xml | 85 |
18 files changed, 1702 insertions, 1242 deletions
diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index d5ec90b060..031d79d0e2 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -42,10 +42,10 @@ and the corresponding identifiers are as follows:</p> <list type="bulleted"> - <item><c>abstract_code ("Abst")</c></item> <item><c>atoms ("Atom")</c></item> <item><c>attributes ("Attr")</c></item> <item><c>compile_info ("CInf")</c></item> + <item><c>debug_info ("Dbgi")</c></item> <item><c>exports ("ExpT")</c></item> <item><c>imports ("ImpT")</c></item> <item><c>indexed_imports ("ImpT")</c></item> @@ -60,9 +60,8 @@ <title>Debug Information/Abstract Code</title> <p>Option <c>debug_info</c> can be specified to the Compiler (see <seealso marker="compiler:compile#debug_info"><c>compile(3)</c></seealso>) - to have debug information in the form of abstract code (see section - <seealso marker="erts:absform">The Abstract Format</seealso> in the - ERTS User's Guide) stored in the <c>abstract_code</c> chunk. + to have debug information, such as <seealso marker="erts:absform">Erlang + Abstract Format</seealso>, stored in the <c>debug_info</c> chunk. Tools such as Debugger and Xref require the debug information to be included.</p> @@ -79,7 +78,7 @@ <section> <title>Reconstruct Source Code</title> - <p>The following example shows how to reconstruct source code from + <p>The following example shows how to reconstruct Erlang source code from the debug information in a BEAM file <c>Beam</c>:</p> <code type="none"> @@ -117,7 +116,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code> <list type="ordered"> <item> - <p>Use Compiler option <c>{debug_info,Key}</c>, see + <p>Use Compiler option <c>{debug_info_key,Key}</c>, see <seealso marker="compiler:compile#debug_info_key"><c>compile(3)</c></seealso> and function <seealso marker="#crypto_key_fun/1"><c>crypto_key_fun/1</c></seealso> @@ -198,18 +197,40 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code> <datatype> <name name="chunkid"/> <desc> - <p>"Abst" | "Attr" | "CInf" | "ExpT" | "ImpT" | "LocT" | "Atom"</p> + <p>"Attr" | "CInf" | "Dbgi" | "ExpT" | "ImpT" | "LocT" | "AtU8"</p> </desc> </datatype> <datatype> <name name="dataB"/> </datatype> <datatype> + <name name="debug_info"/> + <desc> + <p>The format stored in the <c>debug_info</c> chunk. + To retrieve particular code representation from the backend, + <c>Backend:debug_info(Format, Module, Data, Opts)</c> must be + invoked. <c>Format</c> is an atom, such as <c>erlang_v1</c> for + the Erlang Abstract Format or <c>core_v1</c> for Core Erlang. + <c>Module</c> is the module represented by the beam file and + <c>Data</c> is the value stored in the debug info chunk. + <c>Opts</c> is any list of values supported by the <c>Backend</c>. + <c>Backend:debug_info/4</c> must return <c>{ok, Code}</c> or + <c>{error, Term}</c>.</p> + + <p>Developers must always invoke the <c>debug_info/4</c> function + and never rely on the <c>Data</c> stored in the <c>debug_info</c> + chunk, as it is opaque and may change at any moment. <c>no_debug_info</c> + means that chunk <c>"Dbgi"</c> is present, but empty.</p> + </desc> + </datatype> + <datatype> <name name="abst_code"/> <desc> <p>It is not checked that the forms conform to the abstract format indicated by <c><anno>AbstVersion</anno></c>. <c>no_abstract_code</c> means that chunk <c>"Abst"</c> is present, but empty.</p> + <p>For modules compiled with OTP 20 onwards, the <c>abst_code</c> chunk + is automatically computed from the <c>debug_info</c> chunk.</p> </desc> </datatype> <datatype> @@ -346,7 +367,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code> <desc> <p>Registers an unary fun that is called if <c>beam_lib</c> must read an - <c>abstract_code</c> chunk that has been encrypted. The fun + <c>debug_info</c> chunk that has been encrypted. The fun is held in a process that is started by the function.</p> <p>If a fun is already registered when attempting to register a fun, <c>{error, exists}</c> is returned.</p> @@ -443,7 +464,8 @@ CryptoKeyFun(clear) -> term()</code> <desc> <p>Removes all chunks from a BEAM file except those needed by the loader. In particular, - the debug information (chunk <c>abstract_code</c>) is removed.</p> + the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>) + is removed.</p> </desc> </func> @@ -454,9 +476,9 @@ CryptoKeyFun(clear) -> term()</code> <desc> <p>Removes all chunks except those needed by the loader from BEAM files. In particular, - the debug information (chunk <c>abstract_code</c>) is removed. - The returned list contains one element for each specified filename, - in the same order as in <c>Files</c>.</p> + the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>) + is removed. The returned list contains one element for each + specified filename, in the same order as in <c>Files</c>.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml index f28d8b425b..fab7c832d5 100644 --- a/lib/stdlib/doc/src/erl_tar.xml +++ b/lib/stdlib/doc/src/erl_tar.xml @@ -292,6 +292,10 @@ <c>Fd</c> is assumed to be a file descriptor returned from function <c>file:open/2</c>.</p> <p>Otherwise, <c>Name</c> is to be a filename.</p> + <note><p>Leading slashes in tar member names will be removed before + writing the file. That is, absolute paths will be turned into + relative paths. There will be an info message written to the error + logger when paths are changed in this way.</p></note> </desc> </func> diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 42e952fd46..56cb7974a2 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -579,6 +579,13 @@ gen_event:stop -----> Module:terminate/2 <v>Extra = term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not export it. + If a release upgrade/downgrade with <c>Change={advanced,Extra}</c> + specified in the <c>.appup</c> file is made when <c>code_change/3</c> + isn't implemented the event handler will crash with an <c>undef</c> error + reason.</p> + </note> <p>This function is called for an installed event handler that is to update its internal state during a release upgrade/downgrade, that is, when the instruction @@ -759,6 +766,12 @@ gen_event:stop -----> Module:terminate/2 <v> Id = term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_event</c> module provides a default + implementation of this function that logs about the unexpected + <c>Info</c> message, drops it and returns <c>{noreply, State}</c>.</p> + </note> <p>This function is called for each installed event handler when an event manager receives any other message than an event or a synchronous request (or a system message).</p> @@ -815,6 +828,11 @@ gen_event:stop -----> Module:terminate/2 <v> Args = Reason = Term = term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_event</c> module provides a default + implementation without cleanup.</p> + </note> <p>Whenever an event handler is deleted from an event manager, this function is called. It is to be the opposite of <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml index 719ab2b558..7187630b43 100644 --- a/lib/stdlib/doc/src/gen_fsm.xml +++ b/lib/stdlib/doc/src/gen_fsm.xml @@ -4,14 +4,14 @@ <erlref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996-2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software @@ -29,926 +29,176 @@ <rev></rev> </header> <module>gen_fsm</module> - <modulesummary>Generic finite state machine behavior.</modulesummary> - <description> - <note> - <p> - There is a new behaviour - <seealso marker="gen_statem"><c>gen_statem</c></seealso> - that is intended to replace <c>gen_fsm</c> for new code. - <c>gen_fsm</c> will not be removed for the foreseeable future - to keep old state machine implementations running. - </p> - </note> - <p>This behavior module provides a finite state machine. - A generic finite state machine process (<c>gen_fsm</c>) implemented - using this module has a standard set of interface functions - and includes functionality for tracing and error reporting. It - also fits into an OTP supervision tree. For more information, see - <seealso marker="doc/design_principles:fsm">OTP Design Principles</seealso>. - </p> - - <p>A <c>gen_fsm</c> process assumes all specific parts to be located in a - callback module exporting a predefined set of functions. The relationship - between the behavior functions and the callback functions is as - follows:</p> - - <pre> -gen_fsm module Callback module --------------- --------------- -gen_fsm:start -gen_fsm:start_link -----> Module:init/1 - -gen_fsm:stop -----> Module:terminate/3 - -gen_fsm:send_event -----> Module:StateName/2 - -gen_fsm:send_all_state_event -----> Module:handle_event/3 - -gen_fsm:sync_send_event -----> Module:StateName/3 - -gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4 - -- -----> Module:handle_info/3 - -- -----> Module:terminate/3 + <modulesummary>Deprecated and replaced by gen_statem </modulesummary> -- -----> Module:code_change/4</pre> - - <p>If a callback function fails or returns a bad value, the <c>gen_fsm</c> - process terminates.</p> - - <p>A <c>gen_fsm</c> process handles system messages as described in - <seealso marker="sys"><c>sys(3)</c></seealso>. The <c>sys</c> module - can be used for debugging a <c>gen_fsm</c> process.</p> - - <p>Notice that a <c>gen_fsm</c> process does not trap exit signals - automatically, this must be explicitly initiated in the callback - module.</p> - - <p>Unless otherwise stated, all functions in this module fail if - the specified <c>gen_fsm</c> process does not exist or if bad arguments - are specified.</p> - - <p>The <c>gen_fsm</c> process can go into hibernation - (see <seealso marker="erts:erlang#hibernate/3"> - <c>erlang:hibernate/3</c></seealso>) if a callback function - specifies <c>'hibernate'</c> instead of a time-out value. This - can be useful if the server is expected to be idle for a long - time. However, use this feature with care, as hibernation - implies at least two garbage collections (when hibernating and - shortly after waking up) and is not something you want to do - between each call to a busy state machine.</p> + <description> + <p> Deprecated and replaced by <seealso marker="gen_statem"><c>gen_statem</c></seealso> </p> </description> - - <funcs> - <func> - <name>cancel_timer(Ref) -> RemainingTime | false</name> - <fsummary>Cancel an internal timer in a generic FSM.</fsummary> - <type> - <v>Ref = reference()</v> - <v>RemainingTime = integer()</v> - </type> - <desc> - <p>Cancels an internal timer referred by <c>Ref</c> in the - <c>gen_fsm</c> process that calls this function.</p> - <p><c>Ref</c> is a reference returned from - <seealso marker="#send_event_after/2"> - <c>send_event_after/2</c></seealso> or - <seealso marker="#start_timer/2"><c>start_timer/2</c></seealso>.</p> - <p>If the timer has already timed out, but the event not yet - been delivered, it is cancelled as if it had <em>not</em> - timed out, so there is no false timer event after - returning from this function.</p> - <p>Returns the remaining time in milliseconds until the timer would - have expired if <c>Ref</c> referred to an active timer, otherwise - <c>false</c>.</p> - </desc> - </func> - - <func> - <name>enter_loop(Module, Options, StateName, StateData)</name> - <name>enter_loop(Module, Options, StateName, StateData, FsmName)</name> - <name>enter_loop(Module, Options, StateName, StateData, Timeout)</name> - <name>enter_loop(Module, Options, StateName, StateData, FsmName, Timeout)</name> - <fsummary>Enter the <c>gen_fsm</c> receive loop.</fsummary> - <type> - <v>Module = atom()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>FsmName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Timeout = int() | infinity</v> - </type> - <desc> - <p>Makes an existing process into a <c>gen_fsm</c> process. - Does not return, - instead the calling process enters the <c>gen_fsm</c> receive - loop and becomes a <c>gen_fsm</c> process. The process <em>must</em> - have been started using one of the start functions in - <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>. The user is - responsible for any initialization of the process, including - registering a name for it.</p> - <p>This function is useful when a more complex initialization - procedure is needed than the <c>gen_fsm</c> behavior provides.</p> - <p><c>Module</c>, <c>Options</c>, and <c>FsmName</c> have - the same meanings as when calling - <seealso marker="#start_link/3"><c>start[_link]/3,4</c></seealso>. - However, if <c>FsmName</c> is specified, the process must have - been registered accordingly <em>before</em> this function is - called.</p> - <p><c>StateName</c>, <c>StateData</c>, and <c>Timeout</c> have - the same meanings as in the return value of - <seealso marker="#Moduleinit"><c>Module:init/1</c></seealso>. - The callback module <c>Module</c> does not need to - export an <c>init/1</c> function.</p> - <p>The function fails if the calling process was not started by a - <c>proc_lib</c> start function, or if it is not registered - according to <c>FsmName</c>.</p> - </desc> - </func> - - <func> - <name>reply(Caller, Reply) -> Result</name> - <fsummary>Send a reply to a caller.</fsummary> - <type> - <v>Caller - see below</v> - <v>Reply = term()</v> - <v>Result = term()</v> - </type> - <desc> - <p>This function can be used by a <c>gen_fsm</c> process to - explicitly send a reply to a client process that called - <seealso marker="#sync_send_event/2"> - <c>sync_send_event/2,3</c></seealso> or - <seealso marker="#sync_send_all_state_event/2"> - <c>sync_send_all_state_event/2,3</c></seealso> - when the reply cannot be defined in the return value of - <seealso marker="#Module:StateName/3"> - <c>Module:StateName/3</c></seealso> or - <seealso marker="#Module:handle_sync_event/4"> - <c>Module:handle_sync_event/4</c></seealso>.</p> - <p><c>Caller</c> must be the <c>From</c> argument provided to - the callback function. <c>Reply</c> is any term - given back to the client as the return value of - <c>sync_send_event/2,3</c> or - <c>sync_send_all_state_event/2,3</c>.</p> - <p>Return value <c>Result</c> is not further defined, and - is always to be ignored.</p> - </desc> - </func> - - <func> - <name>send_all_state_event(FsmRef, Event) -> ok</name> - <fsummary>Send an event asynchronously to a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - </type> - <desc> - <p>Sends an event asynchronously to the <c>FsmRef</c> of the - <c>gen_fsm</c> process and returns <c>ok</c> immediately. - The <c>gen_fsm</c> process calls - <seealso marker="#Module:handle_event/3"> - <c>Module:handle_event/3</c></seealso> to handle the event.</p> - <p>For a description of the arguments, see - <seealso marker="#send_event/2"><c>send_event/2</c></seealso>.</p> - <p>The difference between <c>send_event/2</c> and - <c>send_all_state_event/2</c> is which callback function is - used to handle the event. This function is useful when - sending events that are handled the same way in every state, - as only one <c>handle_event</c> clause is needed to handle - the event instead of one clause in each state name function.</p> - </desc> - </func> - - <func> - <name>send_event(FsmRef, Event) -> ok</name> - <fsummary>Send an event asynchronously to a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - </type> - <desc> - <p>Sends an event asynchronously to the <c>FsmRef</c> of the - <c>gen_fsm</c> process - and returns <c>ok</c> immediately. The <c>gen_fsm</c> process calls - <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso> to handle the event, where - <c>StateName</c> is the name of the current state of - the <c>gen_fsm</c> process.</p> - <p><c>FsmRef</c> can be any of the following:</p> - <list type="bulleted"> - <item>The pid</item> - <item><c>Name</c>, if the <c>gen_fsm</c> process is locally - registered</item> - <item><c>{Name,Node}</c>, if the <c>gen_fsm</c> process is locally - registered at another node</item> - <item><c>{global,GlobalName}</c>, if the <c>gen_fsm</c> process is - globally registered</item> - <item><c>{via,Module,ViaName}</c>, if the <c>gen_fsm</c> process is - registered through an alternative process registry</item> - </list> - <p><c>Event</c> is any term that is passed as one of - the arguments to <c>Module:StateName/2</c>.</p> - </desc> - </func> - - <func> - <name>send_event_after(Time, Event) -> Ref</name> - <fsummary>Send a delayed event internally in a generic FSM.</fsummary> - <type> - <v>Time = integer()</v> - <v>Event = term()</v> - <v>Ref = reference()</v> - </type> - <desc> - <p>Sends a delayed event internally in the <c>gen_fsm</c> process - that calls this function after <c>Time</c> milliseconds. - Returns immediately a - reference that can be used to cancel the delayed send using - <seealso marker="#cancel_timer/1"><c>cancel_timer/1</c></seealso>.</p> - <p>The <c>gen_fsm</c> process calls - <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso> to handle - the event, where <c>StateName</c> is the name of the current - state of the <c>gen_fsm</c> process at the time the delayed event is - delivered.</p> - <p><c>Event</c> is any term that is passed as one of - the arguments to <c>Module:StateName/2</c>.</p> - </desc> - </func> - - <func> - <name>start(Module, Args, Options) -> Result</name> - <name>start(FsmName, Module, Args, Options) -> Result</name> - <fsummary>Create a standalone <c>gen_fsm</c> process.</fsummary> - <type> - <v>FsmName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [term()]</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> - <desc> - <p>Creates a standalone <c>gen_fsm</c> process, that is, a process that - is not part of a supervision tree and thus has no supervisor.</p> - <p>For a description of arguments and return values, see - <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>.</p> - </desc> - </func> - - <func> - <name>start_link(Module, Args, Options) -> Result</name> - <name>start_link(FsmName, Module, Args, Options) -> Result</name> - <fsummary>Create a <c>gen_fsm</c> process in a supervision tree. - </fsummary> - <type> - <v>FsmName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [SOpt]</v> - <v> SOpt - see erlang:spawn_opt/2,3,4,5</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> - <desc> - <p>Creates a <c>gen_fsm</c> process as part of a supervision tree. - The function is to be called, directly or indirectly, by - the supervisor. For example, it ensures that - the <c>gen_fsm</c> process is linked to the supervisor.</p> - <p>The <c>gen_fsm</c> process calls - <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> to - initialize. To ensure a synchronized startup procedure, - <c>start_link/3,4</c> does not return until - <c>Module:init/1</c> has returned.</p> - <list type="bulleted"> - <item> - <p>If <c>FsmName={local,Name}</c>, the <c>gen_fsm</c> process is - registered locally as <c>Name</c> using <c>register/2</c>.</p> - </item> - <item> - <p>If <c>FsmName={global,GlobalName}</c>, the <c>gen_fsm</c> process - is registered globally as <c>GlobalName</c> using - <seealso marker="kernel:global#register_name/2"> - <c>global:register_name/2</c></seealso>.</p> - </item> - <item> - <p>If <c>FsmName={via,Module,ViaName}</c>, the <c>gen_fsm</c> - process registers with the registry represented by <c>Module</c>. - The <c>Module</c> callback is to export the functions - <c>register_name/2</c>, <c>unregister_name/1</c>, - <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave - like the corresponding functions in - <seealso marker="kernel:global"><c>global</c></seealso>. - Thus, <c>{via,global,GlobalName}</c> is a valid reference.</p> - </item> - </list> - <p>If no name is provided, the <c>gen_fsm</c> process is not - registered.</p> - <p><c>Module</c> is the name of the callback module.</p> - <p><c>Args</c> is any term that is passed as - the argument to <c>Module:init/1</c>.</p> - <p>If option <c>{timeout,Time}</c> is present, the <c>gen_fsm</c> - process is allowed to spend <c>Time</c> milliseconds initializing - or it terminates and the start function returns - <c>{error,timeout}</c>.</p> - <p>If option <c>{debug,Dbgs}</c> is present, the corresponding - <c>sys</c> function is called for each item in <c>Dbgs</c>; see - <seealso marker="sys"><c>sys(3)</c></seealso>.</p> - <p>If option <c>{spawn_opt,SOpts}</c> is present, <c>SOpts</c> is - passed as option list to the <c>spawn_opt</c> BIF that is used to - spawn the <c>gen_fsm</c> process; see - <seealso marker="erts:erlang#spawn_opt/2"> - <c>spawn_opt/2</c></seealso>.</p> - <note> - <p>Using spawn option <c>monitor</c> is not - allowed, it causes the function to fail with reason - <c>badarg</c>.</p> - </note> - <p>If the <c>gen_fsm</c> process is successfully created and - initialized, the function returns <c>{ok,Pid}</c>, where <c>Pid</c> - is the pid of the <c>gen_fsm</c> process. If a process with the - specified <c>FsmName</c> exists already, the function returns - <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is - the pid of that process.</p> - <p>If <c>Module:init/1</c> fails with <c>Reason</c>, - the function returns <c>{error,Reason}</c>. If - <c>Module:init/1</c> returns <c>{stop,Reason}</c> or - <c>ignore</c>, the process is terminated and the function - returns <c>{error,Reason}</c> or <c>ignore</c>, respectively.</p> - </desc> - </func> - - <func> - <name>start_timer(Time, Msg) -> Ref</name> - <fsummary>Send a time-out event internally in a generic FSM.</fsummary> - <type> - <v>Time = integer()</v> - <v>Msg = term()</v> - <v>Ref = reference()</v> - </type> - <desc> - <p>Sends a time-out event internally in the <c>gen_fsm</c> - process that calls this function after <c>Time</c> milliseconds. - Returns immediately a - reference that can be used to cancel the timer using - <seealso marker="#cancel_timer/1"><c>cancel_timer/1</c></seealso>.</p> - <p>The <c>gen_fsm</c> process calls - <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso> to handle - the event, where <c>StateName</c> is the name of the current - state of the <c>gen_fsm</c> process at the time the time-out - message is delivered.</p> - <p><c>Msg</c> is any term that is passed in the - time-out message, <c>{timeout, Ref, Msg}</c>, as one of - the arguments to <c>Module:StateName/2</c>.</p> - </desc> - </func> - - <func> - <name>stop(FsmRef) -> ok</name> - <name>stop(FsmRef, Reason, Timeout) -> ok</name> - <fsummary>Synchronously stop a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Reason = term()</v> - <v>Timeout = int()>0 | infinity</v> - </type> - <desc> - <p>Orders a generic finite state machine to exit with the specified - <c>Reason</c> and waits for it to terminate. The <c>gen_fsm</c> - process calls <seealso marker="#Module:terminate/3"> - <c>Module:terminate/3</c></seealso> before exiting.</p> - <p>The function returns <c>ok</c> if the generic finite state machine - terminates with the expected reason. Any other reason than - <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c> causes an - error report to be issued using - <seealso marker="kernel:error_logger#format/2"> - <c>error_logger:format/2</c></seealso>. - The default <c>Reason</c> is <c>normal</c>.</p> - <p><c>Timeout</c> is an integer greater than zero that - specifies how many milliseconds to wait for the generic FSM - to terminate, or the atom <c>infinity</c> to wait - indefinitely. The default value is <c>infinity</c>. If the - generic finite state machine has not terminated within the specified - time, a <c>timeout</c> exception is raised.</p> - <p>If the process does not exist, a <c>noproc</c> exception - is raised.</p> - </desc> - </func> - - <func> - <name>sync_send_all_state_event(FsmRef, Event) -> Reply</name> - <name>sync_send_all_state_event(FsmRef, Event, Timeout) -> Reply</name> - <fsummary>Send an event synchronously to a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - <v>Timeout = int()>0 | infinity</v> - <v>Reply = term()</v> - </type> - <desc> - <p>Sends an event to the <c>FsmRef</c> of the <c>gen_fsm</c> - process and waits until a reply arrives or a time-out occurs. - The <c>gen_fsm</c> process calls - <seealso marker="#Module:handle_sync_event/4"> - <c>Module:handle_sync_event/4</c></seealso> to handle the event.</p> - <p>For a description of <c>FsmRef</c> and <c>Event</c>, see - <seealso marker="#send_event/2">send_event/2</seealso>. - For a description of <c>Timeout</c> and <c>Reply</c>, see - <seealso marker="#sync_send_event/3"> - <c>sync_send_event/3</c></seealso>.</p> - <p>For a discussion about the difference between - <c>sync_send_event</c> and <c>sync_send_all_state_event</c>, see - <seealso marker="#send_all_state_event/2"> - <c>send_all_state_event/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name>sync_send_event(FsmRef, Event) -> Reply</name> - <name>sync_send_event(FsmRef, Event, Timeout) -> Reply</name> - <fsummary>Send an event synchronously to a generic FSM.</fsummary> - <type> - <v>FsmRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Name = Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Event = term()</v> - <v>Timeout = int()>0 | infinity</v> - <v>Reply = term()</v> - </type> - <desc> - <p>Sends an event to the <c>FsmRef</c> of the <c>gen_fsm</c> - process and waits until a reply arrives or a time-out occurs. - <c>The gen_fsm</c> process calls - <seealso marker="#Module:StateName/3"> - <c>Module:StateName/3</c></seealso> to handle the event, where - <c>StateName</c> is the name of the current state of - the <c>gen_fsm</c> process.</p> - <p>For a description of <c>FsmRef</c> and <c>Event</c>, see - <seealso marker="#send_event/2"><c>send_event/2</c></seealso>.</p> - <p><c>Timeout</c> is an integer greater than zero that - specifies how many milliseconds to wait for a reply, or - the atom <c>infinity</c> to wait indefinitely. Defaults - to 5000. If no reply is received within the specified time, - the function call fails.</p> - <p>Return value <c>Reply</c> is defined in the return value - of <c>Module:StateName/3</c>.</p> - </desc> - </func> - </funcs> - - <section> - <title>Callback Functions</title> - <p>The following functions are to be exported from a <c>gen_fsm</c> - callback module.</p> - - <p><em>state name</em> denotes a state of the state machine.</p> - - <p><em>state data</em> denotes the internal state of the Erlang process - that implements the state machine.</p> - </section> - - <funcs> - <func> - <name>Module:code_change(OldVsn, StateName, StateData, Extra) -> {ok, NextStateName, NewStateData}</name> - <fsummary>Update the internal state data during upgrade/downgrade. - </fsummary> - <type> - <v>OldVsn = Vsn | {down, Vsn}</v> - <v> Vsn = term()</v> - <v>StateName = NextStateName = atom()</v> - <v>StateData = NewStateData = term()</v> - <v>Extra = term()</v> - </type> - <desc> - <p>This function is called by a <c>gen_fsm</c> process when it is to - update its internal state data during a release upgrade/downgrade, - that is, when instruction <c>{update,Module,Change,...}</c>, - where <c>Change={advanced,Extra}</c>, is given in - the <c>appup</c> file; see section - <seealso marker="doc/design_principles:release_handling#instr"> - Release Handling Instructions</seealso> in OTP Design Principles.</p> - <p>For an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and for a downgrade, - <c>OldVsn</c> is <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the - <c>vsn</c> attribute(s) of the old version of the callback module - <c>Module</c>. If no such attribute is defined, the version is - the checksum of the Beam file.</p> - <p><c>StateName</c> is the current state name and <c>StateData</c> the - internal state data of the <c>gen_fsm</c> process.</p> - <p><c>Extra</c> is passed "as is" from the <c>{advanced,Extra}</c> - part of the update instruction.</p> - <p>The function is to return the new current state name and - updated internal data.</p> - </desc> - </func> - - <func> - <name>Module:format_status(Opt, [PDict, StateData]) -> Status</name> - <fsummary>Optional function for providing a term describing the - current <c>gen_fsm</c> process status.</fsummary> - <type> - <v>Opt = normal | terminate</v> - <v>PDict = [{Key, Value}]</v> - <v>StateData = term()</v> - <v>Status = term()</v> - </type> - <desc> - <note> - <p>This callback is optional, so callback modules need not - export it. The <c>gen_fsm</c> module provides a default - implementation of this function that returns the callback - module state data.</p> - </note> - <p>This function is called by a <c>gen_fsm</c> process in the - following situations:</p> - <list type="bulleted"> - <item>One of <seealso marker="sys#get_status/1"> - <c>sys:get_status/1,2</c></seealso> - is invoked to get the <c>gen_fsm</c> status. <c>Opt</c> is set to - the atom <c>normal</c> for this case.</item> - <item>The <c>gen_fsm</c> process terminates abnormally and logs an - error. <c>Opt</c> is set to the atom <c>terminate</c> for - this case.</item> - </list> - <p>This function is useful for changing the form and - appearance of the <c>gen_fsm</c> status for these cases. A callback - module wishing to change the <c>sys:get_status/1,2</c> - return value as well as how its status appears in - termination error logs, exports an instance - of <c>format_status/2</c> that returns a term describing the - current status of the <c>gen_fsm</c> process.</p> - <p><c>PDict</c> is the current value of the process dictionary of the - <c>gen_fsm</c> process.</p> - <p><c>StateData</c> is the internal state data of the - <c>gen_fsm</c> process.</p> - <p>The function is to return <c>Status</c>, a term that - change the details of the current state and status of - the <c>gen_fsm</c> process. There are no restrictions on the - form <c>Status</c> can take, but for - the <c>sys:get_status/1,2</c> case (when <c>Opt</c> - is <c>normal</c>), the recommended form for - the <c>Status</c> value is <c>[{data, [{"StateData", - Term}]}]</c>, where <c>Term</c> provides relevant details of - the <c>gen_fsm</c> state data. Following this recommendation is not - required, but it makes the callback module status - consistent with the rest of the <c>sys:get_status/1,2</c> - return value.</p> - <p>One use for this function is to return compact alternative - state data representations to avoid that large state terms - are printed in log files.</p> - </desc> - </func> - - <func> - <name>Module:handle_event(Event, StateName, StateData) -> Result</name> - <fsummary>Handle an asynchronous event.</fsummary> - <type> - <v>Event = term()</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,NewStateData}</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <p>Whenever a <c>gen_fsm</c> process receives an event sent using - <seealso marker="#send_all_state_event/2"> - <c>send_all_state_event/2</c></seealso>, - this function is called to handle the event.</p> - <p><c>StateName</c> is the current state name of the <c>gen_fsm</c> - process.</p> - <p>For a description of the other arguments and possible return values, - see <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name>Module:handle_info(Info, StateName, StateData) -> Result</name> - <fsummary>Handle an incoming message.</fsummary> - <type> - <v>Info = term()</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,NewStateData}</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = normal | term()</v> - </type> - <desc> - <p>This function is called by a <c>gen_fsm</c> process when it receives - any other message than a synchronous or asynchronous event (or a - system message).</p> - <p><c>Info</c> is the received message.</p> - <p>For a description of the other arguments and possible return values, - see <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name>Module:handle_sync_event(Event, From, StateName, StateData) -> Result</name> - <fsummary>Handle a synchronous event.</fsummary> - <type> - <v>Event = term()</v> - <v>From = {pid(),Tag}</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - <v>Result = {reply,Reply,NextStateName,NewStateData}</v> - <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> - <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> - <v> | {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}</v> - <v> Reply = term()</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <p>Whenever a <c>gen_fsm</c> process receives an event sent using - <seealso marker="#sync_send_all_state_event/2"> - <c>sync_send_all_state_event/2,3</c></seealso>, - this function is called to handle the event.</p> - <p><c>StateName</c> is the current state name of the <c>gen_fsm</c> - process.</p> - <p>For a description of the other arguments and possible return values, - see <seealso marker="#Module:StateName/3"> - <c>Module:StateName/3</c></seealso>.</p> - </desc> - </func> - - <func> - <name>Module:init(Args) -> Result</name> - <fsummary>Initialize process and internal state name and state data. - </fsummary> - <type> - <v>Args = term()</v> - <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v> - <v> | {ok,StateName,StateData,hibernate}</v> - <v> | {stop,Reason} | ignore</v> - <v> StateName = atom()</v> - <v> StateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <marker id="Moduleinit"></marker> - <p>Whenever a <c>gen_fsm</c> process is started using - <seealso marker="#start/3"><c>start/3,4</c></seealso> or - <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>, - this function is called by the new process to initialize.</p> - <p><c>Args</c> is the <c>Args</c> argument provided to the start - function.</p> - <p>If initialization is successful, the function is to return - <c>{ok,StateName,StateData}</c>, - <c>{ok,StateName,StateData,Timeout}</c>, or - <c>{ok,StateName,StateData,hibernate}</c>, where <c>StateName</c> - is the initial state name and <c>StateData</c> the initial - state data of the <c>gen_fsm</c> process.</p> - <p>If an integer time-out value is provided, a time-out occurs - unless an event or a message is received within <c>Timeout</c> - milliseconds. A time-out is represented by the atom - <c>timeout</c> and is to be handled by the - <seealso marker="#Module:StateName/2"> - <c>Module:StateName/2</c></seealso> callback functions. The atom - <c>infinity</c> can be used to wait indefinitely, this is - the default value.</p> - <p>If <c>hibernate</c> is specified instead of a time-out value, the - process goes into hibernation when waiting for the next message - to arrive (by calling <seealso marker="proc_lib#hibernate/3"> - <c>proc_lib:hibernate/3</c></seealso>).</p> - <p>If the initialization fails, the function returns - <c>{stop,Reason}</c>, where <c>Reason</c> is any term, - or <c>ignore</c>.</p> - </desc> - </func> - - <func> - <name>Module:StateName(Event, StateData) -> Result</name> - <fsummary>Handle an asynchronous event.</fsummary> - <type> - <v>Event = timeout | term()</v> - <v>StateData = term()</v> - <v>Result = {next_state,NextStateName,NewStateData} </v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,NewStateData}</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = term()</v> - </type> - <desc> - <p>There is to be one instance of this function for each - possible state name. Whenever a <c>gen_fsm</c> process receives - an event sent using - <seealso marker="#send_event/2"><c>send_event/2</c></seealso>, - the instance of this function with the same name as - the current state name <c>StateName</c> is called to handle - the event. It is also called if a time-out occurs.</p> - <p><c>Event</c> is either the atom <c>timeout</c>, if a time-out - has occurred, or the <c>Event</c> argument provided to - <c>send_event/2</c>.</p> - <p><c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> - <p>If the function returns - <c>{next_state,NextStateName,NewStateData}</c>, - <c>{next_state,NextStateName,NewStateData,Timeout}</c>, or - <c>{next_state,NextStateName,NewStateData,hibernate}</c>, the - <c>gen_fsm</c> process continues executing with the current state - name set to <c>NextStateName</c> and with the possibly - updated state data <c>NewStateData</c>. For a description of - <c>Timeout</c> and <c>hibernate</c>, see - <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.</p> - <p>If the function returns <c>{stop,Reason,NewStateData}</c>, - the <c>gen_fsm</c> process calls - <c>Module:terminate(Reason,StateName,NewStateData)</c> and - terminates.</p> - </desc> - </func> - - <func> - <name>Module:StateName(Event, From, StateData) -> Result</name> - <fsummary>Handle a synchronous event.</fsummary> - <type> - <v>Event = term()</v> - <v>From = {pid(),Tag}</v> - <v>StateData = term()</v> - <v>Result = {reply,Reply,NextStateName,NewStateData}</v> - <v> | {reply,Reply,NextStateName,NewStateData,Timeout}</v> - <v> | {reply,Reply,NextStateName,NewStateData,hibernate}</v> - <v> | {next_state,NextStateName,NewStateData}</v> - <v> | {next_state,NextStateName,NewStateData,Timeout}</v> - <v> | {next_state,NextStateName,NewStateData,hibernate}</v> - <v> | {stop,Reason,Reply,NewStateData} | {stop,Reason,NewStateData}</v> - <v> Reply = term()</v> - <v> NextStateName = atom()</v> - <v> NewStateData = term()</v> - <v> Timeout = int()>0 | infinity</v> - <v> Reason = normal | term()</v> - </type> - <desc> - <p>There is to be one instance of this function for each - possible state name. Whenever a <c>gen_fsm</c> process receives an - event sent using <seealso marker="#sync_send_event/2"> - <c>sync_send_event/2,3</c></seealso>, - the instance of this function with the same name as - the current state name <c>StateName</c> is called to handle - the event.</p> - <p><c>Event</c> is the <c>Event</c> argument provided to - <c>sync_send_event/2,3</c>.</p> - <p><c>From</c> is a tuple <c>{Pid,Tag}</c> where <c>Pid</c> is - the pid of the process that called <c>sync_send_event/2,3</c> - and <c>Tag</c> is a unique tag.</p> - <p><c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> - <list type="bulleted"> - <item> - <p>If <c>{reply,Reply,NextStateName,NewStateData}</c>, - <c>{reply,Reply,NextStateName,NewStateData,Timeout}</c>, or - <c>{reply,Reply,NextStateName,NewStateData,hibernate}</c> is - returned, <c>Reply</c> is given back to <c>From</c> as the return - value of <c>sync_send_event/2,3</c>. The <c>gen_fsm</c> process - then continues executing with the current state name set to - <c>NextStateName</c> and with the possibly updated state data - <c>NewStateData</c>. For a description of <c>Timeout</c> and - <c>hibernate</c>, see - <seealso marker="#Module:init/1"> - <c>Module:init/1</c></seealso>.</p> - </item> - <item> - <p>If <c>{next_state,NextStateName,NewStateData}</c>, - <c>{next_state,NextStateName,NewStateData,Timeout}</c>, or - <c>{next_state,NextStateName,NewStateData,hibernate}</c> is - returned, the <c>gen_fsm</c> process continues executing in - <c>NextStateName</c> with <c>NewStateData</c>. - Any reply to <c>From</c> must be specified explicitly using - <seealso marker="#reply/2"><c>reply/2</c></seealso>.</p> - </item> - <item> - <p>If the function returns - <c>{stop,Reason,Reply,NewStateData}</c>, <c>Reply</c> is - given back to <c>From</c>. If the function returns - <c>{stop,Reason,NewStateData}</c>, any reply to <c>From</c> - must be specified explicitly using <c>reply/2</c>. - The <c>gen_fsm</c> process then calls - <c>Module:terminate(Reason,StateName,NewStateData)</c> and - terminates.</p> - </item> - </list> - </desc> - </func> - - <func> - <name>Module:terminate(Reason, StateName, StateData)</name> - <fsummary>Clean up before termination.</fsummary> - <type> - <v>Reason = normal | shutdown | {shutdown,term()} | term()</v> - <v>StateName = atom()</v> - <v>StateData = term()</v> - </type> - <desc> - <p>This function is called by a <c>gen_fsm</c> process when it is about - to terminate. It is to be the opposite of - <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> - and do any necessary cleaning up. When it returns, the <c>gen_fsm</c> - process terminates with <c>Reason</c>. The return value is ignored. - </p> - <p><c>Reason</c> is a term denoting the stop reason, - <c>StateName</c> is the current state name, and - <c>StateData</c> is the state data of the <c>gen_fsm</c> process.</p> - <p><c>Reason</c> depends on why the <c>gen_fsm</c> process is - terminating. If - it is because another callback function has returned a stop - tuple <c>{stop,..}</c>, <c>Reason</c> has the value - specified in that tuple. If it is because of a failure, - <c>Reason</c> is the error reason.</p> - <p>If the <c>gen_fsm</c> process is part of a supervision tree and is - ordered by its supervisor to terminate, this function is called - with <c>Reason=shutdown</c> if the following conditions apply:</p> - <list type="bulleted"> - <item> - <p>The <c>gen_fsm</c> process has been set to trap exit signals.</p> - </item> - <item> - <p>The shutdown strategy as defined in the child specification of - the supervisor is an integer time-out value, not - <c>brutal_kill</c>.</p> - </item> - </list> - <p>Even if the <c>gen_fsm</c> process is <em>not</em> part of a - supervision tree, - this function is called if it receives an <c>'EXIT'</c> - message from its parent. <c>Reason</c> is the same as in - the <c>'EXIT'</c> message.</p> - <p>Otherwise, the <c>gen_fsm</c> process terminates immediately.</p> - <p>Notice that for any other reason than <c>normal</c>, - <c>shutdown</c>, or <c>{shutdown,Term}</c> the <c>gen_fsm</c> process - is assumed to terminate because of an error and an error report is - issued using <seealso marker="kernel:error_logger#format/2"> - <c>error_logger:format/2</c></seealso>.</p> - </desc> - </func> - </funcs> - <section> - <title>See Also</title> - <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>, - <seealso marker="gen_server"><c>gen_server(3)</c></seealso>, - <seealso marker="gen_statem"><c>gen_statem(3)</c></seealso>, - <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>, - <seealso marker="supervisor"><c>supervisor(3)</c></seealso>, - <seealso marker="sys"><c>sys(3)</c></seealso></p> + <marker id="Migration to gen_statem"/> + <title>Migration to gen_statem</title> + + <p>Here follows a simple example of turning a gen_fsm into + a <seealso marker="gen_statem"><c>gen_statem</c></seealso>. The example comes + from the previous Users Guide for <c>gen_fsm</c> </p> + + <code type="erl"> +-module(code_lock). +-define(NAME, code_lock). +%-define(BEFORE_REWRITE, true). + +-ifdef(BEFORE_REWRITE). +-behaviour(gen_fsm). +-else. +-behaviour(gen_statem). +-endif. + +-export([start_link/1, button/1, stop/0]). + +-ifdef(BEFORE_REWRITE). +-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3, + handle_info/3, terminate/3, code_change/4]). +-else. +-export([init/1, callback_mode/0, locked/3, open/3, terminate/3, code_change/4]). +%% Add callback__mode/0 +%% Change arity of the state functions +%% Remove handle_info/3 +-endif. + +-ifdef(BEFORE_REWRITE). +start_link(Code) -> + gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []). +-else. +start_link(Code) -> + gen_statem:start_link({local,?NAME}, ?MODULE, Code, []). +-endif. + +-ifdef(BEFORE_REWRITE). +button(Digit) -> + gen_fsm:send_event(?NAME, {button, Digit}). +-else. +button(Digit) -> + gen_statem:cast(?NAME, {button,Digit}). + %% send_event is asynchronous and becomes a cast +-endif. + +-ifdef(BEFORE_REWRITE). +stop() -> + gen_fsm:sync_send_all_state_event(?NAME, stop). +-else. +stop() -> + gen_statem:call(?NAME, stop). + %% sync_send is synchronous and becomes call + %% all_state is handled by callback code in gen_statem +-endif. + +init(Code) -> + do_lock(), + Data = #{code => Code, remaining => Code}, + {ok, locked, Data}. + +-ifdef(BEFORE_REWRITE). +-else. +callback_mode() -> + state_functions. +%% state_functions mode is the mode most similar to +%% gen_fsm. There is also handle_event mode which is +%% a fairly different concept. +-endif. + +-ifdef(BEFORE_REWRITE). +locked({button, Digit}, Data0) -> + case analyze_lock(Digit, Data0) of + {open = StateName, Data} -> + {next_state, StateName, Data, 10000}; + {StateName, Data} -> + {next_state, StateName, Data} + end. +-else. +locked(cast, {button,Digit}, Data0) -> + case analyze_lock(Digit, Data0) of + {open = StateName, Data} -> + {next_state, StateName, Data, 10000}; + {StateName, Data} -> + {next_state, StateName, Data} + end; +locked({call, From}, Msg, Data) -> + handle_call(From, Msg, Data); +locked({info, Msg}, StateName, Data) -> + handle_info(Msg, StateName, Data). +%% Arity differs +%% All state events are dispatched to handle_call and handle_info help +%% functions. If you want to handle a call or cast event specifically +%% for this state you would add a special clause for it above. +-endif. + +-ifdef(BEFORE_REWRITE). +open(timeout, State) -> + do_lock(), + {next_state, locked, State}; +open({button,_}, Data) -> + {next_state, locked, Data}. +-else. +open(timeout, _, Data) -> + do_lock(), + {next_state, locked, Data}; +open(cast, {button,_}, Data) -> + {next_state, locked, Data}; +open({call, From}, Msg, Data) -> + handle_call(From, Msg, Data); +open(info, Msg, Data) -> + handle_info(Msg, open, Data). +%% Arity differs +%% All state events are dispatched to handle_call and handle_info help +%% functions. If you want to handle a call or cast event specifically +%% for this state you would add a special clause for it above. +-endif. + +-ifdef(BEFORE_REWRITE). +handle_sync_event(stop, _From, _StateName, Data) -> + {stop, normal, ok, Data}. + +handle_event(Event, StateName, Data) -> + {stop, {shutdown, {unexpected, Event, StateName}}, Data}. + +handle_info(Info, StateName, Data) -> + {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}. +-else. +-endif. + +terminate(_Reason, State, _Data) -> + State =/= locked andalso do_lock(), + ok. +code_change(_Vsn, State, Data, _Extra) -> + {ok, State, Data}. + +%% Internal functions +-ifdef(BEFORE_REWRITE). +-else. +handle_call(From, stop, Data) -> + {stop_and_reply, normal, {reply, From, ok}, Data}. + +handle_info(Info, StateName, Data) -> + {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}. +%% These are internal functions for handling all state events +%% and not behaviour callbacks as in gen_fsm +-endif. + +analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> + do_unlock(), + {open, Data#{remaining := Code}}; + [Digit|Rest] -> % Incomplete + {locked, Data#{remaining := Rest}}; + _Wrong -> + {locked, Data#{remaining := Code}} + end. + +do_lock() -> + io:format("Lock~n", []). +do_unlock() -> + io:format("Unlock~n", []). + </code> </section> </erlref> diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index 662076b5f0..0bcbbc2805 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -504,6 +504,13 @@ gen_server:abcast -----> Module:handle_cast/2 <v>Reason = term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not export it. + If a release upgrade/downgrade with <c>Change={advanced,Extra}</c> + specified in the <c>appup</c> file is made when <c>code_change/3</c> + isn't implemented the process will crash with an <c>undef</c> exit + reason.</p> + </note> <p>This function is called by a <c>gen_server</c> process when it is to update its internal state during a release upgrade/downgrade, that is, when the instruction <c>{update,Module,Change,...}</c>, @@ -690,6 +697,12 @@ gen_server:abcast -----> Module:handle_cast/2 <v> Reason = normal | term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_server</c> module provides a default + implementation of this function that logs about the unexpected + <c>Info</c> message, drops it and returns <c>{noreply, State}</c>.</p> + </note> <p>This function is called by a <c>gen_server</c> process when a time-out occurs or when it receives any other message than a synchronous or asynchronous request (or a system message).</p> @@ -750,6 +763,11 @@ gen_server:abcast -----> Module:handle_cast/2 <v>State = term()</v> </type> <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_server</c> module provides a default + implementation without cleanup.</p> + </note> <p>This function is called by a <c>gen_server</c> process when it is about to terminate. It is to be the opposite of <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso> @@ -796,7 +814,6 @@ gen_server:abcast -----> Module:handle_cast/2 <section> <title>See Also</title> <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>, - <seealso marker="gen_fsm"><c>gen_fsm(3)</c></seealso>, <seealso marker="gen_statem"><c>gen_statem(3)</c></seealso>, <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>, <seealso marker="supervisor"><c>supervisor(3)</c></seealso>, diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 5eb13db1aa..17a3a3c83c 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2016-2017</year> + <year>2016</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -62,24 +62,29 @@ </p> </note> <p> - The <c>gen_statem</c> behavior is intended to replace - <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> for new code. + The <c>gen_statem</c> behavior replaces + <seealso marker="gen_fsm"><c>gen_fsm</c> </seealso> in Erlang/OTP 20.0. It has the same features and adds some really useful: </p> <list type="bulleted"> - <item>State code is gathered.</item> - <item>The state can be any term.</item> - <item>Events can be postponed.</item> - <item>Events can be self-generated.</item> - <item>Automatic state enter code can be called.</item> - <item>A reply can be sent from a later state.</item> - <item>There can be multiple <c>sys</c> traceable replies.</item> + <item>Gathered state code.</item> + <item>Arbitrary term state.</item> + <item>Event postponing.</item> + <item>Self-generated events.</item> + <item>State time-out.</item> + <item>Multiple generic named time-outs.</item> + <item>Absolute time-out time.</item> + <item>Automatic state enter calls.</item> + <item>Reply from other state than the request.</item> + <item>Multiple <c>sys</c> traceable replies.</item> </list> <p> The callback model(s) for <c>gen_statem</c> differs from the one for <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>, - but it is still fairly easy to rewrite - from <c>gen_fsm</c> to <c>gen_statem</c>. + but it is still fairly easy to + <seealso marker="gen_fsm#Migration to gen_statem"> + rewrite from + </seealso> <c>gen_fsm</c> to <c>gen_statem</c>. </p> <p> A generic state machine process (<c>gen_statem</c>) implemented @@ -146,7 +151,7 @@ erlang:'!' -----> Module:StateName/3 This gathers all code for a specific state in one function as the <c>gen_statem</c> engine branches depending on state name. - Notice the fact that there is a mandatory callback function + Note the fact that the callback function <seealso marker="#Module:terminate/3"><c>Module:terminate/3</c></seealso> makes the state name <c>terminate</c> unusable in this mode. </p> @@ -531,10 +536,12 @@ handle_event(_, _, State, Data) -> originate from the corresponding API functions. For calls, the event contains whom to reply to. Type <c>info</c> originates from regular process messages sent - to the <c>gen_statem</c>. Also, the state machine - implementation can generate events of types - <c>timeout</c>, <c>state_timeout</c>, - and <c>internal</c> to itself. + to the <c>gen_statem</c>. The state machine + implementation can, in addition to the above, + generate + <seealso marker="#type-event_type"><c>events of types</c></seealso> + <c>timeout</c>, <c>{timeout,<anno>Name</anno>}</c>, + <c>state_timeout</c>, and <c>internal</c> to itself. </p> </desc> </datatype> @@ -701,13 +708,14 @@ handle_event(_, _, State, Data) -> </item> <item> <p> - Timeout timers - <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> + Time-out timers + <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>, + <seealso marker="#type-generic_timeout"><c>generic_timeout()</c></seealso> and - <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso> + <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> are handled. Time-outs with zero time are guaranteed to be delivered to the state machine before any external - not yet received event so if there is such a timeout requested, + not yet received event so if there is such a time-out requested, the corresponding time-out zero event is enqueued as the newest event. </p> @@ -785,49 +793,102 @@ handle_event(_, _, State, Data) -> <name name="event_timeout"/> <desc> <p> - Generates an event of + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>timeout</c>. + When the timer expires an event of <seealso marker="#type-event_type"><c>event_type()</c></seealso> - <c>timeout</c> - after this time (in milliseconds) unless another - event arrives or has arrived - in which case this time-out is cancelled. + <c>timeout</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. + </p> + <p> + Any event that arrives cancels this time-out. Note that a retried or inserted event counts as arrived. So does a state time-out zero event, if it was generated - before this timer is requested. + before this time-out is requested. </p> <p> - If the value is <c>infinity</c>, no timer is started, as - it never would trigger anyway. + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. </p> <p> - If the value is <c>0</c> no timer is actually started, + If <c>Time</c> is relative and <c>0</c> + no timer is actually started, instead the the time-out event is enqueued to ensure that it gets processed before any not yet received external event. </p> <p> - Note that it is not possible or needed to cancel this time-out, + Note that it is not possible nor needed to cancel this time-out, as it is cancelled automatically by any other event. </p> </desc> </datatype> <datatype> + <name name="generic_timeout"/> + <desc> + <p> + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>{timeout,Name}</c>. + When the timer expires an event of + <seealso marker="#type-event_type"><c>event_type()</c></seealso> + <c>{timeout,Name}</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. + </p> + <p> + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. + </p> + <p> + If <c>Time</c> is relative and <c>0</c> + no timer is actually started, + instead the the time-out event is enqueued to ensure + that it gets processed before any not yet + received external event. + </p> + <p> + Setting a timer with the same <c>Name</c> while it is running + will restart it with the new time-out value. + Therefore it is possible to cancel + a specific time-out by setting it to <c>infinity</c>. + </p> + </desc> + </datatype> + <datatype> <name name="state_timeout"/> <desc> <p> - Generates an event of + Starts a timer set by + <seealso marker="#type-enter_action"><c>enter_action()</c></seealso> + <c>state_timeout</c>. + When the timer expires an event of <seealso marker="#type-event_type"><c>event_type()</c></seealso> - <c>state_timeout</c> - after this time (in milliseconds) unless the <c>gen_statem</c> - changes states (<c>NewState =/= OldState</c>) - which case this time-out is cancelled. + <c>state_timeout</c> will be generated. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for how <c>Time</c> and + <seealso marker="#type-timeout_option"><c>Options</c></seealso> + are interpreted. Future <c>erlang:start_timer/4</c> <c>Options</c> + will not necessarily be supported. </p> <p> - If the value is <c>infinity</c>, no timer is started, as - it never would trigger anyway. + If <c>Time</c> is <c>infinity</c>, + no timer is started, as it never would expire anyway. </p> <p> - If the value is <c>0</c> no timer is actually started, + If <c>Time</c> is relative and <c>0</c> + no timer is actually started, instead the the time-out event is enqueued to ensure that it gets processed before any not yet received external event. @@ -840,6 +901,20 @@ handle_event(_, _, State, Data) -> </desc> </datatype> <datatype> + <name name="timeout_option"/> + <desc> + <p> + If <c>Abs</c> is <c>true</c> an absolute timer is started, + and if it is <c>false</c> a relative, which is the default. + See + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso> + for details. + </p> + <p> + </p> + </desc> + </datatype> + <datatype> <name name="action"/> <desc> <p> @@ -945,7 +1020,6 @@ handle_event(_, _, State, Data) -> <seealso marker="#state callback">state callback</seealso> return value <c>{next_state,NextState,NewData,Timeout}</c> allowed like for <c>gen_fsm</c>'s - <seealso marker="gen_fsm#Module:StateName/2"><c>Module:StateName/2</c></seealso>. </p> </item> <tag><c>timeout</c></tag> @@ -954,7 +1028,21 @@ handle_event(_, _, State, Data) -> Sets the <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso> - to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c>. + to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. + </p> + </item> + <tag><c>{timeout,<anno>Name</anno>}</c></tag> + <item> + <p> + Sets the + <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> + <seealso marker="#type-generic_timeout"><c>generic_timeout()</c></seealso> + to <c><anno>Time</anno></c> for <c><anno>Name</anno></c> + with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. </p> </item> <tag><c>state_timeout</c></tag> @@ -963,7 +1051,9 @@ handle_event(_, _, State, Data) -> Sets the <seealso marker="#type-transition_option"><c>transition_option()</c></seealso> <seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso> - to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c>. + to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c> + and time-out options + <seealso marker="#type-timeout_option"><c><anno>Options</anno></c></seealso>. </p> </item> </taglist> @@ -1235,7 +1325,7 @@ handle_event(_, _, State, Data) -> to avoid that the calling process dies when the call times out, you will have to be prepared to handle a late reply. - So why not just allow the calling process to die? + So why not just let the calling process die? </p> </note> <p> @@ -1644,6 +1734,16 @@ handle_event(_, _, State, Data) -> <v>Reason = term()</v> </type> <desc> + <note> + <p> + This callback is optional, so callback modules need not export it. + If a release upgrade/downgrade with + <c>Change={advanced,Extra}</c> + specified in the <c>.appup</c> file is made + when <c>code_change/4</c> is not implemented + the process will crash with exit reason <c>undef</c>. + </p> + </note> <p> This function is called by a <c>gen_statem</c> when it is to update its internal state during a release upgrade/downgrade, @@ -1704,7 +1804,7 @@ handle_event(_, _, State, Data) -> <func> <name>Module:init(Args) -> Result(StateType)</name> <fsummary> - Optional function for initializing process and internal state. + Initializing process and internal state. </fsummary> <type> <v>Args = term()</v> @@ -1720,7 +1820,7 @@ handle_event(_, _, State, Data) -> <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso> or <seealso marker="#start/3"><c>start/3,4</c></seealso>, - this optional function is called by the new process to initialize + this function is called by the new process to initialize the implementation state and server data. </p> <p> @@ -1729,13 +1829,16 @@ handle_event(_, _, State, Data) -> </p> <note> <p> - This callback is optional, so a callback module does not need - to export it, but most do. If this function is not exported, - the <c>gen_statem</c> should be started through + Note that if the <c>gen_statem</c> is started trough <seealso marker="proc_lib"><c>proc_lib</c></seealso> and - <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>. + <seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>, + this callback will never be called. + Since this callback is not optional it can + in that case be implemented as: </p> + <pre> +init(Args) -> erlang:error(not_implemented, [Args]).</pre> </note> </desc> </func> diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index 11a64c7f8a..64fcf4379f 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -265,6 +265,8 @@ ok <p>Writes data with the standard syntax. This is used to output Erlang terms. Atoms are printed within quotes if they contain embedded non-printable characters. + Atom characters > 255 are escaped unless the + Unicode translation modifier (<c>t</c>) is used. Floats are printed accurately as the shortest, correctly rounded string.</p> </item> @@ -567,8 +569,6 @@ Prompt> <input><Characters beyond latin1 range not printable in this medium&g <item> <p>Similar to <c>s</c>, but the resulting string is converted into an atom.</p> - <p>The Unicode translation modifier is not allowed (atoms - cannot contain characters beyond the <c>latin1</c> range).</p> </item> <tag><c>c</c></tag> <item> diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml index 931e50f6f2..bc1d77ac83 100644 --- a/lib/stdlib/doc/src/io_lib.xml +++ b/lib/stdlib/doc/src/io_lib.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -147,7 +147,7 @@ format string (that is, <c>~ts</c> or <c>~tc</c>), the resulting list can contain characters beyond the ISO Latin-1 character range (that is, numbers > 255). If so, the - result is not an ordinary Erlang <c>string()</c>, but can well be + result is still an ordinary Erlang <c>string()</c>, and can well be used in any context where Unicode data is allowed.</p> </desc> </func> @@ -356,7 +356,8 @@ <func> <name name="write" arity="1"/> - <name name="write" arity="2"/> + <name name="write" arity="2" clause_i="1"/> + <name name="write" arity="2" clause_i="2"/> <fsummary>Write a term.</fsummary> <desc> <p>Returns a character list that represents <c><anno>Term</anno></c>. @@ -384,6 +385,16 @@ </func> <func> + <name name="write_atom_as_latin1" arity="1"/> + <fsummary>Write an atom.</fsummary> + <desc> + <p>Returns the list of characters needed to print atom + <c><anno>Atom</anno></c>. Non-Latin-1 characters + are escaped.</p> + </desc> + </func> + + <func> <name name="write_char" arity="1"/> <fsummary>Write a character.</fsummary> <desc> diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index e64b2ce18a..7939a0ef61 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -36,7 +36,7 @@ the <seealso marker="doc/design_principles:des_princ"> OTP Design Principles</seealso>. Specifically, the functions in this module are used by the OTP standard behaviors (for example, - <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_statem</c>) + <c>gen_server</c> and <c>gen_statem</c>) when starting new processes. The functions can also be used to start <em>special processes</em>, user-defined processes that comply to the OTP design principles. For an example, diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index 2ddf3021ac..e06d7e467d 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2015</year><year>2016</year> + <year>2015</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -50,26 +50,73 @@ <p>The following algorithms are provided:</p> <taglist> - <tag><c>exsplus</c></tag> + <tag><c>exrop</c></tag> <item> - <p>Xorshift116+, 58 bits precision and period of 2^116-1</p> + <p>Xoroshiro116+, 58 bits precision and period of 2^116-1</p> <p>Jump function: equivalent to 2^64 calls</p> </item> - <tag><c>exs64</c></tag> - <item> - <p>Xorshift64*, 64 bits precision and a period of 2^64-1</p> - <p>Jump function: not available</p> - </item> - <tag><c>exs1024</c></tag> + <tag><c>exs1024s</c></tag> <item> <p>Xorshift1024*, 64 bits precision and a period of 2^1024-1</p> <p>Jump function: equivalent to 2^512 calls</p> </item> + <tag><c>exsp</c></tag> + <item> + <p>Xorshift116+, 58 bits precision and period of 2^116-1</p> + <p>Jump function: equivalent to 2^64 calls</p> + <p> + This is a corrected version of the previous default algorithm, + that now has been superseeded by Xoroshiro116+ (<c>exrop</c>). + Since there is no native 58 bit rotate instruction this + algorithm executes a little (say < 15%) faster than <c>exrop</c>. + See the + <url href="http://xorshift.di.unimi.it">algorithms' homepage</url>. + </p> + </item> </taglist> - <p>The default algorithm is <c>exsplus</c>. If a specific algorithm is + <p> + The default algorithm is <c>exrop</c> (Xoroshiro116+). + If a specific algorithm is required, ensure to always use <seealso marker="#seed-1"> - <c>seed/1</c></seealso> to initialize the state.</p> + <c>seed/1</c></seealso> to initialize the state. + </p> + + <p> + Undocumented (old) algorithms are deprecated but still implemented + so old code relying on them will produce + the same pseudo random sequences as before. + </p> + + <note> + <p> + There were a number of problems in the implementation + of the now undocumented algorithms, which is why + they are deprecated. The new algorithms are a bit slower + but do not have these problems: + </p> + <p> + Uniform integer ranges had a skew in the probability distribution + that was not noticable for small ranges but for large ranges + less than the generator's precision the probability to produce + a low number could be twice the probability for a high. + </p> + <p> + Uniform integer ranges larger than or equal to the generator's + precision used a floating point fallback that only calculated + with 52 bits which is smaller than the requested range + and therefore were not all numbers in the requested range + even possible to produce. + </p> + <p> + Uniform floats had a non-uniform density so small values + i.e less than 0.5 had got smaller intervals decreasing + as the generated value approached 0.0 although still uniformly + distributed for sufficiently large subranges. The new algorithms + produces uniformly distributed floats on the form N * 2.0^(-53) + hence equally spaced. + </p> + </note> <p>Every time a random number is requested, a state is used to calculate it and a new state is produced. The state can either be @@ -99,19 +146,19 @@ R1 = rand:uniform(),</pre> <p>Use a specified algorithm:</p> <pre> -_ = rand:seed(exs1024), +_ = rand:seed(exs1024s), R2 = rand:uniform(),</pre> <p>Use a specified algorithm with a constant seed:</p> <pre> -_ = rand:seed(exs1024, {123, 123534, 345345}), +_ = rand:seed(exs1024s, {123, 123534, 345345}), R3 = rand:uniform(),</pre> <p>Use the functional API with a non-constant seed:</p> <pre> -S0 = rand:seed_s(exsplus), +S0 = rand:seed_s(exrop), {R4, S1} = rand:uniform_s(S0),</pre> <p>Create a standard normal deviate:</p> @@ -119,6 +166,11 @@ S0 = rand:seed_s(exsplus), <pre> {SND0, S2} = rand:normal_s(S1),</pre> + <p>Create a normal deviate with mean -3 and variance 0.5:</p> + + <pre> +{ND0, S3} = rand:normal_s(-3, 0.5, S2),</pre> + <note> <p>The builtin random number generator algorithms are not cryptographically strong. If a cryptographically strong @@ -127,6 +179,39 @@ S0 = rand:seed_s(exsplus), </p> </note> + <p> + For all these generators the lowest bit(s) has got + a slightly less random behaviour than all other bits. + 1 bit for <c>exrop</c> (and <c>exsp</c>), + and 3 bits for <c>exs1024s</c>. + See for example the explanation in the + <url href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c"> + Xoroshiro128+ + </url> + generator source code: + </p> + <pre> +Beside passing BigCrush, this generator passes the PractRand test suite +up to (and included) 16TB, with the exception of binary rank tests, +which fail due to the lowest bit being an LFSR; all other bits pass all +tests. We suggest to use a sign test to extract a random Boolean value.</pre> + <p> + If this is a problem; to generate a boolean + use something like this: + </p> + <pre>(rand:uniform(16) > 8)</pre> + <p> + And for a general range, with <c>N = 1</c> for <c>exrop</c>, + and <c>N = 3</c> for <c>exs1024s</c>: + </p> + <pre>(((rand:uniform(Range bsl N) - 1) bsr N) + 1)</pre> + <p> + The floating point generating functions in this module + waste the lowest bits when converting from an integer + so they avoid this snag. + </p> + + </description> <datatypes> <datatype> @@ -142,6 +227,18 @@ S0 = rand:seed_s(exsplus), <name name="alg_state"/> </datatype> <datatype> + <name name="state"/> + <desc><p>Algorithm-dependent state.</p></desc> + </datatype> + <datatype> + <name name="export_state"/> + <desc> + <p> + Algorithm-dependent state that can be printed or saved to file. + </p> + </desc> + </datatype> + <datatype> <name name="exs64_state"/> <desc><p>Algorithm specific internal state</p></desc> </datatype> @@ -154,16 +251,8 @@ S0 = rand:seed_s(exsplus), <desc><p>Algorithm specific internal state</p></desc> </datatype> <datatype> - <name name="state"/> - <desc><p>Algorithm-dependent state.</p></desc> - </datatype> - <datatype> - <name name="export_state"/> - <desc> - <p> - Algorithm-dependent state that can be printed or saved to file. - </p> - </desc> + <name name="exrop_state"/> + <desc><p>Algorithm specific internal state</p></desc> </datatype> </datatypes> @@ -224,6 +313,15 @@ S0 = rand:seed_s(exsplus), </func> <func> + <name name="normal" arity="2"/> + <fsummary>Return a normal distributed random float.</fsummary> + <desc> + <p>Returns a normal N(Mean, Variance) deviate float + and updates the state in the process dictionary.</p> + </desc> + </func> + + <func> <name name="normal_s" arity="1"/> <fsummary>Return a standard normal distributed random float.</fsummary> <desc> @@ -234,6 +332,15 @@ S0 = rand:seed_s(exsplus), </func> <func> + <name name="normal_s" arity="3"/> + <fsummary>Return a normal distributed random float.</fsummary> + <desc> + <p>Returns, for a specified state, a normal N(Mean, Variance) + deviate float and a new state.</p> + </desc> + </func> + + <func> <name name="seed" arity="1"/> <fsummary>Seed random number generator.</fsummary> <desc> diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml index 7f4f0aa18c..078ca0e38c 100644 --- a/lib/stdlib/doc/src/re.xml +++ b/lib/stdlib/doc/src/re.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2016</year> + <year>2017</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -45,9 +45,10 @@ <p>The matching algorithms of the library are based on the PCRE library, but not all of the PCRE library is interfaced and - some parts of the library go beyond what PCRE offers. The sections of - the PCRE documentation that are relevant to this module are included - here.</p> + some parts of the library go beyond what PCRE offers. Currently + PCRE version 8.40 (release date 2017-01-11) is used. The sections + of the PCRE documentation that are relevant to this module are + included here.</p> <note> <p>The Erlang literal syntax for strings uses the "\" @@ -78,6 +79,14 @@ <funcs> <func> + <name name="version" arity="0"/> + <fsummary>Gives the PCRE version of the system in a string format</fsummary> + <desc> + <p>The return of this function is a string with the PCRE version of the system that was used in the Erlang/OTP compilation.</p> + </desc> + </func> + + <func> <name name="compile" arity="1"/> <fsummary>Compile a regular expression into a match program</fsummary> <desc> @@ -149,13 +158,25 @@ </item> <tag><c>extended</c></tag> <item> - <p>Whitespace data characters in the pattern are ignored except - when escaped or inside a character class. Whitespace does not - include character 'vt' (ASCII 11). Characters between an - unescaped <c>#</c> outside a character class and the next newline, - inclusive, are also ignored. This is equivalent to Perl option - <c>/x</c> and can be changed within a pattern by a <c>(?x)</c> - option setting.</p> + <p>If this option is set, most white space characters in the + pattern are totally ignored except when escaped or inside a + character class. However, white space is not allowed within + sequences such as <c>(?></c> that introduce various + parenthesized subpatterns, nor within a numerical quantifier + such as <c>{1,3}</c>. However, ignorable white space is permitted + between an item and a following quantifier and between a + quantifier and a following + that indicates possessiveness. + </p> + <p>White space did not used to include the VT character (code + 11), because Perl did not treat this character as white space. + However, Perl changed at release 5.18, so PCRE followed at + release 8.34, and VT is now treated as white space. + </p> + <p>This also causes characters between an unescaped # + outside a character class and the next newline, inclusive, to + be ignored. This is equivalent to Perl's <c>/x</c> option, and it + can be changed within a pattern by a <c>(?x)</c> option setting. + </p> <p>With this option, comments inside complicated patterns can be included. However, notice that this applies only to data characters. Whitespace characters can never appear within special @@ -1321,6 +1342,8 @@ re:split("Erlang","[lg]",[{return,list},{parts,4}]).</code> VM. Notice that the recursion limit does not affect the stack depth of the VM, as PCRE for Erlang is compiled in such a way that the match function never does recursion on the C stack.</p> + <p>Note that <c>LIMIT_MATCH</c> and <c>LIMIT_RECURSION</c> can only reduce + the value of the limits set by the caller, not increase them.</p> </section> <section> @@ -1444,12 +1467,17 @@ Pattern PCRE matches Perl matches <tag>\n</tag><item>Line feed (hex 0A)</item> <tag>\r</tag><item>Carriage return (hex 0D)</item> <tag>\t</tag><item>Tab (hex 09)</item> + <tag>\0dd</tag><item>Character with octal code 0dd</item> <tag>\ddd</tag><item>Character with octal code ddd, or back reference </item> + <tag>\o{ddd..}</tag><item>character with octal code ddd..</item> <tag>\xhh</tag><item>Character with hex code hh</item> <tag>\x{hhh..}</tag><item>Character with hex code hhh..</item> </taglist> + <note><p>Note that \0dd is always an octal code, and that \8 and \9 are + the literal characters "8" and "9".</p></note> + <p>The precise effect of \cx on ASCII characters is as follows: if x is a lowercase letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A @@ -1461,50 +1489,38 @@ Pattern PCRE matches Perl matches <p>The \c facility was designed for use with ASCII characters, but with the extension to Unicode it is even less useful than it once was.</p> - <p>By default, after \x, from zero to two hexadecimal digits are read - (letters can be in upper or lower case). Any number of hexadecimal digits - can appear between \x{ and }, but the character code is constrained as - follows:</p> - - <taglist> - <tag>8-bit non-Unicode mode</tag> - <item>< 0x100</item> - <tag>8-bit UTF-8 mode</tag> - <item>< 0x10ffff and a valid code point</item> - </taglist> - - <p>Invalid Unicode code points are the range 0xd800 to 0xdfff (the so-called - "surrogate" code points), and 0xffef.</p> - - <p>If characters other than hexadecimal digits appear between \x{ and }, - or if there is no terminating }, this form of escape is not recognized. - Instead, the initial \x is interpreted as a basic hexadecimal escape, - with no following digits, giving a character whose value is zero.</p> - - <p>Characters whose value is < 256 can be defined by either of the two - syntaxes for \x. There is no difference in the way they are handled. For - example, \xdc is the same as \x{dc}.</p> - <p>After \0 up to two further octal digits are read. If there are fewer than - two digits, only those that are present are used. Thus the sequence - \0\x\07 specifies two binary zeros followed by a BEL character (code value - 7). Ensure to supply two digits after the initial zero if the pattern - character that follows is itself an octal digit.</p> + two digits, just those that are present are used. Thus the sequence + \0\x\015 specifies two binary zeros followed by a CR character (code value + 13). Make sure you supply two digits after the initial zero if the pattern + character that follows is itself an octal digit.</p> + + <p>The escape \o must be followed by a sequence of octal digits, enclosed + in braces. An error occurs if this is not the case. This escape is a recent + addition to Perl; it provides way of specifying character code points as + octal numbers greater than 0777, and it also allows octal numbers and back + references to be unambiguously specified.</p> + + <p>For greater clarity and unambiguity, it is best to avoid following \ by + a digit greater than zero. Instead, use \o{} or \x{} to specify character + numbers, and \g{} to specify back references. The following paragraphs + describe the old, ambiguous syntax.</p> <p>The handling of a backslash followed by a digit other than 0 is - complicated. Outside a character class, PCRE reads it and any following - digits as a decimal number. If the number is < 10, or if there have + complicated, and Perl has changed in recent releases, causing PCRE also + to change. Outside a character class, PCRE reads the digit and any following + digits as a decimal number. If the number is < 8, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a <em>back reference</em>. A description of how this works is provided later, following the discussion of parenthesized subpatterns.</p> - <p>Inside a character class, or if the decimal number is > 9 and there - have not been that many capturing subpatterns, PCRE re-reads up to three - octal digits following the backslash, and uses them to generate a data - character. Any subsequent digits stand for themselves. The value of the - character is constrained in the same way as characters specified in - hexadecimal. For example:</p> + <p>Inside a character class, or if the decimal number following \ is > + 7 and there have not been that many capturing subpatterns, PCRE handles + \8 and \9 as the literal characters "8" and "9", and otherwise re-reads + up to three octal digits following the backslash, and using them to + generate a data character. Any subsequent digits stand for themselves. + For example:</p> <taglist> <tag>\040</tag> @@ -1526,12 +1542,38 @@ Pattern PCRE matches Perl matches <tag>\377</tag> <item>Can be a back reference, otherwise value 255 (decimal)</item> <tag>\81</tag> - <item>Either a back reference, or a binary zero followed by the two - characters "8" and "1"</item> + <item>Either a back reference, or the two characters "8" and "1"</item> </taglist> - <p>Notice that octal values >= 100 must not be introduced by a leading - zero, as no more than three octal digits are ever read.</p> + <p>Notice that octal values >= 100 that are specified using this syntax + must not be introduced by a leading zero, as no more than three octal digits + are ever read.</p> + + <p>By default, after \x that is not followed by {, from zero to two + hexadecimal digits are read (letters can be in upper or lower case). Any + number of hexadecimal digits may appear between \x{ and }. If a character + other than a hexadecimal digit appears between \x{ and }, or if there is no + terminating }, an error occurs. + </p> + + <p>Characters whose value is less than 256 can be defined by either of the + two syntaxes for \x. There is no difference in the way they are handled. For + example, \xdc is exactly the same as \x{dc}.</p> + + <p><em>Constraints on character values</em></p> + + <p>Characters that are specified using octal or hexadecimal numbers are + limited to certain values, as follows:</p> + <taglist> + <tag>8-bit non-UTF mode</tag> + <item><p>< 0x100</p></item> + <tag>8-bit UTF-8 mode</tag> + <item><p>< 0x10ffff and a valid codepoint</p></item> + </taglist> + <p>Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the + so-called "surrogate" codepoints), and 0xffef.</p> + + <p><em>Escape sequences in character classes</em></p> <p>All the sequences that define a single character value can be used both inside and outside character classes. Also, inside a character class, \b @@ -1597,11 +1639,14 @@ Pattern PCRE matches Perl matches appropriate type. If the current matching point is at the end of the subject string, all fail, as there is no character to match.</p> - <p>For compatibility with Perl, \s does not match the VT character - (code 11). This makes it different from the Posix "space" class. The \s - characters are HT (9), LF (10), FF (12), CR (13), and space (32). If "use - locale;" is included in a Perl script, \s can match the VT character. In - PCRE, it never does.</p> + <p>For compatibility with Perl, \s did not used to match the VT character (code + 11), which made it different from the the POSIX "space" class. However, Perl + added VT at release 5.18, and PCRE followed suit at release 8.34. The default + \s characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space + (32), which are defined as white space in the "C" locale. This list may vary if + locale-specific matching is taking place. For example, in some locales the + "non-breaking space" character (\xA0) is recognized as white space, and in + others the VT character is not.</p> <p>A "word" character is an underscore or any character that is a letter or a digit. By default, the definition of letters and digits is controlled by @@ -1619,9 +1664,9 @@ Pattern PCRE matches Perl matches <taglist> <tag>\d</tag><item>Any character that \p{Nd} matches (decimal digit) </item> - <tag>\s</tag><item>Any character that \p{Z} matches, plus HT, LF, FF, CR + <tag>\s</tag><item>Any character that \p{Z} or \h or \v </item> - <tag>\w</tag><item>Any character that \p{L} or \p{N} matches, plus + <tag>\w</tag><item>Any character that matches \p{L} or \p{N} matches, plus underscore</item> </taglist> @@ -1769,6 +1814,7 @@ Pattern PCRE matches Perl matches <item>Avestan</item> <item>Balinese</item> <item>Bamum</item> + <item>Bassa_Vah</item> <item>Batak</item> <item>Bengali</item> <item>Bopomofo</item> @@ -1777,6 +1823,7 @@ Pattern PCRE matches Perl matches <item>Buhid</item> <item>Canadian_Aboriginal</item> <item>Carian</item> + <item>Caucasian_Albanian</item> <item>Chakma</item> <item>Cham</item> <item>Cherokee</item> @@ -1787,11 +1834,14 @@ Pattern PCRE matches Perl matches <item>Cyrillic</item> <item>Deseret</item> <item>Devanagari</item> + <item>Duployan</item> <item>Egyptian_Hieroglyphs</item> + <item>Elbasan</item> <item>Ethiopic</item> <item>Georgian</item> <item>Glagolitic</item> <item>Gothic</item> + <item>Grantha</item> <item>Greek</item> <item>Gujarati</item> <item>Gurmukhi</item> @@ -1811,40 +1861,56 @@ Pattern PCRE matches Perl matches <item>Kayah_Li</item> <item>Kharoshthi</item> <item>Khmer</item> + <item>Khojki</item> + <item>Khudawadi</item> <item>Lao</item> <item>Latin</item> <item>Lepcha</item> <item>Limbu</item> + <item>Linear_A</item> <item>Linear_B</item> <item>Lisu</item> <item>Lycian</item> <item>Lydian</item> + <item>Mahajani</item> <item>Malayalam</item> <item>Mandaic</item> + <item>Manichaean</item> <item>Meetei_Mayek</item> + <item>Mende_Kikakui</item> <item>Meroitic_Cursive</item> <item>Meroitic_Hieroglyphs</item> <item>Miao</item> + <item>Modi</item> <item>Mongolian</item> + <item>Mro</item> <item>Myanmar</item> + <item>Nabataean</item> <item>New_Tai_Lue</item> <item>Nko</item> <item>Ogham</item> + <item>Ol_Chiki</item> <item>Old_Italic</item> + <item>Old_North_Arabian</item> + <item>Old_Permic</item> <item>Old_Persian</item> <item>Oriya</item> <item>Old_South_Arabian</item> <item>Old_Turkic</item> - <item>Ol_Chiki</item> <item>Osmanya</item> + <item>Pahawh_Hmong</item> + <item>Palmyrene</item> + <item>Pau_Cin_Hau</item> <item>Phags_Pa</item> <item>Phoenician</item> + <item>Psalter_Pahlavi</item> <item>Rejang</item> <item>Runic</item> <item>Samaritan</item> <item>Saurashtra</item> <item>Sharada</item> <item>Shavian</item> + <item>Siddham</item> <item>Sinhala</item> <item>Sora_Sompeng</item> <item>Sundanese</item> @@ -1862,8 +1928,10 @@ Pattern PCRE matches Perl matches <item>Thai</item> <item>Tibetan</item> <item>Tifinagh</item> + <item>Tirhuta</item> <item>Ugaritic</item> <item>Vai</item> + <item>Warang_Citi</item> <item>Yi</item> </list> @@ -2001,10 +2069,10 @@ Pattern PCRE matches Perl matches <p>In addition to the standard Unicode properties described earlier, PCRE supports four more that make it possible to convert traditional escape - sequences, such as \w and \s, and Posix character classes to use Unicode + sequences, such as \w and \s to use Unicode properties. PCRE uses these non-standard, non-Perl properties internally - when <c>PCRE_UCP</c> is set. However, they can also be used explicitly. - The properties are as follows:</p> + when the <c>ucp</c> option is passed. However, they can also be used + explicitly. The properties are as follows:</p> <taglist> <tag>Xan</tag> @@ -2030,6 +2098,16 @@ Pattern PCRE matches Perl matches </item> </taglist> + <p>Perl and POSIX space are now the same. Perl added VT to its space + character set at release 5.18 and PCRE changed at release 8.34.</p> + + <p>Xan matches characters that have either the L (letter) or the N (number) + property. Xps matches the characters tab, linefeed, vertical tab, form feed, + or carriage return, and any other character that has the Z (separator) + property. Xsp is the same as Xps; it used to exclude vertical tab, for Perl + compatibility, but Perl changed, and so PCRE followed at release 8.34. Xwd + matches the same characters as Xan, plus underscore. + </p> <p>There is another non-standard property, Xuc, which matches any character that can be represented by a Universal Character Name in C++ and other programming languages. These are the characters $, @, ` (grave accent), @@ -2062,7 +2140,9 @@ foo\Kbar</code> <p>Perl documents that the use of \K within assertions is "not well defined". In PCRE, \K is acted upon when it occurs inside positive - assertions, but is ignored in negative assertions.</p> + assertions, but is ignored in negative assertions. Note that when a + pattern such as (?=ab\K) matches, the reported start of the match can + be greater than the end of the match.</p> <p><em>Simple Assertions</em></p> @@ -2301,7 +2381,8 @@ foo\Kbar</code> m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last - character in the class.</p> + character in the class, or immediately after a range. For example, [b-d-z] + matches letters in the range b to d, a hyphen character, or z.</p> <p>The literal character "]" cannot be the end character of a range. A pattern such as [W-]46] is interpreted as a class of two characters ("W" @@ -2311,6 +2392,11 @@ foo\Kbar</code> followed by two other characters. The octal or hexadecimal representation of "]" can also be used to end a range.</p> + <p>An error is generated if a POSIX character class (see below) or an + escape sequence other than one that defines a single character appears at + a point where a range ending character is expected. For example, [z-\xff] + is valid, but [A-\d] and [A-[:digit:]] are not.</p> + <p>Ranges operate in the collating sequence of character values. They can also be used for characters specified numerically, for example, [\000-\037]. Ranges can include any characters that are valid for the @@ -2353,7 +2439,8 @@ foo\Kbar</code> range)</item> <item>Circumflex (only at the start)</item> <item>Opening square bracket (only when it can be interpreted as - introducing a Posix class name; see the next section)</item> + introducing a Posix class name, or for a special compatibility + feature; see the next two sections)</item> <item>Terminating closing square bracket</item> </list> @@ -2385,16 +2472,18 @@ foo\Kbar</code> <tag>print</tag><item>Printing characters, including space</item> <tag>punct</tag><item>Printing characters, excluding letters, digits, and space</item> - <tag>space</tag><item>Whitespace (not quite the same as \s)</item> + <tag>space</tag><item>Whitespace (the same as \s from PCRE 8.34)</item> <tag>upper</tag><item>Uppercase letters</item> <tag>word</tag><item>"Word" characters (same as \w)</item> <tag>xdigit</tag><item>Hexadecimal digits</item> </taglist> - <p>The "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13), - and space (32). Notice that this list includes the VT character (code 11). - This makes "space" different to \s, which does not include VT (for Perl - compatibility).</p> + <p>The default "space" characters are HT (9), LF (10), VT (11), FF (12), + CR (13), and space (32). If locale-specific matching is taking place, the + list of space characters may be different; there may be fewer or more of + them. "Space" used to be different to \s, which did not include VT, for + Perl compatibility. However, Perl changed at release 5.18, and PCRE followed + at release 8.34. "Space" and \s now match the same set of characters.</p> <p>The name "word" is a Perl extension, and "blank" is a GNU extension from Perl 5.8. Another Perl extension is negation, which is indicated by a ^ @@ -2408,11 +2497,11 @@ foo\Kbar</code> "ch" is a "collating element", but these are not supported, and an error is given if they are encountered.</p> - <p>By default, in UTF modes, characters with values > 255 do not match + <p>By default, characters with values > 255 do not match any of the Posix character classes. However, if option <c>PCRE_UCP</c> is passed to <c>pcre_compile()</c>, some of the classes are changed so that - Unicode character properties are used. This is achieved by replacing the - Posix classes by other sequences, as follows:</p> + Unicode character properties are used. This is achieved by replacing + certain Posix classes by other sequences, as follows:</p> <taglist> <tag>[:alnum:]</tag><item>Becomes <em>\p{Xan}</em></item> @@ -2425,9 +2514,49 @@ foo\Kbar</code> <tag>[:word:]</tag><item>Becomes <em>\p{Xwd}</em></item> </taglist> - <p>Negated versions, such as [:^alpha:], use \P instead of \p. The other - Posix classes are unchanged, and match only characters with code points - < 256.</p> + <p>Negated versions, such as [:^alpha:], use \P instead of \p. Three other + POSIX classes are handled specially in UCP mode:</p> + <taglist> + <tag>[:graph:]</tag> + <item><p>This matches characters that have glyphs that mark the page + when printed. In Unicode property terms, it matches all characters with + the L, M, N, P, S, or Cf properties, except for:</p> + <taglist> + <tag>U+061C</tag><item><p>Arabic Letter Mark</p></item> + <tag>U+180E</tag><item><p>Mongolian Vowel Separator</p></item> + <tag>U+2066 - U+2069</tag><item><p>Various "isolate"s</p></item> + </taglist> + </item> + <tag>[:print:]</tag> + <item><p>This matches the same characters as [:graph:] plus space + characters that are not controls, that is, characters with the Zs + property.</p></item> + <tag>[:punct:]</tag><item><p>This matches all characters that have + the Unicode P (punctuation) property, plus those characters whose code + points are less than 128 that have the S (Symbol) property.</p></item> + </taglist> + <p>The other POSIX classes are unchanged, and match only characters with + code points less than 128. + </p> + + <p><em>Compatibility Feature for Word Boundaries</em></p> + + <p>In the POSIX.2 compliant library that was included in 4.4BSD Unix, + the ugly syntax [[:<:]] and [[:>:]] is used for matching "start + of word" and "end of word". PCRE treats these items as follows:</p> + <taglist> + <tag>[[:<:]]</tag><item><p>is converted to \b(?=\w)</p></item> + <tag>[[:>:]]</tag><item><p>is converted to \b(?<=\w)</p></item> + </taglist> + <p>Only these exact character sequences are recognized. A sequence such as + [a[:<:]b] provokes error for an unrecognized POSIX class name. This + support is not compatible with Perl. It is provided to help migrations from + other environments, and is best not used in any new patterns. Note that \b + matches at the start and the end of a word (see "Simple assertions" above), + and in a Perl-style pattern the preceding or following character normally + shows which is wanted, without the need for the assertions that are used + above in order to give exactly the POSIX behaviour.</p> + </section> <section> @@ -2476,8 +2605,7 @@ gilbert|sullivan</code> <p>When one of these option changes occurs at top-level (that is, not inside subpattern parentheses), the change applies to the remainder of the - pattern that follows. If the change is placed right at the start of a - pattern, PCRE extracts it into the global options.</p> + pattern that follows.</p> <p>An option change within a subpattern (see section <seealso marker="#sect11">Subpatterns</seealso>) affects only that part of the subpattern that follows it. So, the following matches abc and aBc and @@ -2645,9 +2773,9 @@ the ((?:red|white) (king|queen))</code> parentheses from other parts of the pattern, such as back references, recursion, and conditions, can be made by name and by number.</p> - <p>Names consist of up to 32 alphanumeric characters and underscores. Named - capturing parentheses are still allocated numbers as well as names, - exactly as if the names were not present. + <p>Names consist of up to 32 alphanumeric characters and underscores, but + must start with a non-digit. Named capturing parentheses are still allocated + numbers as well as names, exactly as if the names were not present. The <c>capture</c> specification to <seealso marker="#run/3"> <c>run/3</c></seealso> can use named values if they are present in the regular expression.</p> @@ -3118,7 +3246,14 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</code> purposes of numbering the capturing subpatterns in the whole pattern. However, substring capturing is done only for positive assertions. (Perl sometimes, but not always, performs capturing in negative assertions.)</p> - + <warning> + <p>If a positive assertion containing one or more capturing subpatterns + succeeds, but failure to match later in the pattern causes backtracking over + this assertion, the captures within the assertion are reset only if no higher + numbered captures are already set. This is, unfortunately, a fundamental + limitation of the current implementation, and as PCRE1 is now in + maintenance-only status, it is unlikely ever to change.</p> + </warning> <p>For compatibility with Perl, assertion subpatterns can be repeated. However, it makes no sense to assert the same thing many times, the side effect of capturing parentheses can occasionally be useful. In practice, @@ -3371,12 +3506,7 @@ abcd$</code> <p>Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a used subpattern by name. For compatibility with earlier versions of PCRE, which had this facility before Perl, the syntax (?(name)...) is also - recognized. However, there is a possible ambiguity with this syntax, as - subpattern names can consist entirely of digits. PCRE looks first for a - named subpattern; if it cannot find one and the name consists entirely of - digits, PCRE looks for a subpattern of that number, which must be > 0. - Using subpattern names that consist entirely of digits is not - recommended.</p> + recognized.</p> <p>Rewriting the previous example to use a named subpattern gives:</p> @@ -3958,11 +4088,13 @@ a+(*COMMIT)b</code> 2> re:run("xyzabc","(*COMMIT)abc",[{capture,all,list},no_start_optimize]). nomatch</code> - <p>PCRE knows that any match must start with "a", so the optimization skips - along the subject to "a" before running the first match attempt, which - succeeds. When the optimization is disabled by option - <c>no_start_optimize</c>, the match starts at "x" and so the (*COMMIT) - causes it to fail without trying any other starting points.</p> + <p>For this pattern, PCRE knows that any match must start with "a", so the + optimization skips along the subject to "a" before applying the pattern to the + first set of data. The match attempt then succeeds. In the second call the + <c>no_start_optimize</c> disables the optimization that skips along to the + first character. The pattern is now applied starting at "x", and so the + (*COMMIT) causes the match to fail without trying any other starting + points.</p> <p>The following verb causes the match to fail at the current starting position in the subject if there is a later matching failure that causes @@ -4138,7 +4270,7 @@ A (B(*THEN)C | (*FAIL)) | D</code> ...(*COMMIT)(*PRUNE)...</code> <p>If there is a matching failure to the right, backtracking onto (*PRUNE) - cases it to be triggered, and its action is taken. There can never be a + causes it to be triggered, and its action is taken. There can never be a backtrack onto (*COMMIT).</p> <p><em>Backtracking Verbs in Repeated Groups</em></p> diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml index 44dc104645..4dc5d68151 100644 --- a/lib/stdlib/doc/src/sets.xml +++ b/lib/stdlib/doc/src/sets.xml @@ -40,7 +40,7 @@ <p>This module provides the same interface as the <seealso marker="ordsets"><c>ordsets(3)</c></seealso> module - but with a defined representation. One difference is + but with an undefined representation. One difference is that while this module considers two elements as different if they do not match (<c>=:=</c>), <c>ordsets</c> considers two elements as different if and only if they do not compare equal (<c>==</c>).</p> diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml index f52bc39deb..2593d3690b 100644 --- a/lib/stdlib/doc/src/shell.xml +++ b/lib/stdlib/doc/src/shell.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -569,7 +569,7 @@ Hello Number: 3378 <pre> 42> <input>E = ets:new(t, []).</input> -17</pre> +#Ref<0.1662103692.2407923716.214192></pre> <p>Command 42 creates an ETS table.</p> @@ -602,7 +602,7 @@ false</pre> <pre> 47> <input>E = ets:new(t, []).</input> -18 +#Ref<0.1662103692.2407923716.214197> 48> <input>ets:insert({d,1,2}).</input> * exception error: undefined function ets:insert/1</pre> @@ -617,10 +617,23 @@ true</pre> <p>Command 49 successfully inserts the tuple into the ETS table.</p> <pre> -50> <input>halt().</input> +50> <input>ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).</input> +true</pre> + + <p>Command 50 inserts another tuple into the ETS table. This time + the first argument is the table identifier itself. The shell can + parse commands with pids (<c><0.60.0></c>), ports + (<c>#Port<0.536></c>), references + (<c>#Ref<0.1662103692.2407792644.214210></c>), and external + functions (<c>#Fun<a.b.1></c>), but the command fails unless + the corresponding pid, port, reference, or function can be created + in the running system.</p> + + <pre> +51> <input>halt().</input> strider 2></pre> - <p>Command 50 exits the Erlang runtime system.</p> + <p>Command 51 exits the Erlang runtime system.</p> </section> <section> @@ -854,7 +867,7 @@ q - quit erlang <c>{history, N}</c>, where <c>N</c> is the current command number. The function is to return a list of characters or an atom. This constraint is because of the Erlang I/O protocol. Unicode characters - beyond code point 255 are allowed in the list. Notice + beyond code point 255 are allowed in the list and the atom. Notice that in restricted mode the call <c>Mod:Func(L)</c> must be allowed or the default shell prompt function is called.</p> </section> diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml index dddedf1132..dc83c40a9a 100644 --- a/lib/stdlib/doc/src/string.xml +++ b/lib/stdlib/doc/src/string.xml @@ -36,8 +36,613 @@ <modulesummary>String processing functions.</modulesummary> <description> <p>This module provides functions for string processing.</p> + <p>A string in this module is represented by <seealso marker="unicode#type-chardata"> + <c>unicode:chardata()</c></seealso>, that is, a list of codepoints, + binaries with UTF-8-encoded codepoints + (<em>UTF-8 binaries</em>), or a mix of the two.</p> + <code> +"abcd" is a valid string +<<"abcd">> is a valid string +["abcd"] is a valid string +<<"abc..åäö"/utf8>> is a valid string +<<"abc..åäö">> is NOT a valid string, + but a binary with Latin-1-encoded codepoints +[<<"abc">>, "..åäö"] is a valid string +[atom] is NOT a valid string</code> + <p> + This module operates on grapheme clusters. A <em>grapheme cluster</em> + is a user-perceived character, which can be represented by several + codepoints. + </p> + <code> +"å" [229] or [97, 778] +"e̊" [101, 778]</code> + <p> + The string length of "ß↑e̊" is 3, even though it is represented by the + codepoints <c>[223,8593,101,778]</c> or the UTF-8 binary + <c><<195,159,226,134,145,101,204,138>></c>. + </p> + <p> + Grapheme clusters for codepoints of class <c>prepend</c> + and non-modern (or decomposed) Hangul is not handled for performance + reasons in + <seealso marker="#find/3"><c>find/3</c></seealso>, + <seealso marker="#replace/3"><c>replace/3</c></seealso>, + <seealso marker="#split/2"><c>split/2</c></seealso>, + <seealso marker="#lexemes/2"><c>split/2</c></seealso> and + <seealso marker="#trim/3"><c>trim/3</c></seealso>. + </p> + <p> + Splitting and appending strings is to be done on grapheme clusters + borders. + There is no verification that the results of appending strings are + valid or normalized. + </p> + <p> + Most of the functions expect all input to be normalized to one form, + see for example <seealso marker="unicode#characters_to_nfc_list/1"> + <c>unicode:characters_to_nfc_list/1</c></seealso>. + </p> + <p> + Language or locale specific handling of input is not considered + in any function. + </p> + <p> + The functions can crash for non-valid input strings. For example, + the functions expect UTF-8 binaries but not all functions + verify that all binaries are encoded correctly. + </p> + <p> + Unless otherwise specified the return value type is the same as + the input type. That is, binary input returns binary output, + list input returns a list output, and mixed input can return a + mixed output.</p> + <code> +1> string:trim(" sarah "). +"sarah" +2> string:trim(<<" sarah ">>). +<<"sarah">> +3> string:lexemes("foo bar", " "). +["foo","bar"] +4> string:lexemes(<<"foo bar">>, " "). +[<<"foo">>,<<"bar">>]</code> + <p>This module has been reworked in Erlang/OTP 20 to + handle <seealso marker="unicode#type-chardata"> + <c>unicode:chardata()</c></seealso> and operate on grapheme + clusters. The <seealso marker="#oldapi"> <c>old + functions</c></seealso> that only work on Latin-1 lists as input + are still available but should not be + used. They will be deprecated in Erlang/OTP 21. + </p> </description> + <datatypes> + <datatype> + <name name="direction"/> + <name name="grapheme_cluster"/> + <desc> + <p>A user-perceived character, consisting of one or more + codepoints.</p> + </desc> + </datatype> + </datatypes> + + <funcs> + + <func> + <name name="casefold" arity="1"/> + <fsummary>Convert a string to a comparable string.</fsummary> + <desc> + <p> + Converts <c><anno>String</anno></c> to a case-agnostic + comparable string. Function <c>casefold/1</c> is preferred + over <c>lowercase/1</c> when two strings are to be compared + for equality. See also <seealso marker="#equal/4"><c>equal/4</c></seealso>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:casefold("Ω and ẞ SHARP S").</input> +"ω and ss sharp s"</pre> + </desc> + </func> + + <func> + <name name="chomp" arity="1"/> + <fsummary>Remove trailing end of line control characters.</fsummary> + <desc> + <p> + Returns a string where any trailing <c>\n</c> or + <c>\r\n</c> have been removed from <c><anno>String</anno></c>. + </p> + <p><em>Example:</em></p> + <pre> +182> <input>string:chomp(<<"\nHello\n\n">>).</input> +<<"\nHello">> +183> <input>string:chomp("\nHello\r\r\n").</input> +"\nHello\r"</pre> + </desc> + </func> + + <func> + <name name="equal" arity="2"/> + <name name="equal" arity="3"/> + <name name="equal" arity="4"/> + <fsummary>Test string equality.</fsummary> + <desc> + <p> + Returns <c>true</c> if <c><anno>A</anno></c> and + <c><anno>B</anno></c> are equal, otherwise <c>false</c>. + </p> + <p> + If <c><anno>IgnoreCase</anno></c> is <c>true</c> + the function does <seealso marker="#casefold/1"> + <c>casefold</c>ing</seealso> on the fly before the equality test. + </p> + <p>If <c><anno>Norm</anno></c> is not <c>none</c> + the function applies normalization on the fly before the equality test. + There are four available normalization forms: + <seealso marker="unicode#characters_to_nfc_list/1"> <c>nfc</c></seealso>, + <seealso marker="unicode#characters_to_nfd_list/1"> <c>nfd</c></seealso>, + <seealso marker="unicode#characters_to_nfkc_list/1"> <c>nfkc</c></seealso>, and + <seealso marker="unicode#characters_to_nfkd_list/1"> <c>nfkd</c></seealso>. + </p> + <p>By default, + <c><anno>IgnoreCase</anno></c> is <c>false</c> and + <c><anno>Norm</anno></c> is <c>none</c>.</p> + <p><em>Example:</em></p> + <pre> +1> <input>string:equal("åäö", <<"åäö"/utf8>>).</input> +true +2> <input>string:equal("åäö", unicode:characters_to_nfd_binary("åäö")).</input> +false +3> <input>string:equal("åäö", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).</input> +true</pre> + </desc> + </func> + + <func> + <name name="find" arity="2"/> + <name name="find" arity="3"/> + <fsummary>Find start of substring.</fsummary> + <desc> + <p> + Removes anything before <c><anno>SearchPattern</anno></c> in <c><anno>String</anno></c> + and returns the remainder of the string or <c>nomatch</c> if <c><anno>SearchPattern</anno></c> is not + found. + <c><anno>Dir</anno></c>, which can be <c>leading</c> or + <c>trailing</c>, indicates from which direction characters + are to be searched. + </p> + <p> + By default, <c><anno>Dir</anno></c> is <c>leading</c>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:find("ab..cd..ef", ".").</input> +"..cd..ef" +2> <input>string:find(<<"ab..cd..ef">>, "..", trailing).</input> +<<"..ef">> +3> <input>string:find(<<"ab..cd..ef">>, "x", leading).</input> +nomatch +4> <input>string:find("ab..cd..ef", "x", trailing).</input> +nomatch</pre> + </desc> + </func> + + <func> + <name name="is_empty" arity="1"/> + <fsummary>Check if the string is empty.</fsummary> + <desc> + <p>Returns <c>true</c> if <c><anno>String</anno></c> is the + empty string, otherwise <c>false</c>.</p> + <p><em>Example:</em></p> + <pre> +1> <input>string:is_empty("foo").</input> +false +2> <input>string:is_empty(["",<<>>]).</input> +true</pre> + </desc> + </func> + + <func> + <name name="length" arity="1"/> + <fsummary>Calculate length of the string.</fsummary> + <desc> + <p> + Returns the number of grapheme clusters in <c><anno>String</anno></c>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:length("ß↑e̊").</input> +3 +2> <input>string:length(<<195,159,226,134,145,101,204,138>>).</input> +3</pre> + </desc> + </func> + + <func> + <name name="lexemes" arity="2"/> + <fsummary>Split string into lexemes.</fsummary> + <desc> + <p> + Returns a list of lexemes in <c><anno>String</anno></c>, separated + by the grapheme clusters in <c><anno>SeparatorList</anno></c>. + </p> + <p> + Notice that, as shown in this example, two or more + adjacent separator graphemes clusters in <c><anno>String</anno></c> + are treated as one. That is, there are no empty + strings in the resulting list of lexemes. + See also <seealso marker="#split/3"><c>split/3</c></seealso> which returns + empty strings. + </p> + <p>Notice that <c>[$\r,$\n]</c> is one grapheme cluster.</p> + <p><em>Example:</em></p> + <pre> +1> <input>string:lexemes("abc de̊fxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).</input> +["abc","de̊f","ghi","jkl","foo"] +2> <input>string:lexemes(<<"abc de̊fxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).</input> +[<<"abc">>,<<"de̊f"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]</pre> + </desc> + </func> + + <func> + <name name="lowercase" arity="1"/> + <fsummary>Convert a string to lowercase</fsummary> + <desc> + <p> + Converts <c><anno>String</anno></c> to lowercase. + </p> + <p> + Notice that function <seealso marker="#casefold/1"><c>casefold/1</c></seealso> + should be used when converting a string to + be tested for equality. + </p> + <p><em>Example:</em></p> + <pre> +2> <input>string:lowercase(string:uppercase("Michał")).</input> +"michał"</pre> + </desc> + </func> + + <func> + <name name="next_codepoint" arity="1"/> + <fsummary>Pick the first codepoint.</fsummary> + <desc> + <p> + Returns the first codepoint in <c><anno>String</anno></c> + and the rest of <c><anno>String</anno></c> in the tail. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:next_codepoint(unicode:characters_to_binary("e̊fg")).</input> +[101|<<"̊fg"/utf8>>]</pre> + </desc> + </func> + + <func> + <name name="next_grapheme" arity="1"/> + <fsummary>Pick the first grapheme cluster.</fsummary> + <desc> + <p> + Returns the first grapheme cluster in <c><anno>String</anno></c> + and the rest of <c><anno>String</anno></c> in the tail. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:next_grapheme(unicode:characters_to_binary("e̊fg")).</input> +["e̊"|<<"fg">>]</pre> + </desc> + </func> + + <func> + <name name="nth_lexeme" arity="3"/> + <fsummary>Pick the nth lexeme.</fsummary> + <desc> + <p>Returns lexeme number <c><anno>N</anno></c> in + <c><anno>String</anno></c>, where lexemes are separated by + the grapheme clusters in <c><anno>SeparatorList</anno></c>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:nth_lexeme("abc.de̊f.ghiejkl", 3, ".e").</input> +"ghi"</pre> + </desc> + </func> + + <func> + <name name="pad" arity="2"/> + <name name="pad" arity="3"/> + <name name="pad" arity="4"/> + <fsummary>Pad a string to given length.</fsummary> + <desc> + <p> + Pads <c><anno>String</anno></c> to <c><anno>Length</anno></c> with + grapheme cluster <c><anno>Char</anno></c>. + <c><anno>Dir</anno></c>, which can be <c>leading</c>, <c>trailing</c>, + or <c>both</c>, indicates where the padding should be added. + </p> + <p>By default, <c><anno>Char</anno></c> is <c>$\s</c> and + <c><anno>Dir</anno></c> is <c>trailing</c>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:pad(<<"He̊llö"/utf8>>, 8).</input> +[<<72,101,204,138,108,108,195,182>>,32,32,32] +2> <input>io:format("'~ts'~n",[string:pad("He̊llö", 8, leading)]).</input> +' He̊llö' +3> <input>io:format("'~ts'~n",[string:pad("He̊llö", 8, both)]).</input> +' He̊llö '</pre> + </desc> + </func> + + <func> + <name name="prefix" arity="2"/> + <fsummary>Remove prefix from string.</fsummary> + <desc> + <p> + If <c><anno>Prefix</anno></c> is the prefix of + <c><anno>String</anno></c>, removes it and returns the + remainder of <c><anno>String</anno></c>, otherwise returns + <c>nomatch</c>. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:prefix(<<"prefix of string">>, "pre").</input> +<<"fix of string">> +2> <input>string:prefix("pre", "prefix").</input> +nomatch</pre> + </desc> + </func> + + <func> + <name name="replace" arity="3"/> + <name name="replace" arity="4"/> + <fsummary>Replace a pattern in string.</fsummary> + <desc> + <p> + Replaces <c><anno>SearchPattern</anno></c> in <c><anno>String</anno></c> + with <c><anno>Replacement</anno></c>. + <c><anno>Where</anno></c>, default <c>leading</c>, indicates whether + the <c>leading</c>, the <c>trailing</c> or <c>all</c> encounters of + <c><anno>SearchPattern</anno></c> are to be replaced. + </p> + <p>Can be implemented as:</p> + <pre>lists:join(Replacement, split(String, SearchPattern, Where)).</pre> + <p><em>Example:</em></p> + <pre> +1> <input>string:replace(<<"ab..cd..ef">>, "..", "*").</input> +[<<"ab">>,"*",<<"cd..ef">>] +2> <input>string:replace(<<"ab..cd..ef">>, "..", "*", all).</input> +[<<"ab">>,"*",<<"cd">>,"*",<<"ef">>]</pre> + </desc> + </func> + + <func> + <name name="reverse" arity="1"/> + <fsummary>Reverses a string</fsummary> + <desc> + <p> + Returns the reverse list of the grapheme clusters in <c><anno>String</anno></c>. + </p> + <p><em>Example:</em></p> + <pre> +1> Reverse = <input>string:reverse(unicode:characters_to_nfd_binary("ÅÄÖ")).</input> +[[79,776],[65,776],[65,778]] +2> <input>io:format("~ts~n",[Reverse]).</input> +ÖÄÅ</pre> + </desc> + </func> + + <func> + <name name="slice" arity="2"/> + <name name="slice" arity="3"/> + <fsummary>Extract a part of string</fsummary> + <desc> + <p>Returns a substring of <c><anno>String</anno></c> of + at most <c><anno>Length</anno></c> grapheme clusters, starting at position + <c><anno>Start</anno></c>.</p> + <p>By default, <c><anno>Length</anno></c> is <c>infinity</c>.</p> + <p><em>Example:</em></p> + <pre> +1> <input>string:slice(<<"He̊llö Wörld"/utf8>>, 4).</input> +<<"ö Wörld"/utf8>> +2> <input>string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,4).</input> +"ö Wö" +3> <input>string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,50).</input> +"ö Wörld"</pre> + </desc> + </func> + + <func> + <name name="split" arity="2"/> + <name name="split" arity="3"/> + <fsummary>Split a string into substrings.</fsummary> + <desc> + <p> + Splits <c><anno>String</anno></c> where <c><anno>SearchPattern</anno></c> + is encountered and return the remaining parts. + <c><anno>Where</anno></c>, default <c>leading</c>, indicates whether + the <c>leading</c>, the <c>trailing</c> or <c>all</c> encounters of + <c><anno>SearchPattern</anno></c> will split <c><anno>String</anno></c>. + </p> + <p><em>Example:</em></p> + <pre> +0> <input>string:split("ab..bc..cd", "..").</input> +["ab","bc..cd"] +1> <input>string:split(<<"ab..bc..cd">>, "..", trailing).</input> +[<<"ab..bc">>,<<"cd">>] +2> <input>string:split(<<"ab..bc....cd">>, "..", all).</input> +[<<"ab">>,<<"bc">>,<<>>,<<"cd">>]</pre> + </desc> + </func> + + <func> + <name name="take" arity="2"/> + <name name="take" arity="3"/> + <name name="take" arity="4"/> + <fsummary>Take leading or trailing parts.</fsummary> + <desc> + <p>Takes characters from <c><anno>String</anno></c> as long as + the characters are members of set <c><anno>Characters</anno></c> + or the complement of set <c><anno>Characters</anno></c>. + <c><anno>Dir</anno></c>, + which can be <c>leading</c> or <c>trailing</c>, indicates from + which direction characters are to be taken. + </p> + <p><em>Example:</em></p> + <pre> +5> <input>string:take("abc0z123", lists:seq($a,$z)).</input> +{"abc","0z123"} +6> <input>string:take(<<"abc0z123">>, lists:seq($0,$9), true, leading).</input> +{<<"abc">>,<<"0z123">>} +7> <input>string:take("abc0z123", lists:seq($0,$9), false, trailing).</input> +{"abc0z","123"} +8> <input>string:take(<<"abc0z123">>, lists:seq($a,$z), true, trailing).</input> +{<<"abc0z">>,<<"123">>}</pre> + </desc> + </func> + + <func> + <name name="titlecase" arity="1"/> + <fsummary>Convert a string to titlecase.</fsummary> + <desc> + <p> + Converts <c><anno>String</anno></c> to titlecase. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:titlecase("ß is a SHARP s").</input> +"Ss is a SHARP s"</pre> + </desc> + </func> + + <func> + <name name="to_float" arity="1"/> + <fsummary>Return a float whose text representation is the integers + (ASCII values) of a string.</fsummary> + <desc> + <p>Argument <c><anno>String</anno></c> is expected to start with a + valid text represented float (the digits are ASCII values). + Remaining characters in the string after the float are returned in + <c><anno>Rest</anno></c>.</p> + <p><em>Example:</em></p> + <pre> +> <input>{F1,Fs} = string:to_float("1.0-1.0e-1"),</input> +> <input>{F2,[]} = string:to_float(Fs),</input> +> <input>F1+F2.</input> +0.9 +> <input>string:to_float("3/2=1.5").</input> +{error,no_float} +> <input>string:to_float("-1.5eX").</input> +{-1.5,"eX"}</pre> + </desc> + </func> + + <func> + <name name="to_integer" arity="1"/> + <fsummary>Return an integer whose text representation is the integers + (ASCII values) of a string.</fsummary> + <desc> + <p>Argument <c><anno>String</anno></c> is expected to start with a + valid text represented integer (the digits are ASCII values). + Remaining characters in the string after the integer are returned in + <c><anno>Rest</anno></c>.</p> + <p><em>Example:</em></p> + <pre> +> <input>{I1,Is} = string:to_integer("33+22"),</input> +> <input>{I2,[]} = string:to_integer(Is),</input> +> <input>I1-I2.</input> +11 +> <input>string:to_integer("0.5").</input> +{0,".5"} +> <input>string:to_integer("x=2").</input> +{error,no_integer}</pre> + </desc> + </func> + + <func> + <name name="to_graphemes" arity="1"/> + <fsummary>Convert a string to a list of grapheme clusters.</fsummary> + <desc> + <p> + Converts <c><anno>String</anno></c> to a list of grapheme clusters. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:to_graphemes("ß↑e̊").</input> +[223,8593,[101,778]] +2> <input>string:to_graphemes(<<"ß↑e̊"/utf8>>).</input> +[223,8593,[101,778]]</pre> + </desc> + </func> + + <func> + <name name="trim" arity="1"/> + <name name="trim" arity="2"/> + <name name="trim" arity="3"/> + <fsummary>Trim leading or trailing, or both, characters.</fsummary> + <desc> + <p> + Returns a string, where leading or trailing, or both, + <c><anno>Characters</anno></c> have been removed. + <c><anno>Dir</anno></c> which can be <c>leading</c>, <c>trailing</c>, + or <c>both</c>, indicates from which direction characters + are to be removed. + </p> + <p> Default <c><anno>Characters</anno></c> are the set of + nonbreakable whitespace codepoints, defined as + Pattern_White_Space in + <url href="http://unicode.org/reports/tr31/">Unicode Standard Annex #31</url>. + <c>By default, <anno>Dir</anno></c> is <c>both</c>. + </p> + <p> + Notice that <c>[$\r,$\n]</c> is one grapheme cluster according + to the Unicode Standard. + </p> + <p><em>Example:</em></p> + <pre> +1> <input>string:trim("\t Hello \n").</input> +"Hello" +2> <input>string:trim(<<"\t Hello \n">>, leading).</input> +<<"Hello \n">> +3> <input>string:trim(<<".Hello.\n">>, trailing, "\n.").</input> +<<".Hello">></pre> + </desc> + </func> + + <func> + <name name="uppercase" arity="1"/> + <fsummary>Convert a string to uppercase.</fsummary> + <desc> + <p> + Converts <c><anno>String</anno></c> to uppercase. + </p> + <p>See also <seealso marker="#titlecase/1"><c>titlecase/1</c></seealso>.</p> + <p><em>Example:</em></p> + <pre> +1> <input>string:uppercase("Michał").</input> +"MICHAŁ"</pre> + </desc> + </func> + + </funcs> + + <section> + <marker id="oldapi"/> + <title>Obsolete API functions</title> + <p>Here follows the function of the old API. + These functions only work on a list of Latin-1 characters. + </p> + <note><p> + The functions are kept for backward compatibility, but are + not recommended. + They will be deprecated in Erlang/OTP 21. + </p> + <p>Any undocumented functions in <c>string</c> are not to be used.</p> + </note> + </section> + <funcs> <func> <name name="centre" arity="2"/> @@ -47,17 +652,24 @@ <p>Returns a string, where <c><anno>String</anno></c> is centered in the string and surrounded by blanks or <c><anno>Character</anno></c>. The resulting string has length <c><anno>Number</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#pad/3"><c>pad/3</c></seealso>. + </p> </desc> </func> <func> <name name="chars" arity="2"/> <name name="chars" arity="3"/> - <fsummary>Returns a string consisting of numbers of characters.</fsummary> + <fsummary>Return a string consisting of numbers of characters.</fsummary> <desc> <p>Returns a string consisting of <c><anno>Number</anno></c> characters <c><anno>Character</anno></c>. Optionally, the string can end with string <c><anno>Tail</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="lists#duplicate/2"><c>lists:duplicate/2</c></seealso>.</p> </desc> </func> @@ -69,6 +681,9 @@ <p>Returns the index of the first occurrence of <c><anno>Character</anno></c> in <c><anno>String</anno></c>. Returns <c>0</c> if <c><anno>Character</anno></c> does not occur.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#find/2"><c>find/2</c></seealso>.</p> </desc> </func> @@ -79,6 +694,16 @@ <p>Concatenates <c><anno>String1</anno></c> and <c><anno>String2</anno></c> to form a new string <c><anno>String3</anno></c>, which is returned.</p> + <p> + This function is <seealso marker="#oldapi">obsolete</seealso>. + Use <c>[<anno>String1</anno>, <anno>String2</anno>]</c> as + <c>Data</c> argument, and call + <seealso marker="unicode#characters_to_list/2"> + <c>unicode:characters_to_list/2</c></seealso> or + <seealso marker="unicode#characters_to_binary/2"> + <c>unicode:characters_to_binary/2</c></seealso> + to flatten the output. + </p> </desc> </func> @@ -88,6 +713,9 @@ <desc> <p>Returns a string containing <c><anno>String</anno></c> repeated <c><anno>Number</anno></c> times.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="lists#duplicate/2"><c>lists:duplicate/2</c></seealso>.</p> </desc> </func> @@ -98,6 +726,9 @@ <p>Returns the length of the maximum initial segment of <c><anno>String</anno></c>, which consists entirely of characters not from <c><anno>Chars</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#take/3"><c>take/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:cspan("\t abcdef", " \t"). @@ -106,20 +737,14 @@ </func> <func> - <name name="equal" arity="2"/> - <fsummary>Test string equality.</fsummary> - <desc> - <p>Returns <c>true</c> if <c><anno>String1</anno></c> and - <c><anno>String2</anno></c> are equal, otherwise <c>false</c>.</p> - </desc> - </func> - - <func> <name name="join" arity="2"/> <fsummary>Join a list of strings with separator.</fsummary> <desc> <p>Returns a string with the elements of <c><anno>StringList</anno></c> separated by the string in <c><anno>Separator</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="lists#join/2"><c>lists:join/2</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > join(["one", "two", "three"], ", "). @@ -137,6 +762,10 @@ fixed. If <c>length(<anno>String</anno>)</c> < <c><anno>Number</anno></c>, then <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#pad/2"><c>pad/2</c></seealso> or + <seealso marker="#pad/3"><c>pad/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:left("Hello",10,$.). @@ -149,6 +778,9 @@ <fsummary>Return the length of a string.</fsummary> <desc> <p>Returns the number of characters in <c><anno>String</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#length/1"><c>length/1</c></seealso>.</p> </desc> </func> @@ -160,6 +792,9 @@ <p>Returns the index of the last occurrence of <c><anno>Character</anno></c> in <c><anno>String</anno></c>. Returns <c>0</c> if <c><anno>Character</anno></c> does not occur.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#find/3"><c>find/3</c></seealso>.</p> </desc> </func> @@ -173,6 +808,9 @@ fixed. If the length of <c>(<anno>String</anno>)</c> < <c><anno>Number</anno></c>, then <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#pad/3"><c>pad/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:right("Hello", 10, $.). @@ -188,6 +826,9 @@ <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. Returns <c>0</c> if <c><anno>SubString</anno></c> does not exist in <c><anno>String</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#find/3"><c>find/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:rstr(" Hello Hello World World ", "Hello World"). @@ -202,6 +843,9 @@ <p>Returns the length of the maximum initial segment of <c><anno>String</anno></c>, which consists entirely of characters from <c><anno>Chars</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#take/2"><c>take/2</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:span("\t abcdef", " \t"). @@ -217,6 +861,9 @@ <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. Returns <c>0</c> if <c><anno>SubString</anno></c> does not exist in <c><anno>String</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#find/2"><c>find/2</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:str(" Hello Hello World World ", "Hello World"). @@ -230,12 +877,15 @@ <name name="strip" arity="3"/> <fsummary>Strip leading or trailing characters.</fsummary> <desc> - <p>Returns a string, where leading and/or trailing blanks or a + <p>Returns a string, where leading or trailing, or both, blanks or a number of <c><anno>Character</anno></c> have been removed. <c><anno>Direction</anno></c>, which can be <c>left</c>, <c>right</c>, or <c>both</c>, indicates from which direction blanks are to be removed. <c>strip/1</c> is equivalent to <c>strip(String, both)</c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#trim/3"><c>trim/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:strip("...Hello.....", both, $.). @@ -251,6 +901,9 @@ <p>Returns a substring of <c><anno>String</anno></c>, starting at position <c><anno>Start</anno></c> to the end of the string, or to and including position <c><anno>Stop</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#slice/3"><c>slice/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> sub_string("Hello World", 4, 8). @@ -266,6 +919,9 @@ sub_string("Hello World", 4, 8). <p>Returns a substring of <c><anno>String</anno></c>, starting at position <c><anno>Start</anno></c>, and ending at the end of the string or at length <c><anno>Length</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#slice/3"><c>slice/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > substr("Hello World", 4, 5). @@ -281,6 +937,9 @@ sub_string("Hello World", 4, 8). <p>Returns the word in position <c><anno>Number</anno></c> of <c><anno>String</anno></c>. Words are separated by blanks or <c><anno>Character</anno></c>s.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#nth_lexeme/3"><c>nth_lexeme/3</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > string:sub_word(" Hello old boy !",3,$o). @@ -289,50 +948,6 @@ sub_string("Hello World", 4, 8). </func> <func> - <name name="to_float" arity="1"/> - <fsummary>Returns a float whose text representation is the integers - (ASCII values) in a string.</fsummary> - <desc> - <p>Argument <c><anno>String</anno></c> is expected to start with a - valid text represented float (the digits are ASCII values). - Remaining characters in the string after the float are returned in - <c><anno>Rest</anno></c>.</p> - <p><em>Example:</em></p> - <code type="none"> -> {F1,Fs} = string:to_float("1.0-1.0e-1"), -> {F2,[]} = string:to_float(Fs), -> F1+F2. -0.9 -> string:to_float("3/2=1.5"). -{error,no_float} -> string:to_float("-1.5eX"). -{-1.5,"eX"}</code> - </desc> - </func> - - <func> - <name name="to_integer" arity="1"/> - <fsummary>Returns an integer whose text representation is the integers - (ASCII values) in a string.</fsummary> - <desc> - <p>Argument <c><anno>String</anno></c> is expected to start with a - valid text represented integer (the digits are ASCII values). - Remaining characters in the string after the integer are returned in - <c><anno>Rest</anno></c>.</p> - <p><em>Example:</em></p> - <code type="none"> -> {I1,Is} = string:to_integer("33+22"), -> {I2,[]} = string:to_integer(Is), -> I1-I2. -11 -> string:to_integer("0.5"). -{0,".5"} -> string:to_integer("x=2"). -{error,no_integer}</code> - </desc> - </func> - - <func> <name name="to_lower" arity="1" clause_i="1"/> <name name="to_lower" arity="1" clause_i="2"/> <name name="to_upper" arity="1" clause_i="1"/> @@ -346,6 +961,11 @@ sub_string("Hello World", 4, 8). <p>The specified string or character is case-converted. Notice that the supported character set is ISO/IEC 8859-1 (also called Latin 1); all values outside this set are unchanged</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso> use + <seealso marker="#lowercase/1"><c>lowercase/1</c></seealso>, + <seealso marker="#uppercase/1"><c>uppercase/1</c></seealso>, + <seealso marker="#titlecase/1"><c>titlecase/1</c></seealso> or + <seealso marker="#casefold/1"><c>casefold/1</c></seealso>.</p> </desc> </func> @@ -363,6 +983,9 @@ sub_string("Hello World", 4, 8). adjacent separator characters in <c><anno>String</anno></c> are treated as one. That is, there are no empty strings in the resulting list of tokens.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#lexemes/2"><c>lexemes/2</c></seealso>.</p> </desc> </func> @@ -373,6 +996,9 @@ sub_string("Hello World", 4, 8). <desc> <p>Returns the number of words in <c><anno>String</anno></c>, separated by blanks or <c><anno>Character</anno></c>.</p> + <p>This function is <seealso marker="#oldapi">obsolete</seealso>. + Use + <seealso marker="#lexemes/2"><c>lexemes/2</c></seealso>.</p> <p><em>Example:</em></p> <code type="none"> > words(" Hello old boy!", $o). @@ -387,10 +1013,7 @@ sub_string("Hello World", 4, 8). other. The reason is that this string package is the combination of two earlier packages and all functions of both packages have been retained.</p> - - <note> - <p>Any undocumented functions in <c>string</c> are not to be used.</p> - </note> </section> + </erlref> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index bb06d3645e..a42cfdd567 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -36,7 +36,6 @@ process can either be another supervisor or a worker process. Worker processes are normally implemented using one of the <seealso marker="gen_event"><c>gen_event</c></seealso>, - <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>, <seealso marker="gen_server"><c>gen_server</c></seealso>, or <seealso marker="gen_statem"><c>gen_statem</c></seealso> behaviors. A supervisor implemented using this module has @@ -237,8 +236,8 @@ child_spec() = #{id => child_id(), % mandatory <p><c>modules</c> is used by the release handler during code replacement to determine which processes are using a certain module. As a rule of thumb, if the child process is a - <c>supervisor</c>, <c>gen_server</c>, - <c>gen_statem</c>, or <c>gen_fsm</c>, + <c>supervisor</c>, <c>gen_server</c> or, + <c>gen_statem</c>, this is to be a list with one element <c>[Module]</c>, where <c>Module</c> is the callback module. If the child process is an event manager (<c>gen_event</c>) with a @@ -706,7 +705,6 @@ child_spec() = #{id => child_id(), % mandatory <section> <title>See Also</title> <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>, - <seealso marker="gen_fsm"><c>gen_fsm(3)</c></seealso>, <seealso marker="gen_statem"><c>gen_statem(3)</c></seealso>, <seealso marker="gen_server"><c>gen_server(3)</c></seealso>, <seealso marker="sys"><c>sys(3)</c></seealso></p> diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index 45171f814d..78840aaaf3 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -168,12 +168,6 @@ </item> <item> <p>For a - <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> - process, <c><anno>State</anno></c> is the tuple - <c>{CurrentStateName, CurrentStateData}</c>.</p> - </item> - <item> - <p>For a <seealso marker="gen_statem"><c>gen_statem</c></seealso> process, <c><anno>State</anno></c> is the tuple <c>{CurrentState,CurrentData}</c>.</p> @@ -222,7 +216,7 @@ <p>Function <c>system_get_state/1</c> is primarily useful for user-defined behaviors and modules that implement OTP <seealso marker="#special_process">special processes</seealso>. - The <c>gen_server</c>, <c>gen_fsm</c>, + The <c>gen_server</c>, <c>gen_statem</c>, and <c>gen_event</c> OTP behavior modules export this function, so callback modules for those behaviors need not to supply their own.</p> @@ -246,11 +240,6 @@ process returns the state of the callback module.</p> </item> <item> - <p>A <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> - process returns information, such as its current - state name and state data.</p> - </item> - <item> <p>A <seealso marker="gen_statem"><c>gen_statem</c></seealso> process returns information, such as its current state name and state data.</p> @@ -262,14 +251,12 @@ </item> </list> <p>Callback modules for <c>gen_server</c>, - <c>gen_fsm</c>, <c>gen_statem</c>, and <c>gen_event</c> + <c>gen_statem</c>, and <c>gen_event</c> can also change the value of <c><anno>Misc</anno></c> by exporting a function <c>format_status/2</c>, which contributes module-specific information. For details, see <seealso marker="gen_server#Module:format_status/2"> <c>gen_server:format_status/2</c></seealso>, - <seealso marker="gen_fsm#Module:format_status/2"> - <c>gen_fsm:format_status/2</c></seealso>, <seealso marker="gen_statem#Module:format_status/2"> <c>gen_statem:format_status/2</c></seealso>, and <seealso marker="gen_event#Module:format_status/2"> @@ -373,13 +360,6 @@ is a new instance of that state.</p> </item> <item> - <p>For a <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> process, - <c><anno>State</anno></c> is the tuple <c>{CurrentStateName, - CurrentStateData}</c>, and <c><anno>NewState</anno></c> is a - similar tuple, which can contain - a new state name, new state data, or both.</p> - </item> - <item> <p>For a <seealso marker="gen_statem"><c>gen_statem</c></seealso> process, <c><anno>State</anno></c> is the tuple <c>{CurrentState,CurrentData}</c>, @@ -422,7 +402,7 @@ return its <c><anno>State</anno></c> argument.</p> <p>If a <c><anno>StateFun</anno></c> function crashes or throws an exception, the original state of the process is unchanged for - <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_statem</c> processes. + <c>gen_server</c>, and <c>gen_statem</c> processes. For <c>gen_event</c> processes, a crashing or failing <c><anno>StateFun</anno></c> function means that only the state of the particular event handler it was @@ -462,7 +442,7 @@ user-defined behaviors and modules that implement OTP <seealso marker="#special_process">special processes</seealso>. The OTP behavior modules <c>gen_server</c>, - <c>gen_fsm</c>, <c>gen_statem</c>, and <c>gen_event</c> + <c>gen_statem</c>, and <c>gen_event</c> export this function, so callback modules for those behaviors need not to supply their own.</p> </desc> diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml index 93d0d37456..382b253ba1 100644 --- a/lib/stdlib/doc/src/unicode.xml +++ b/lib/stdlib/doc/src/unicode.xml @@ -50,8 +50,35 @@ external entities where this is required. When working inside the Erlang/OTP environment, it is recommended to keep binaries in UTF-8 when representing Unicode characters. ISO Latin-1 encoding is supported both - for backward compatibility and for communication - with external entities not supporting Unicode character sets.</p> + for backward compatibility and for communication + with external entities not supporting Unicode character sets.</p> + <p>Programs should always operate on a normalized form and compare + canonical-equivalent Unicode characters as equal. All characters + should thus be normalized to one form once on the system borders. + One of the following functions can convert characters to their + normalized forms <seealso marker="#characters_to_nfc_list/1"> + <c>characters_to_nfc_list/1</c></seealso>, + <seealso marker="#characters_to_nfc_binary/1"> + <c>characters_to_nfc_binary/1</c></seealso>, + <seealso marker="#characters_to_nfd_list/1"> + <c>characters_to_nfd_list/1</c></seealso> or + <seealso marker="#characters_to_nfd_binary/1"> + <c>characters_to_nfd_binary/1</c></seealso>. + For general text + <seealso marker="#characters_to_nfc_list/1"> + <c>characters_to_nfc_list/1</c></seealso> or + <seealso marker="#characters_to_nfc_binary/1"> + <c>characters_to_nfc_binary/1</c></seealso> is preferred, and + for identifiers one of the compatibility normalization + functions, such as + <seealso marker="#characters_to_nfkc_list/1"> + <c>characters_to_nfkc_list/1</c></seealso>, + is preferred for security reasons. + The normalization functions where introduced in OTP 20. + Additional information on normalization can be found in the + <url href="http://unicode.org/faq/normalization.html">Unicode FAQ</url>. + </p> + </description> <datatypes> @@ -335,6 +362,154 @@ decode_data(Data) -> </func> <func> + <name name="characters_to_nfc_list" arity="1"/> + <fsummary>Normalize characters to a list of canonical equivalent + composed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of canonical equivalent Composed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding. + </p> + <p>The result is a list of characters.</p> + <code> +3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]). +"abc..åäö" +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfc_binary" arity="1"/> + <fsummary>Normalize characters to a utf8 binary of canonical equivalent + composed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of canonical equivalent Composed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding.</p> + <p>The result is an utf8 encoded binary.</p> + <code> +4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]). +<<"abc..åäö"/utf8>> +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfd_list" arity="1"/> + <fsummary>Normalize characters to a list of canonical equivalent + decomposed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of canonical equivalent Decomposed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding. + </p> + <p>The result is a list of characters.</p> + <code> +1> unicode:characters_to_nfd_list("abc..åäö"). +[97,98,99,46,46,97,778,97,776,111,776] +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfd_binary" arity="1"/> + <fsummary>Normalize characters to a utf8 binary of canonical equivalent + decomposed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of canonical equivalent Decomposed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding.</p> + <p>The result is an utf8 encoded binary.</p> + <code> +2> unicode:characters_to_nfd_binary("abc..åäö"). +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>> +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfkc_list" arity="1"/> + <fsummary>Normalize characters to a list of canonical equivalent + composed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of compatibly equivalent Composed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding. + </p> + <p>The result is a list of characters.</p> + <code> +3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]). +"abc..åäö32" +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfkc_binary" arity="1"/> + <fsummary>Normalize characters to a utf8 binary of compatibly equivalent + composed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of compatibly equivalent Composed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding.</p> + <p>The result is an utf8 encoded binary.</p> + <code> +4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]). +<<"abc..åäö32"/utf8>> +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfkd_list" arity="1"/> + <fsummary>Normalize characters to a list of compatibly equivalent + decomposed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of compatibly equivalent Decomposed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding. + </p> + <p>The result is a list of characters.</p> + <code> +1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]). +[97,98,99,46,46,97,778,97,776,111,776,51,50] +</code> + </desc> + </func> + + <func> + <name name="characters_to_nfkd_binary" arity="1"/> + <fsummary>Normalize characters to a utf8 binary of compatibly equivalent + decomposed Unicode characters.</fsummary> + <desc> + <p>Converts a possibly deep list of characters and binaries + into a Normalized Form of compatibly equivalent Decomposed + characters according to the Unicode standard.</p> + <p>Any binaries in the input must be encoded with utf8 + encoding.</p> + <p>The result is an utf8 encoded binary.</p> + <code> +2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]). +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>> +</code> + </desc> + </func> + + <func> <name name="encoding_to_bom" arity="1"/> <fsummary>Create a binary UTF byte order mark from encoding.</fsummary> <type_desc variable="Bin"> diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index a8ef8ff5c5..6af2fa9fa3 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -64,8 +64,11 @@ source files was switched to UTF-8.</p></item> <item><p>In Erlang/OTP 20.0, atoms and function can contain - Unicode characters. Module names are still restricted to - the ISO-Latin-1 range.</p></item> + Unicode characters. Module names, application names, and node + names are still restricted to the ISO Latin-1 range.</p> + <p>Support was added for normalizations forms in + <c>unicode</c> and the <c>string</c> module now handles + utf8-encoded binaries.</p></item> </list> <p>This section outlines the current Unicode support and gives some @@ -110,23 +113,27 @@ </item> </list> - <p>So, a conversion function must know not only one character at a time, - but possibly the whole sentence, the natural language to translate to, - the differences in input and output string length, and so on. - Erlang/OTP has currently no Unicode <c>to_upper</c>/<c>to_lower</c> - functionality, but publicly available libraries address these issues.</p> - - <p>Another example is the accented characters, where the same glyph has two - different representations. The Swedish letter "ö" is one example. - The Unicode standard has a code point for it, but you can also write it - as "o" followed by "U+0308" (Combining Diaeresis, with the simplified - meaning that the last letter is to have "¨" above). They have the same - glyph. They are for most purposes the same, but have different - representations. For example, MacOS X converts all filenames to use - Combining Diaeresis, while most other programs (including Erlang) try to - hide that by doing the opposite when, for example, listing directories. - However it is done, it is usually important to normalize such - characters to avoid confusion.</p> + <p>So, a conversion function must know not only one character at a + time, but possibly the whole sentence, the natural language to + translate to, the differences in input and output string length, + and so on. Erlang/OTP has currently no Unicode + <c>uppercase</c>/<c>lowercase</c> functionality with language + specific handling, but publicly available libraries address these + issues.</p> + + <p>Another example is the accented characters, where the same + glyph has two different representations. The Swedish letter "ö" is + one example. The Unicode standard has a code point for it, but + you can also write it as "o" followed by "U+0308" (Combining + Diaeresis, with the simplified meaning that the last letter is to + have "¨" above). They have the same glyph, user perceived + character. They are for most purposes the same, but have different + representations. For example, MacOS X converts all filenames to + use Combining Diaeresis, while most other programs (including + Erlang) try to hide that by doing the opposite when, for example, + listing directories. However it is done, it is usually important + to normalize such characters to avoid confusion. + </p> <p>The list of examples can be made long. One need a kind of knowledge that was not needed when programs only considered one or two languages. The @@ -273,7 +280,7 @@ them. In some cases functionality has been added to already existing interfaces (as the <seealso marker="stdlib:string"><c>string</c></seealso> module now can - handle lists with any code points). In some cases new + handle strings with any code points). In some cases new functionality or options have been added (as in the <seealso marker="stdlib:io"><c>io</c></seealso> module, the file handling, the <seealso @@ -345,10 +352,11 @@ <p>Having the source code in UTF-8 also allows you to write string literals, function names, and atoms containing Unicode characters with code points > 255. - Module names are still restricted to the ISO Latin-1 range. - Binary literals, where you use type + Module names, application names, and node names are still restricted + to the ISO Latin-1 range. Binary literals, where you use type <c>/utf8</c>, can also be expressed using Unicode characters > 255. - Having module names using characters other than 7-bit ASCII can cause + Having module names or application names using characters other than + 7-bit ASCII can cause trouble on operating systems with inconsistent file naming schemes, and can hurt portability, so it is not recommended.</p> <p>EEP 40 suggests that the language is also to allow for Unicode @@ -444,8 +452,8 @@ external_charlist() = maybe_improper_list(char() | external_unicode_binary() | marker="stdlib:epp#encoding"><c>epp(3)</c></seealso> module. As from Erlang/OTP R16, strings and comments can be written using Unicode. As from Erlang/OTP 20, also atoms and functions can be - written using Unicode. Modules names must still be named using - characters from the ISO Latin-1 character set. (These + written using Unicode. Modules, applications, and nodes must still be + named using characters from the ISO Latin-1 character set. (These restrictions in the language are independent of the encoding of the source file.)</p> @@ -773,7 +781,7 @@ Eshell V5.10.1 (abort with ^G) filenames or directory names. If the file system content is listed, you also get Unicode lists as return value. The support lies in the Kernel and STDLIB modules, which is why - most applications (that does not explicitly require the filenames + most applications (that do not explicitly require the filenames to be in the ISO Latin-1 range) benefit from the Unicode support without change.</p> @@ -977,7 +985,7 @@ Eshell V5.10.1 (abort with ^G) <p>Fortunately, most textual data has been stored in lists and range checking has been sparse, so modules like <c>string</c> work well for - Unicode lists with little need for conversion or extension.</p> + Unicode strings with little need for conversion or extension.</p> <p>Some modules are, however, changed to be explicitly Unicode-aware. These modules include:</p> @@ -1028,18 +1036,17 @@ Eshell V5.10.1 (abort with ^G) has extensive support for Unicode text.</p></item> </taglist> - <p>The <seealso marker="stdlib:string"><c>string</c></seealso> module works - perfectly for Unicode strings and ISO Latin-1 strings, except the - language-dependent functions - <seealso marker="stdlib:string#to_upper/1"><c>string:to_upper/1</c></seealso> - and - <seealso marker="stdlib:string#to_lower/1"><c>string:to_lower/1</c></seealso>, - which are only correct for the ISO Latin-1 character set. These two - functions can never function correctly for Unicode characters in their - current form, as there are language and locale issues as well as - multi-character mappings to consider when converting text between cases. - Converting case in an international environment is a large subject not - yet addressed in OTP.</p> + <p>The <seealso marker="stdlib:string"><c>string</c></seealso> + module works perfectly for Unicode strings and ISO Latin-1 + strings, except the language-dependent functions <seealso + marker="stdlib:string#uppercase/1"><c>string:uppercase/1</c></seealso> + and <seealso + marker="stdlib:string#lowercase/1"><c>string:lowercase/1</c></seealso>. + These two functions can never function correctly for Unicode + characters in their current form, as there are language and locale + issues to consider when converting text between cases. Converting + case in an international environment is a large subject not yet + addressed in OTP.</p> </section> <section> |