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/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 | 15 | ||||
-rw-r--r-- | lib/stdlib/doc/src/io.xml | 6 | ||||
-rw-r--r-- | lib/stdlib/doc/src/io_lib.xml | 3 | ||||
-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/sets.xml | 2 | ||||
-rw-r--r-- | lib/stdlib/doc/src/shell.xml | 21 | ||||
-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 |
16 files changed, 1314 insertions, 1102 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/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..e70f347479 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 <seealso marker="gen_statem"><c>gen_statem</c></seealso> </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 bc86415d28..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,8 +62,8 @@ </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"> @@ -81,8 +81,10 @@ <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 @@ -706,7 +708,7 @@ handle_event(_, _, State, Data) -> </item> <item> <p> - Time-out timers + Time-out timers <seealso marker="#type-event_timeout"><c>event_timeout()</c></seealso>, <seealso marker="#type-generic_timeout"><c>generic_timeout()</c></seealso> and @@ -1018,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> 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 5ae400da62..bc1d77ac83 100644 --- a/lib/stdlib/doc/src/io_lib.xml +++ b/lib/stdlib/doc/src/io_lib.xml @@ -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>. 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/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 ab62c2fcdd..2593d3690b 100644 --- a/lib/stdlib/doc/src/shell.xml +++ b/lib/stdlib/doc/src/shell.xml @@ -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> 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> |