diff options
Diffstat (limited to 'system')
28 files changed, 568 insertions, 476 deletions
diff --git a/system/doc/design_principles/appup_cookbook.xml b/system/doc/design_principles/appup_cookbook.xml index 70c34a5a06..22c48db855 100644 --- a/system/doc/design_principles/appup_cookbook.xml +++ b/system/doc/design_principles/appup_cookbook.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2013</year> + <year>2003</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -132,7 +132,7 @@ code_change(_Vsn, Chs, _Extra) -> loaded.</p> <p>Thus, <c>ch3</c> must be loaded before <c>m1</c> is, in the upgrade case, and vice versa in the downgrade case. We say - that <c>m1</c><em>is dependent on</em><c>ch3</c>. In a release + that <c>m1</c> <em>is dependent on</em> <c>ch3</c>. In a release handling instruction, this is expressed by the element <c>DepMods</c>:</p> <code type="none"> @@ -239,7 +239,7 @@ system_code_change(Chs, _Module, _OldVsn, _Extra) -> <marker id="sup"></marker> <title>Changing a Supervisor</title> <p>The supervisor behaviour supports changing the internal state, - i.e. changing restart strategy and maximum restart frequency + i.e. changing restart strategy and maximum restart intensity properties, as well as changing existing child specifications.</p> <p>Adding and deleting child processes are also possible, but not handled automatically. Instructions must be given by in @@ -267,7 +267,7 @@ system_code_change(Chs, _Module, _OldVsn, _Extra) -> ... init(_Args) -> - {ok, {{one_for_all, 1, 60}, ...}}.</code> + {ok, {#{strategy => one_for_all, ...}, ...}}.</code> <p>The file <c>ch_app.appup</c>:</p> <code type="none"> {"2", diff --git a/system/doc/design_principles/distributed_applications.xml b/system/doc/design_principles/distributed_applications.xml index 2886f06b53..4d4ba3136e 100644 --- a/system/doc/design_principles/distributed_applications.xml +++ b/system/doc/design_principles/distributed_applications.xml @@ -43,7 +43,7 @@ addressing mechanism is required to ensure that it can be addressed by other applications, regardless on which node it currently executes. This issue is not addressed here, but the - Kernel module <c>global</c> or STDLIB module <c>pg</c> can be + Kernel modules <c>global</c> or <c>pg2</c> can be used for this purpose.</p> </section> diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml index ba8a88d1c2..9d1e2c8669 100644 --- a/system/doc/design_principles/release_handling.xml +++ b/system/doc/design_principles/release_handling.xml @@ -310,7 +310,7 @@ the following instruction is used:</p> <code type="none"> {apply, {M, F, A}}</code> - <p>The release handler will evalute <c>apply(M, F, A)</c>.</p> + <p>The release handler will evaluate <c>apply(M, F, A)</c>.</p> </section> <section> @@ -350,7 +350,7 @@ possible.</p> </warning> <p>An info report is written when the upgrade is completed. To - programatically find out if the upgrade is complete, + programmatically find out if the upgrade is complete, call <c>release_handler:which_releases(current)</c> and check if it returns the expected (i.e. the new) release.</p> <p>The new release version must be made permanent when the new diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml index e4fb5fdca7..e849388a38 100644 --- a/system/doc/design_principles/spec_proc.xml +++ b/system/doc/design_principles/spec_proc.xml @@ -431,43 +431,79 @@ loop(...) -> <section> <title>User-Defined Behaviours</title> - <p><marker id="behaviours"/>To implement a user-defined behaviour, write code similar to - code for a special process but calling functions in a callback - module for handling specific tasks.</p> - <p>If it is desired that the compiler should warn for missing callback - functions, as it does for the OTP behaviours, add <c>-callback</c> attributes in the - behaviour module to describe the expected callbacks:</p> + + <p><marker id="behaviours"/>To implement a user-defined behaviour, + write code similar to code for a special process but calling + functions in a callback module for handling specific tasks.</p> + <p>If it is desired that the compiler should warn for missing + callback functions, as it does for the OTP behaviours, add + <c>-callback</c> attributes in the behaviour module to describe + the expected callback functions:</p> + <code type="none"> -callback Name1(Arg1_1, Arg1_2, ..., Arg1_N1) -> Res1. -callback Name2(Arg2_1, Arg2_2, ..., Arg2_N2) -> Res2. ... -callback NameM(ArgM_1, ArgM_2, ..., ArgM_NM) -> ResM.</code> - <p>where <c>NameX</c> are the names of the expected callbacks and - <c>ArgX_Y</c>, <c>ResX</c> are types as they are described in Specifications - for functions in <seealso marker="../reference_manual/typespec">Types and - Function Specifications</seealso>. The whole syntax of <c>-spec</c> attribute is - supported by <c>-callback</c> attribute.</p> - <p>Alternatively you may directly implement and export the function:</p> + + <p>where each <c>Name</c> is the name of a callback function and + <c>Arg</c> and <c>Res</c> are types as described in + Specifications for functions in <seealso + marker="../reference_manual/typespec">Types and Function + Specifications</seealso>. The whole syntax of the + <c>-spec</c> attribute is supported by <c>-callback</c> + attribute.</p> + <p>Callback functions that are optional for the user of the + behaviour to implement are specified by use of the + <c>-optional_callbacks</c> attribute:</p> + +<code type="none"> +-optional_callbacks([OptName1/OptArity1, ..., OptNameK/OptArityK]).</code> + + <p>where each <c>OptName/OptArity</c> specifies the name and arity + of a callback function. Note that the <c>-optional_callbacks</c> + attribute is to be used together with the <c>-callback</c> + attribute; it cannot be combined with the + <c>behaviour_info()</c> function described below.</p> + <p>Tools that need to know about optional callback functions can + call <c>Behaviour:behaviour_info(optional_callbacks)</c> to get + a list of all optional callback functions.</p> + + <note><p>We recommend using the <c>-callback</c> attribute rather + than the <c>behaviour_info()</c> function. The reason is that + the extra type information can be used by tools to produce + documentation or find discrepancies.</p></note> + + <p>As an alternative to the <c>-callback</c> and + <c>-optional_callbacks</c> attributes you may directly implement + and export <c>behaviour_info()</c>:</p> + <code type="none"> behaviour_info(callbacks) -> [{Name1, Arity1},...,{NameN, ArityN}].</code> - <p>where each <c>{Name, Arity}</c> specifies the name and arity of a callback - function. This function is otherwise automatically generated by the compiler - using the <c>-callback</c> attributes.</p> + + <p>where each <c>{Name, Arity}</c> specifies the name and arity of + a callback function. This function is otherwise automatically + generated by the compiler using the <c>-callback</c> + attributes.</p> <p>When the compiler encounters the module attribute - <c>-behaviour(Behaviour).</c> in a module <c>Mod</c>, it will call - <c>Behaviour:behaviour_info(callbacks)</c> and compare the result with the - set of functions actually exported from <c>Mod</c>, and issue a warning if - any callback function is missing.</p> + <c>-behaviour(Behaviour).</c> in a module <c>Mod</c>, it will + call <c>Behaviour:behaviour_info(callbacks)</c> and compare the + result with the set of functions actually exported from + <c>Mod</c>, and issue a warning if any callback function is + missing.</p> <p>Example:</p> <code type="none"> %% User-defined behaviour module -module(simple_server). --export([start_link/2,...]). +-export([start_link/2, init/3, ...]). -callback init(State :: term()) -> 'ok'. -callback handle_req(Req :: term(), State :: term()) -> {'ok', Reply :: term()}. -callback terminate() -> 'ok'. +-callback format_state(State :: term()) -> term(). + +-optional_callbacks([format_state/1]). %% Alternatively you may define: %% diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml index 11ef3813d6..3d7b53e339 100644 --- a/system/doc/design_principles/sup_princ.xml +++ b/system/doc/design_principles/sup_princ.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -29,14 +29,14 @@ <file>sup_princ.xml</file> </header> <p>This section should be read in conjunction with - <c>supervisor(3)</c>, where all details about the supervisor - behaviour is given.</p> + <seealso marker="stdlib:supervisor">supervisor(3)</seealso>, where + all details about the supervisor behaviour are described.</p> <section> <title>Supervision Principles</title> - <p>A supervisor is responsible for starting, stopping and + <p>A supervisor is responsible for starting, stopping, and monitoring its child processes. The basic idea of a supervisor is - that it should keep its child processes alive by restarting them + that it shall keep its child processes alive by restarting them when necessary.</p> <p>Which child processes to start and monitor is specified by a list of <seealso marker="#spec">child specifications</seealso>. @@ -61,18 +61,59 @@ start_link() -> supervisor:start_link(ch_sup, []). init(_Args) -> - {ok, {{one_for_one, 1, 60}, - [{ch3, {ch3, start_link, []}, - permanent, brutal_kill, worker, [ch3]}]}}.</code> - <p><c>one_for_one</c> is the <seealso marker="#strategy">restart strategy</seealso>.</p> - <p>1 and 60 defines the <seealso marker="#frequency">maximum restart frequency</seealso>.</p> - <p>The tuple <c>{ch3, ...}</c> is a <seealso marker="#spec">child specification</seealso>.</p> + SupFlags = #{strategy => one_for_one, intensity => 1, period => 5}, + ChildSpecs = [#{id => ch3, + start => {ch3, start_link, []}, + restart => permanent, + shutdown => brutal_kill, + type => worker, + modules => [cg3]}], + {ok, {SupFlags, ChildSpecs}}.</code> + <p>The <c>SupFlags</c> variable in the return value + from <c>init/1</c> represents + the <seealso marker="#flags">supervisor flags</seealso>.</p> + <p>The <c>ChildSpecs</c> variable in the return value + from <c>init/1</c> is a list of <seealso marker="#spec">child + specifications</seealso>.</p> + </section> + + <section> + <title>Supervisor Flags</title> + <p>This is the type definition for the supervisor flags:</p> + <code type="none"><![CDATA[ +sup_flags() = #{strategy => strategy(), % optional + intensity => non_neg_integer(), % optional + period => pos_integer()} % optional + strategy() = one_for_all + | one_for_one + | rest_for_one + | simple_one_for_one]]></code> + <list type="bulleted"> + <item> + <p><c>strategy</c> specifies + the <seealso marker="#strategy">restart + strategy</seealso>.</p> + </item> + <item> + <p><c>intensity</c> and <c>period</c> specify + the <seealso marker="#max_intensity">maximum restart + intensity</seealso>.</p> + </item> + </list> </section> <section> <marker id="strategy"></marker> <title>Restart Strategy</title> + <p> The restart strategy is specified by + the <c>strategy</c> key in the supervisor flags map returned by + the callback function <c>init</c>:</p> + <code type="none"> +SupFlags = #{strategy => Strategy, ...}</code> + <p>The <c>strategy</c> key is optional in this map. If it is not + given, it defaults to <c>one_for_one</c>.</p> + <section> <title>one_for_one</title> <p>If a child process terminates, only that process is restarted.</p> @@ -85,7 +126,7 @@ init(_Args) -> <section> <title>one_for_all</title> <p>If a child process terminates, all other child processes are - terminated and then all child processes, including + terminated, and then all child processes, including the terminated one, are restarted.</p> <marker id="sup5"></marker> <image file="../design_principles/sup5.gif"> @@ -100,29 +141,36 @@ init(_Args) -> process in start order -- are terminated. Then the terminated child process and the rest of the child processes are restarted.</p> </section> + + <section> + <title>simple_one_for_one</title> + <p>See <seealso marker="#simple">simple-one-for-one + supervisors</seealso>.</p> + </section> </section> <section> - <marker id="frequency"></marker> - <title>Maximum Restart Frequency</title> + <marker id="max_intensity"></marker> + <title>Maximum Restart Intensity</title> <p>The supervisors have a built-in mechanism to limit the number of restarts which can occur in a given time interval. This is - determined by the values of the two parameters <c>MaxR</c> and - <c>MaxT</c> in the start specification returned by the callback - function <c>init</c>:</p> + specified by the two keys <c>intensity</c> and + <c>period</c> in the supervisor flags map returned by the + callback function <c>init</c>:</p> <code type="none"> -init(...) -> - {ok, {{RestartStrategy, MaxR, MaxT}, - [ChildSpec, ...]}}.</code> +SupFlags = #{intensity => MaxR, period => MaxT, ...}</code> <p>If more than <c>MaxR</c> number of restarts occur in the last - <c>MaxT</c> seconds, then the supervisor terminates all the child + <c>MaxT</c> seconds, the supervisor terminates all the child processes and then itself.</p> - <p>When the supervisor terminates, then the next higher level + <p>When the supervisor terminates, the next higher level supervisor takes some action. It either restarts the terminated - supervisor, or terminates itself.</p> + supervisor or terminates itself.</p> <p>The intention of the restart mechanism is to prevent a situation where a process repeatedly dies for the same reason, only to be restarted again.</p> + <p>The keys <c>intensity</c> and <c>period</c> are optional in the + supervisor flags map. If they are not given, they default + to <c>1</c> and <c>5</c>, respectively.</p> </section> <section> @@ -130,33 +178,42 @@ init(...) -> <title>Child Specification</title> <p>This is the type definition for a child specification:</p> <code type="none"><![CDATA[ -{Id, StartFunc, Restart, Shutdown, Type, Modules} - Id = term() - StartFunc = {M, F, A} - M = F = atom() - A = [term()] - Restart = permanent | transient | temporary - Shutdown = brutal_kill | integer()>0 | infinity - Type = worker | supervisor - Modules = [Module] | dynamic - Module = atom()]]></code> +child_spec() = #{id => child_id(), % mandatory + start => mfargs(), % mandatory + restart => restart(), % optional + shutdown => shutdown(), % optional + type => worker(), % optional + modules => modules()} % optional</pre> + child_id() = term() + mfargs() = {M :: module(), F :: atom(), A :: [term()]} + modules() = [module()] | dynamic + restart() = permanent | transient | temporary + shutdown() = brutal_kill | timeout() + worker() = worker | supervisor]]></code> <list type="bulleted"> <item> - <p><c>Id</c> is a name that is used to identify the child + <p><c>id</c> is used to identify the child specification internally by the supervisor.</p> + <p>The <c>id</c> key is mandatory.</p> + <p>Note that this identifier on occations has been called + "name". As far as possible, the terms "identifier" or "id" + are now used but in order to keep backwards compatibility, + some occurences of "name" can still be found, for example + in error messages.</p> </item> <item> - <p><c>StartFunc</c> defines the function call used to start + <p><c>start</c> defines the function call used to start the child process. It is a module-function-arguments tuple used as <c>apply(M, F, A)</c>.</p> <p>It should be (or result in) a call to <c>supervisor:start_link</c>, <c>gen_server:start_link</c>, - <c>gen_fsm:start_link</c> or <c>gen_event:start_link</c>. + <c>gen_fsm:start_link</c>, or <c>gen_event:start_link</c>. (Or a function compliant with these functions, see <c>supervisor(3)</c> for details.</p> + <p>The <c>start</c> key is mandatory.</p> </item> <item> - <p><c>Restart</c> defines when a terminated child process should + <p><c>restart</c> defines when a terminated child process shall be restarted.</p> <list type="bulleted"> <item>A <c>permanent</c> child process is always restarted.</item> @@ -166,12 +223,14 @@ init(...) -> death causes the temporary process to be terminated).</item> <item>A <c>transient</c> child process is restarted only if it terminates abnormally, i.e. with another exit reason than - <c>normal</c>, <c>shutdown</c> or <c>{shutdown,Term}</c>.</item> + <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c>.</item> </list> + <p>The <c>restart</c> key is optional. If it is not given, the + default value <c>permanent</c> will be used.</p> </item> <item> <marker id="shutdown"></marker> - <p><c>Shutdown</c> defines how a child process should be + <p><c>shutdown</c> defines how a child process shall be terminated.</p> <list type="bulleted"> <item><c>brutal_kill</c> means the child process is @@ -184,58 +243,78 @@ init(...) -> terminated using <c>exit(Child, kill)</c>.</item> <item>If the child process is another supervisor, it should be set to <c>infinity</c> to give the subtree enough time to - shutdown. It is also allowed to set it to <c>infinity</c>, if the - child process is a worker.</item> + shut down. It is also allowed to set it to <c>infinity</c>, + if the child process is a worker.</item> </list> <warning> - <p>Be careful by setting the <c>Shutdown</c> strategy to + <p>Be careful when setting the shutdown time to <c>infinity</c> when the child process is a worker. Because, in this situation, the termination of the supervision tree depends on the child process, it must be implemented in a safe way and its cleanup procedure must always return.</p> </warning> + <p>The <c>shutdown</c> key is optional. If it is not given, + and the child is of type <c>worker</c>, the default value + <c>5000</c> will be used; if the child is of type + <c>supervisor</c>, the default value <c>infinity</c> will be + used.</p> </item> <item> - <p><c>Type</c> specifies if the child process is a supervisor or + <p><c>type</c> specifies if the child process is a supervisor or a worker.</p> + <p>The <c>type</c> key is optional. If it is not given, the + default value <c>worker</c> will be used.</p> </item> <item> - <p><c>Modules</c> should be a list with one element + <p><c>modules</c> should be a list with one element <c>[Module]</c>, where <c>Module</c> is the name of the callback module, if the child process is a supervisor, gen_server or gen_fsm. If the child process is a gen_event, - <c>Modules</c> should be <c>dynamic</c>.</p> + the value shall be <c>dynamic</c>.</p> <p>This information is used by the release handler during upgrades and downgrades, see <seealso marker="release_handling">Release Handling</seealso>.</p> + <p>The <c>modules</c> key is optional. If it is not given, it + defaults to <c>[M]</c>, where <c>M</c> comes from the + child's start <c>{M,F,A}</c>.</p> </item> </list> <p>Example: The child specification to start the server <c>ch3</c> in the example above looks like:</p> <code type="none"> -{ch3, - {ch3, start_link, []}, - permanent, brutal_kill, worker, [ch3]}</code> +#{id => ch3, + start => {ch3, start_link, []}, + restart => permanent, + shutdown => brutal_kill, + type => worker, + modules => [ch3]}</code> + <p>or simplified, relying on the default values:</p> + <code type="none"> +#{id => ch3, + start => {ch3, start_link, []} + shutdown => brutal_kill}</code> <p>Example: A child specification to start the event manager from the chapter about <seealso marker="events#mgr">gen_event</seealso>:</p> <code type="none"> -{error_man, - {gen_event, start_link, [{local, error_man}]}, - permanent, 5000, worker, dynamic}</code> - <p>Both the server and event manager are registered processes which +#{id => error_man, + start => {gen_event, start_link, [{local, error_man}]}, + modules => dynamic}</code> + <p>Both server and event manager are registered processes which can be expected to be accessible at all times, thus they are specified to be <c>permanent</c>.</p> <p><c>ch3</c> does not need to do any cleaning up before termination, thus no shutdown time is needed but <c>brutal_kill</c> should be sufficient. <c>error_man</c> may need some time for the event handlers to clean up, thus - <c>Shutdown</c> is set to 5000 ms.</p> + the shutdown time is set to 5000 ms (which is the default + value).</p> <p>Example: A child specification to start another supervisor:</p> <code type="none"> -{sup, - {sup, start_link, []}, - transient, infinity, supervisor, [sup]}</code> +#{id => sup, + start => {sup, start_link, []}, + restart => transient, + type => supervisor} % will cause default shutdown=>infinity</code> </section> <section> @@ -262,16 +341,18 @@ start_link() -> <c>supervisor:start_link({local, Name}, Module, Args)</c> or <c>supervisor:start_link({global, Name}, Module, Args)</c>.</p> <p>The new supervisor process calls the callback function - <c>ch_sup:init([])</c>. <c>init</c> is expected to return - <c>{ok, StartSpec}</c>:</p> + <c>ch_sup:init([])</c>. <c>init</c> shall return + <c>{ok, {SupFlags, ChildSpecs}}</c>:</p> <code type="none"> init(_Args) -> - {ok, {{one_for_one, 1, 60}, - [{ch3, {ch3, start_link, []}, - permanent, brutal_kill, worker, [ch3]}]}}.</code> + SupFlags = #{}, + ChildSpecs = [#{id => ch3, + start => {ch3, start_link, []}, + shutdown => brutal_kill}], + {ok, {SupFlags, ChildSpecs}}.</code> <p>The supervisor then starts all its child processes according to - the child specifications in the start specification. In this case - there is one child process, <c>ch3</c>.</p> + the given child specifications. In this case there, is one child + process, <c>ch3</c>.</p> <p>Note that <c>supervisor:start_link</c> is synchronous. It does not return until all child processes have been started.</p> </section> @@ -303,17 +384,19 @@ supervisor:terminate_child(Sup, Id)</code> <code type="none"> supervisor:delete_child(Sup, Id)</code> <p><c>Sup</c> is the pid, or name, of the supervisor. - <c>Id</c> is the id specified in the <seealso marker="#spec">child specification</seealso>.</p> + <c>Id</c> is the value associated with the <c>id</c> key in + the <seealso marker="#spec">child specification</seealso>.</p> <p>As with dynamically added child processes, the effects of deleting a static child process is lost if the supervisor itself restarts.</p> </section> + <marker id="simple"/> <section> <title>Simple-One-For-One Supervisors</title> <p>A supervisor with restart strategy <c>simple_one_for_one</c> is a simplified one_for_one supervisor, where all child processes are - dynamically added instances of the same process.</p> + dynamically added instances of the same child specification.</p> <p>Example of a callback module for a simple_one_for_one supervisor:</p> <code type="none"> -module(simple_sup). @@ -326,9 +409,13 @@ start_link() -> supervisor:start_link(simple_sup, []). init(_Args) -> - {ok, {{simple_one_for_one, 0, 1}, - [{call, {call, start_link, []}, - temporary, brutal_kill, worker, [call]}]}}.</code> + SupFlags = #{strategy => simple_one_for_one, + intensity => 0, + period => 1}, + ChildSpecs = [#{id => call, + start => {call, start_link, []}, + shutdown => brutal_kill}], + {ok, {SupFlags, ChildSpecs}}.</code> <p>When started, the supervisor will not start any child processes. Instead, all child processes are added dynamically by calling:</p> <code type="none"> @@ -336,7 +423,7 @@ supervisor:start_child(Sup, List)</code> <p><c>Sup</c> is the pid, or name, of the supervisor. <c>List</c> is an arbitrary list of terms which will be added to the list of arguments specified in the child specification. If - the start function is specified as <c>{M, F, A}</c>, then + the start function is specified as <c>{M, F, A}</c>, the child process is started by calling <c>apply(M, F, A++List)</c>.</p> <p>For example, adding a child to <c>simple_sup</c> above:</p> @@ -352,10 +439,10 @@ call:start_link(id1)</code> supervisor:terminate_child(Sup, Pid)</code> <p>where <c>Sup</c> is the pid, or name, of the supervisor and <c>Pid</c> is the pid of the child.</p> - <p>Because a <c>simple_one_for_one</c> supervisor could have many children, - it shuts them all down at same time. So, order in which they are stopped is - not defined. For the same reason, it could have an overhead with regards to - the <c>Shutdown</c> strategy.</p> + <p>Because a <c>simple_one_for_one</c> supervisor could have many + children, it shuts them all down asynchronously. This means that + the children will do their cleanup in parallel and therefore the + order in which they are stopped is not defined.</p> </section> <section> diff --git a/system/doc/efficiency_guide/advanced.xml b/system/doc/efficiency_guide/advanced.xml index b5771a5929..51f1b2612c 100644 --- a/system/doc/efficiency_guide/advanced.xml +++ b/system/doc/efficiency_guide/advanced.xml @@ -183,7 +183,7 @@ On 64-bit architectures: 4 words for a reference from the current local node, an <tag><em>Open ports</em></tag> <item> <marker id="ports"></marker> - <p>The maximum number of simultaneously oper Erlang ports is + <p>The maximum number of simultaneously open Erlang ports is often by default 16384. This limit can be configured at startup, for more information see the <seealso marker="erts:erl#max_ports"><c>+Q</c></seealso> diff --git a/system/doc/efficiency_guide/binaryhandling.xml b/system/doc/efficiency_guide/binaryhandling.xml index 6b0df49011..4ba1378059 100644 --- a/system/doc/efficiency_guide/binaryhandling.xml +++ b/system/doc/efficiency_guide/binaryhandling.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -237,8 +237,9 @@ Bin = <<Bin1,...>> %% Bin1 will be COPIED <p><c>Bin1</c> will be copied in the third line.</p> <p>The same thing happens if you insert a binary into an <em>ets</em> - table or send it to a port using <c>erlang:port_command/2</c>.</p> - + table or send it to a port using <c>erlang:port_command/2</c> or pass it to + <seealso marker="erts:erl_nif#enif_inspect_binary">enif_inspect_binary</seealso> + in a NIF.</p> <p>Matching a binary will also cause it to shrink and the next append operation will copy the binary data:</p> diff --git a/system/doc/efficiency_guide/processes.xml b/system/doc/efficiency_guide/processes.xml index 6f85b029eb..86951e2dcc 100644 --- a/system/doc/efficiency_guide/processes.xml +++ b/system/doc/efficiency_guide/processes.xml @@ -186,7 +186,7 @@ kilo_byte(0, Acc) -> kilo_byte(N, Acc) -> kilo_byte(N-1, [Acc|Acc]).</code> - <p><c>kilo_byte/1</c> creates a deep list. If we call + <p><c>kilo_byte/0</c> creates a deep list. If we call <c>list_to_binary/1</c>, we can convert the deep list to a binary of 1024 bytes:</p> diff --git a/system/doc/efficiency_guide/tablesDatabases.xml b/system/doc/efficiency_guide/tablesDatabases.xml index 5b0df76371..94c921fa1c 100644 --- a/system/doc/efficiency_guide/tablesDatabases.xml +++ b/system/doc/efficiency_guide/tablesDatabases.xml @@ -136,7 +136,7 @@ print_person(PersonId) -> io:format("No person with ID = ~p~n", [PersonID]) end. -%%% Internal functionss +%%% Internal functions print_name(PersonID) -> [Person] = ets:lookup(person, PersonId), io:format("No person ~p~n", [Person#person.name]). diff --git a/system/doc/getting_started/conc_prog.xml b/system/doc/getting_started/conc_prog.xml index e392287ff0..2b64826a93 100644 --- a/system/doc/getting_started/conc_prog.xml +++ b/system/doc/getting_started/conc_prog.xml @@ -95,7 +95,7 @@ goodbye</pre> the second a "goodbye", the first another "hello" and so forth. But where did the <0.63.0> come from? The return value of a function is of course the return value of the last "thing" in - the function. The last thing in the function <c>start</c> is</p> + the function. The last thing in the function <c>start</c> is:</p> <code type="none"> spawn(tut14, say_something, [goodbye, 3]).</code> <p><c>spawn</c> returns a <em>process identifier</em>, or @@ -166,11 +166,11 @@ Pong_PID = spawn(tut15, pong, [])</code> <c>start</c> now creates another process "ping".</p> <code type="none"> spawn(tut15, ping, [3, Pong_PID]),</code> - <p>this process executes</p> + <p>This process executes:</p> <code type="none"> tut15:ping(3, Pong_PID)</code> <p><0.36.0> is the return value from the <c>start</c> function.</p> - <p>The process "pong" now does:</p> + <p>The process "pong" now does:</p> <code type="none"> receive finished -> @@ -235,7 +235,7 @@ Ping_PID ! pong</code> Pid ! Message</code> <p>I.e. <c>Message</c> (any Erlang term) is sent to the process with identity <c>Pid</c>.</p> - <p>After sending the message <c>pong</c>, to the process "ping", + <p>After sending the message <c>pong</c> to the process "ping", "pong" calls the <c>pong</c> function again, which causes it to get back to the <c>receive</c> again and wait for another message. Now let's look at the process "ping". Recall that it was started @@ -253,7 +253,7 @@ Pong_PID ! {ping, self()},</code> <p><c>self()</c> returns the pid of the process which executes <c>self()</c>, in this case the pid of "ping". (Recall the code for "pong", this will land up in the variable <c>Ping_PID</c> in - the <c>receive</c> previously explained).</p> + the <c>receive</c> previously explained.)</p> <p>"Ping" now waits for a reply from "pong":</p> <code type="none"> receive @@ -352,8 +352,8 @@ pong ! {ping, self()},</code> on different computers. Before we do this, there are a few things we need to set up to get this to work. The distributed Erlang implementation provides a basic security mechanism to prevent - unauthorized access to an Erlang system on another computer - (*manual*). Erlang systems which talk to each other must have + unauthorized access to an Erlang system on another computer. + Erlang systems which talk to each other must have the same <em>magic cookie</em>. The easiest way to achieve this is by having a file called <c>.erlang.cookie</c> in your home directory on all machines which on which you are going to run @@ -363,8 +363,8 @@ pong ! {ping, self()},</code> you can safely ignore this and simply create a file called <c>.erlang.cookie</c> in the directory you get to after executing the command <c>cd</c> without any argument). - The <c>.erlang.cookie</c> file should contain on line with - the same atom. For example on Linux or Unix in the OS shell:</p> + The <c>.erlang.cookie</c> file should contain one line with + the same atom. For example, on Linux or Unix in the OS shell:</p> <pre> $ <input>cd</input> $ <input>cat > .erlang.cookie</input> @@ -373,10 +373,10 @@ $ <input>chmod 400 .erlang.cookie</input></pre> <p>The <c>chmod</c> above make the <c>.erlang.cookie</c> file accessible only by the owner of the file. This is a requirement.</p> <p>When you start an Erlang system which is going to talk to other - Erlang systems, you must give it a name, eg: </p> + Erlang systems, you must give it a name, e.g.: </p> <pre> $ <input>erl -sname my_name</input></pre> - <p>We will see more details of this later (*manual*). If you want to + <p>We will see more details of this later. If you want to experiment with distributed Erlang, but you only have one computer to work on, you can start two separate Erlang systems on the same computer but give them different names. Each Erlang @@ -385,7 +385,7 @@ $ <input>erl -sname my_name</input></pre> IP domain and we can use only the first component of the IP address, if we want to use nodes in different domains we use <c>-name</c> instead, but then all IP address must be given in - full (*manual*).</p> + full.)</p> <p>Here is the ping pong example modified to run on two separate nodes:</p> <code type="none"> @@ -538,9 +538,9 @@ ping finished</pre> <p>Before we start, let's note the following:</p> <list type="bulleted"> <item> - <p>This example will just show the message passing logic no + <p>This example will just show the message passing logic - no attempt at all has been made to provide a nice graphical user - interface - this can of course also be done in Erlang - but + interface. This can, of course, also be done in Erlang - but that's another tutorial.</p> </item> <item> @@ -550,8 +550,8 @@ ping finished</pre> tutorial.</p> </item> <item> - <p>The first program we write will contain some inadequacies as - regards handling of nodes which disappear, we will correct + <p>The first program we write will contain some inadequacies + regarding the handling of nodes which disappear. We will correct these in a later version of the program.</p> </item> </list> @@ -571,7 +571,7 @@ ping finished</pre> %%% already logged in at the same node, login will be rejected %%% with a suitable error message. %%% logoff() -%%% Logs off anybody at at node +%%% Logs off anybody at that node %%% message(ToName, Message) %%% sends Message to ToName. Error messages if the user of this %%% function is not logged on or if ToName is not logged on at @@ -734,11 +734,11 @@ await_result() -> <item>copy the compiled code (<c>messenger.beam</c>) to the directory on each computer where you start Erlang.</item> </list> - <p>In the following example of use of this program, I have started + <p>In the following example of use of this program I have started nodes on four different computers, but if you don't have that - many machines available on your network, you could start up + many machines available on your network you could start up several nodes on the same machine.</p> - <p>We start up four Erlang nodes, messenger@super, c1@bilbo, + <p>We start up four Erlang nodes: messenger@super, c1@bilbo, c2@kosken, c3@gollum.</p> <p>First we start up a the server at messenger@super:</p> <pre> @@ -780,19 +780,19 @@ ok receiver_not_found</pre> <p>But this fails as Fred has already logged off.</p> <p>First let's look at some of the new concepts we have introduced.</p> - <p>There are two versions of the <c>server_transfer</c> function, + <p>There are two versions of the <c>server_transfer</c> function: one with four arguments (<c>server_transfer/4</c>) and one with five (<c>server_transfer/5</c>). These are regarded by Erlang as two separate functions.</p> <p>Note how we write the <c>server</c> function so that it calls - itself, <c>server(User_List)</c> and thus creates a loop. + itself, via <c>server(User_List)</c>, and thus creates a loop. The Erlang compiler is "clever" and optimizes the code so that this really is a sort of loop and not a proper function call. But this only works if there is no code after the call, otherwise the compiler will expect the call to return and make a proper function call. This would result in the process getting bigger and bigger for every loop.</p> - <p>We use functions in the <c>lists</c> module. This is a very + <p>We use functions from the <c>lists</c> module. This is a very useful module and a study of the manual page is recommended (<c>erl -man lists</c>). <c>lists:keymember(Key,Position,Lists)</c> looks through a list diff --git a/system/doc/getting_started/records_macros.xml b/system/doc/getting_started/records_macros.xml index 76e3d185fb..73c8ce5c8d 100644 --- a/system/doc/getting_started/records_macros.xml +++ b/system/doc/getting_started/records_macros.xml @@ -97,7 +97,7 @@ %%% with a suitable error message. %%% logoff() -%%% Logs off anybody at at node +%%% Logs off anybody at that node %%% message(ToName, Message) %%% sends Message to ToName. Error messages if the user of this @@ -284,7 +284,7 @@ server_transfer(From, Name, To, Message, User_List) -> the record is referred to. If you leave out a field when creating a record, it will get the value of the atom undefined. (*manual*)</p> <p>Pattern matching with records is very similar to creating - records. For example inside a <c>case</c> or <c>receive</c>:</p> + records. For example, inside a <c>case</c> or <c>receive</c>:</p> <code type="none"> #message_to{to_name=ToName, message=Message} -></code> <p>is the same as:</p> diff --git a/system/doc/getting_started/robustness.xml b/system/doc/getting_started/robustness.xml index 359ea93275..e8fb81d5e8 100644 --- a/system/doc/getting_started/robustness.xml +++ b/system/doc/getting_started/robustness.xml @@ -30,7 +30,7 @@ </header> <p>There are several things which are wrong with the <seealso marker="conc_prog#ex">messenger example</seealso> from - the previous chapter. For example if a node where a user is logged + the previous chapter. For example, if a node where a user is logged on goes down without doing a log off, the user will remain in the server's <c>User_List</c> but the client will disappear thus making it impossible for the user to log on again as the server @@ -214,9 +214,9 @@ Ping received pong</pre> signal to be sent to "pong" which will also terminate.</p> <p>It is possible to modify the default behaviour of a process so that it does not get killed when it receives abnormal exit - signals, but all signals will be turned into normal messages on + signals, but all signals will be turned into normal messages with the format <c>{'EXIT',FromPID,Reason}</c> and added to the end of - the receiving processes message queue. This behaviour is set by:</p> + the receiving process' message queue. This behaviour is set by:</p> <code type="none"> process_flag(trap_exit, true)</code> <p>There are several other process flags, see @@ -289,7 +289,7 @@ pong exiting, got {'EXIT',<3820.39.0>,ping}</pre> %%% already logged in at the same node, login will be rejected %%% with a suitable error message. %%% logoff() -%%% Logs off anybody at at node +%%% Logs off anybody at that node %%% message(ToName, Message) %%% sends Message to ToName. Error messages if the user of this %%% function is not logged on or if ToName is not logged on at diff --git a/system/doc/getting_started/seq_prog.xml b/system/doc/getting_started/seq_prog.xml index fd49102263..699b9487ed 100644 --- a/system/doc/getting_started/seq_prog.xml +++ b/system/doc/getting_started/seq_prog.xml @@ -31,14 +31,14 @@ <section> <title>The Erlang Shell</title> - <p>Most operating systems have a command interpreter or shell, Unix - and Linux have many, Windows has the Command Prompt. Erlang has + <p>Most operating systems have a command interpreter or shell- Unix + and Linux have many, while Windows has the Command Prompt. Erlang has its own shell where you can directly write bits of Erlang code and evaluate (run) them to see what happens (see <seealso marker="stdlib:shell">shell(3)</seealso>). Start the Erlang shell (in Linux or UNIX) by starting a shell or command interpreter in your operating system and typing - <c>erl</c>, you will see something like this.</p> + <c>erl</c>. You will see something like this.</p> <pre> % <input>erl</input> Erlang R15B (erts-5.9.1) [source] [smp:8:8] [rq:8] [async-threads:0] [hipe] [kernel-poll:false] @@ -62,7 +62,7 @@ Eshell V5.9.1 (abort with ^G) (See the chapter <seealso marker="erts:tty">"tty - A command line interface"</seealso> in ERTS User's Guide).</p> <p>(Note: you will find a lot of line numbers given by the shell out of sequence in this tutorial as it was written and the code - tested in several sessions).</p> + tested in several sessions.)</p> <p>Now let's try a more complex calculation.</p> <pre> 2> <input>(42 + 77) * 66 / 3.</input> @@ -115,7 +115,7 @@ double(X) -> entered and there will also be error messages to give you some idea as to what has gone wrong so you can change what you have written and try again.</p> - <p>Now lets run the program.</p> + <p>Now let's run the program.</p> <pre> 4> <input>tut:double(10).</input> 20</pre> @@ -208,7 +208,7 @@ mult(X, Y) -> called variables. Variables must start with a capital letter (see the chapter <seealso marker="doc/reference_manual:expressions">"Variables"</seealso> - in the Erlang Reference Manual). Examples of variable could be + in the Erlang Reference Manual). Examples of variables could be <c>Number</c>, <c>ShoeSize</c>, <c>Age</c> etc.</p> </section> @@ -271,7 +271,7 @@ convert(N, centimeter) -> Consider:</p> <code type="none"> tut2:convert(3, inch).</code> - <p>Does this mean that 3 is in inches? or that 3 is in centimeters + <p>Does this mean that 3 is in inches? Or that 3 is in centimeters and we want to convert it to inches? So Erlang has a way to group things together to make things more understandable. We call these <em>tuples</em>. Tuples are surrounded by "{" and "}".</p> @@ -309,7 +309,7 @@ convert_length({inch, Y}) -> <p>We have shown tuples with two parts above, but tuples can have as many parts as we want and contain any valid Erlang <em>term</em>. For example, to represent the temperature of - various cities of the world we could write</p> + various cities of the world we could write:</p> <code type="none"> {moscow, {c, -10}} {cape_town, {f, 70}} @@ -325,7 +325,7 @@ convert_length({inch, Y}) -> <title>Lists</title> <p>Whereas tuples group things together, we also want to be able to represent lists of things. Lists in Erlang are surrounded by "[" - and "]". For example a list of the temperatures of various cities + and "]". For example, a list of the temperatures of various cities in the world could be:</p> <code type="none"> [{moscow, {c, -10}}, {cape_town, {f, 70}}, {stockholm, {c, -4}}, @@ -345,7 +345,7 @@ convert_length({inch, Y}) -> [2,3,4,5]</pre> <p>We use | to separate the first elements of the list from the rest of the list. (<c>First</c> has got value 1 and - <c>TheRest</c> value [2,3,4,5]).</p> + <c>TheRest</c> value [2,3,4,5].)</p> <p>Another example:</p> <pre> 20> <input>[E1, E2 | R] = [1,2,3,4,5,6,7].</input> @@ -403,7 +403,7 @@ list_length([First | Rest]) -> the remaining elements <c>Rest</c> is 1 + the length of <c>Rest</c>.</p> <p>(Advanced readers only: This is not tail recursive, there is a - better way to write this function).</p> + better way to write this function.)</p> <p>In general we can say we use tuples where we would use "records" or "structs" in other languages and we use lists when we want to represent things which have varying sizes, (i.e. where we would @@ -481,7 +481,7 @@ blue(#{blue := SV, alpha := SA}, #{blue := DV, alpha := DA}) -> > <input>color:blend(C2,C1).</input> #{alpha => 1.0,blue => 0.38,green => 0.52,red => 0.51} </pre> - <p>This example warrant some explanation:</p> + <p>This example warrants some explanation:</p> <code type="none"> -define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).</code> <p> @@ -573,10 +573,9 @@ http://www.erlang.org/doc/r9b/doc/index.html</code> <section> <title>Writing Output to a Terminal</title> <p>It's nice to be able to do formatted output in these example, so - the next example shows a simple way to use to use - the <c>io:format</c> function. Of course, just like all other - exported functions, you can test the <c>io:format</c> function in - the shell:</p> + the next example shows a simple way to use the <c>io:format</c> + function. Of course, just like all other exported functions, you + can test the <c>io:format</c> function in the shell:</p> <pre> 31> <input>io:format("hello world~n", []).</input> hello world @@ -673,7 +672,7 @@ ok</pre> <p>Now we call <c>format_temps(Rest)</c> with the rest of the list as an argument. This way of doing things is similar to the loop constructs in other languages. (Yes, this is recursion, but don't - let that worry you). So the same <c>format_temps</c> function is + let that worry you.) So the same <c>format_temps</c> function is called again, this time <c>City</c> gets the value <c>{cape_town,{f,70}}</c> and we repeat the same procedure as before. We go on doing this until the list becomes empty, i.e. [], @@ -737,12 +736,12 @@ list_max([Head|Rest], Result_so_far) -> the next part of the function.</p> <p>Some useful operators in guards are, < less than, > greater than, == equal, >= greater or equal, =< less or - equal, /= not equal. (see the chapter - <seealso marker="doc/reference_manual:expressions">"Guard Sequences"</seealso> in the Erlang Reference Manual).</p> + equal, /= not equal. (See the chapter + <seealso marker="doc/reference_manual:expressions">"Guard Sequences"</seealso> in the Erlang Reference Manual.)</p> <p>To change the above program to one which works out the minimum value of the element in a list, all we would need to do is to write < instead of >. (But it would be wise to change - the name of the function to <c>list_min</c> :-).</p> + the name of the function to <c>list_min</c> :-).)</p> <p>Remember that I mentioned earlier that a variable could only be given a value once in its scope? In the above we see, for example, that <c>Result_so_far</c> has been given several values. This is @@ -846,7 +845,7 @@ reverse([], [3,2,1]) => write a list manipulating function it is a good idea to check that one isn't already written for you. (see <seealso marker="stdlib:lists">lists(3)</seealso>).</p> - <p>Now lets get back to the cities and temperatures, but take a more + <p>Now let's get back to the cities and temperatures, but take a more structured approach this time. First let's convert the whole list to Celsius as follows and test the function:</p> <code type="none"> @@ -890,7 +889,7 @@ format_temps(List_of_cities) -> <code type="none"> [City | convert_list_to_c(Rest)];</code> <p>We go on doing this until we get to the end of the list (i.e. - the list is empty:</p> + the list is empty):</p> <code type="none"> convert_list_to_c([]) -> [].</code> @@ -1152,13 +1151,13 @@ month_length(Year, Month) -> <section> <title>Built In Functions (BIFs)</title> - <p>Built in functions BIFs are functions which for some reason is + <p>Built in functions (BIFs) are functions which for some reason are built in to the Erlang virtual machine. BIFs often implement functionality that is impossible to implement in Erlang or is too inefficient to implement in Erlang. Some BIFs can be called - by use of the function name only but they are by default belonging - to the erlang module so for example the call to the BIF <c>trunc</c> - below is equivalent with a call to <c>erlang:trunc</c>.</p> + by use of the function name only, but they by default belong + to the erlang module. So for example, the call to the BIF <c>trunc</c> + below is equivalent to a call to <c>erlang:trunc</c>.</p> <p>As you can see, we first find out if a year is leap or not. If a year is divisible by 400, it is a leap year. To find this out we first divide the year by 400 and use the built in function @@ -1175,23 +1174,23 @@ trunc(5.01) = 5 2000 / 400 = 5.0 trunc(5.0) = 5 5 * 400 = 2000</code> - <p>so we have a leap year. The next two tests if the year is - divisible by 100 or 4 are done in the same way. The first - <c>if</c> returns <c>leap</c> or <c>not_leap</c> which lands up + <p>so we have a leap year. The next two tests, which check if the year is + divisible by 100 or 4, are done in the same way. The first + <c>if</c> returns <c>leap</c> or <c>not_leap</c> which ends up in the variable <c>Leap</c>. We use this variable in the guard for <c>feb</c> in the following <c>case</c> which tells us how long the month is.</p> - <p>This example showed the use of <c>trunc</c>, an easier way would - be to use the Erlang operator <c>rem</c> which gives the remainder + <p>This example showed the use of <c>trunc</c>. An easier way would + be to use the Erlang operator <c>rem</c>, which gives the remainder after division. For example:</p> <pre> 74> <input>2004 rem 400.</input> 4</pre> - <p>so instead of writing</p> + <p>so instead of writing:</p> <code type="none"> trunc(Year / 400) * 400 == Year -> leap;</code> - <p>we could write</p> + <p>we could write:</p> <code type="none"> Year rem 400 == 0 -> leap;</code> @@ -1201,7 +1200,7 @@ Year rem 400 == 0 -> (see the chapter <seealso marker="doc/reference_manual:expressions">"Guard Sequences"</seealso> in the Erlang Reference Manual) (Aside for advanced readers: This is to ensure that guards don't have side - effects). Let's play with a few of these functions in the shell:</p> + effects.) Let's play with a few of these functions in the shell:</p> <pre> 75> <input>trunc(5.6).</input> 5 @@ -1268,7 +1267,7 @@ map(Fun, []) -> #Fun<erl_eval.5.123085357> 89> <input>lists:map(Add_3, [1,2,3]).</input> [4,5,6]</pre> - <p>Now lets print out the temperatures in a list of cities (yet + <p>Now let's print out the temperatures in a list of cities (yet again):</p> <pre> 90> <input>Print_City = fun({City, {X, Temp}}) -> io:format("~-15w ~w ~w~n",</input> diff --git a/system/doc/reference_manual/character_set.xml b/system/doc/reference_manual/character_set.xml index 884898eb34..b09b484582 100644 --- a/system/doc/reference_manual/character_set.xml +++ b/system/doc/reference_manual/character_set.xml @@ -101,9 +101,10 @@ <tcaption>Character Classes.</tcaption> </table> <p>In Erlang/OTP R16B the syntax of Erlang tokens was extended to - handle Unicode. To begin with the support is limited to - strings, but Erlang/OTP 18 is expected to handle Unicode atoms - as well. More about the usage of Unicode in Erlang source files + handle Unicode. The support is limited to + string literals and comments. Atoms, module names, and + function names are restricted to the ISO-Latin-1 range. + More about the usage of Unicode in Erlang source files can be found in <seealso marker="stdlib:unicode_usage#unicode_in_erlang">STDLIB's User's Guide</seealso>.</p> diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml index 0031664dfb..37c0db5ff7 100644 --- a/system/doc/reference_manual/data_types.xml +++ b/system/doc/reference_manual/data_types.xml @@ -215,7 +215,7 @@ adam 0</pre> <p>A collection of maps processing functions can be found in the STDLIB module <seealso marker="stdlib:maps"><c>maps</c></seealso>.</p> - <p>Read more about <seealso marker="maps">Maps</seealso>.</p> + <p>Read more about <seealso marker="expressions#map_expressions">Maps</seealso>.</p> <note> <p>Maps are considered experimental during OTP 17.</p> </note> diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml index 37208710fe..62a344ad58 100644 --- a/system/doc/reference_manual/expressions.xml +++ b/system/doc/reference_manual/expressions.xml @@ -283,7 +283,7 @@ fun lists:append/2([1,2], [3,4]) length([]) -> 0; length([H|T]) -> - 1 + length(T). %% Calls the local funtion length/1 + 1 + length(T). %% Calls the local function length/1 f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1, %% which is allowed in guards @@ -301,7 +301,7 @@ f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1, -import(mod,[length/1]). -f(X) when erlang:length(X) > 33 -> %% Calls erlang:lenght/1, +f(X) when erlang:length(X) > 33 -> %% Calls erlang:length/1, %% which is allowed in guards erlang:length(X); %% Explicit call to erlang:length in body @@ -792,6 +792,245 @@ Expr1 -- Expr2</pre> </section> <section> + <marker id="map_expressions"></marker> + <title>Map Expressions</title> + <section> + <title>Creating Maps</title> + <p> + Constructing a new map is done by letting an expression <c>K</c> be associated with + another expression <c>V</c>: + </p> + <code>#{ K => V }</code> + <p> + New maps may include multiple associations at construction by listing every + association: + </p> + <code>#{ K1 => V1, .., Kn => Vn }</code> + <p> + An empty map is constructed by not associating any terms with each other: + </p> + <code>#{}</code> + <p> + All keys and values in the map are terms. Any expression is first evaluated and + then the resulting terms are used as <em>key</em> and <em>value</em> respectively. + </p> + <p> + Keys and values are separated by the <c>=></c> arrow and associations are + separated by <c>,</c>. + </p> + + <p> + Examples: + </p> + <code> +M0 = #{}, % empty map +M1 = #{a => <<"hello">>}, % single association with literals +M2 = #{1 => 2, b => b}, % multiple associations with literals +M3 = #{k => {A,B}}, % single association with variables +M4 = #{{"w", 1} => f()}. % compound key associated with an evaluated expression</code> + <p> + where, <c>A</c> and <c>B</c> are any expressions and <c>M0</c> through <c>M4</c> + are the resulting map terms. + </p> + <p> + If two matching keys are declared, the latter key will take precedence. + </p> + <p> + Example: + </p> + +<pre> +1> <input>#{1 => a, 1 => b}.</input> +#{1 => b } +2> <input>#{1.0 => a, 1 => b}.</input> +#{1 => b, 1.0 => a} +</pre> + <p> + The order in which the expressions constructing the keys and their + associated values are evaluated is not defined. The syntactic order of + the key-value pairs in the construction is of no relevance, except in + the above mentioned case of two matching keys. + </p> + </section> + + <section> + <title>Updating Maps</title> + <p> + Updating a map has similar syntax as constructing it. + </p> + <p> + An expression defining the map to be updated is put in front of the expression + defining the keys to be updated and their respective values. + </p> + <code>M#{ K => V }</code> + <p> + where <c>M</c> is a term of type map and <c>K</c> and <c>V</c> are any expression. + </p> + <p> + If key <c>K</c> does not match any existing key in the map, a new association + will be created from key <c>K</c> to value <c>V</c>. If key <c>K</c> matches + an existing key in map <c>M</c> its associated value will be replaced by the + new value <c>V</c>. In both cases the evaluated map expression will return a new map. + </p> + <p> + If <c>M</c> is not of type map an exception of type <c>badmap</c> is thrown. + </p> + <p> + To only update an existing value, the following syntax is used, + </p> + <code>M#{ K := V } </code> + <p> + where <c>M</c> is an term of type map, <c>V</c> is an expression and <c>K</c> + is an expression which evaluates to an existing key in <c>M</c>. + </p> + <p> + If key <c>K</c> does not match any existing keys in map <c>M</c> an exception + of type <c>badarg</c> will be triggered at runtime. If a matching key <c>K</c> + is present in map <c>M</c> its associated value will be replaced by the new + value <c>V</c> and the evaluated map expression returns a new map. + </p> + <p> + If <c>M</c> is not of type map an exception of type <c>badmap</c> is thrown. + </p> + <p> + Examples: + </p> + <code> +M0 = #{}, +M1 = M0#{a => 0}, +M2 = M1#{a => 1, b => 2}, +M3 = M2#{"function" => fun() -> f() end}, +M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code> + <p> + where <c>M0</c> is any map. It follows that <c>M1 .. M4</c> are maps as well. + </p> + <p> + More Examples: + </p> +<pre> +1> <input>M = #{1 => a}.</input> +#{1 => a } +2> <input>M#{1.0 => b}.</input> +#{1 => a, 1.0 => b}. +3> <input>M#{1 := b}.</input> +#{1 => b} +4> <input>M#{1.0 := b}.</input> +** exception error: bad argument +</pre> + <p> + As in construction, the order in which the key and value expressions + are evaluated is not defined. The + syntactic order of the key-value pairs in the update is of no + relevance, except in the case where two keys match, in which + case the latter value is used. + </p> + </section> + + <section> + <title>Maps in Patterns</title> + <p> + Matching of key-value associations from maps is done in the following way: + </p> + + <code>#{ K := V } = M</code> + <p> + where <c>M</c> is any map. The key <c>K</c> has to be an expression with bound + variables or a literals, and <c>V</c> can be any pattern with either bound or + unbound variables. + </p> + <p> + If the variable <c>V</c> is unbound, it will be bound to the value associated + with the key <c>K</c>, which has to exist in the map <c>M</c>. If the variable + <c>V</c> is bound, it has to match the value associated with <c>K</c> in <c>M</c>. + </p> + <p> Example: </p> +<code> +1> <input>M = #{"tuple" => {1,2}}.</input> +#{"tuple" => {1,2}} +2> <input>#{"tuple" := {1,B}} = M.</input> +#{"tuple" => {1,2}} +3> <input>B.</input> +2.</code> + <p> + This will bind variable <c>B</c> to integer <c>2</c>. + </p> + <p> + Similarly, multiple values from the map may be matched: + </p> + <code>#{ K1 := V1, .., Kn := Vn } = M</code> + <p> + where keys <c>K1 .. Kn</c> are any expressions with literals or bound variables. If all + keys exist in map <c>M</c> all variables in <c>V1 .. Vn</c> will be matched to the + associated values of their respective keys. + </p> + <p> + If the matching conditions are not met, the match will fail, either with + </p> + <list> + <item> + a <c>badmatch</c> exception, if used in the context of the matching operator + as in the example, + </item> + <item> + or resulting in the next clause being tested in function heads and + case expressions. + </item> + </list> + <p> + Matching in maps only allows for <c>:=</c> as delimiters of associations. + The order in which keys are declared in matching has no relevance. + </p> + <p> + Duplicate keys are allowed in matching and will match each pattern associated + to the keys. + </p> + <code>#{ K := V1, K := V2 } = M</code> + <p> + Matching an expression against an empty map literal will match its type but + no variables will be bound: + </p> + <code>#{} = Expr</code> + <p> + This expression will match if the expression <c>Expr</c> is of type map, otherwise + it will fail with an exception <c>badmatch</c>. + </p> + <section> + <title>Matching syntax: Example with literals in function heads</title> + <p> + Matching of literals as keys are allowed in function heads. + </p> + <code> +%% only start if not_started +handle_call(start, From, #{ state := not_started } = S) -> +... + {reply, ok, S#{ state := start }}; + +%% only change if started +handle_call(change, From, #{ state := start } = S) -> +... + {reply, ok, S#{ state := changed }};</code> + </section> + </section> + <section> + <title>Maps in Guards</title> + <p> + Maps are allowed in guards as long as all sub-expressions are valid guard expressions. + </p> + <p> + Two guard BIFs handles maps: + </p> + <list> + <item> + <seealso marker="erts:erlang#is_map/1">is_map/1</seealso> + </item> + <item> + <seealso marker="erts:erlang#map_size/1">map_size/1</seealso> + </item> + </list> + </section> + </section> + + <section> <marker id="bit_syntax"></marker> <title>Bit Syntax Expressions</title> <code type="none"><![CDATA[<<>> diff --git a/system/doc/reference_manual/maps.xml b/system/doc/reference_manual/maps.xml deleted file mode 100644 index 78808ce4a2..0000000000 --- a/system/doc/reference_manual/maps.xml +++ /dev/null @@ -1,274 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>2014</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - </legalnotice> - - <title>Maps</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - <file>maps.xml</file> - </header> - - <note> - <p>Maps are considered experimental during OTP 17 and may be subject to change.</p> - <p>The documentation below describes it being possible to use arbitrary - expressions or variables as keys, this is <em>NOT</em> implemented in the current - version of Erlang/OTP.</p> - <p>Exceptions returns <c>badarg</c> instead of <c>badmap</c>, this will change in - the future releases.</p> - </note> - - <section> - <title>Creating Maps</title> - <p> - Constructing a new map is done by letting an expression <c>K</c> be associated with - another expression <c>V</c>: - </p> - <code>#{ K => V }</code> - <p> - New maps may include multiple associations at construction by listing every - association: - </p> - <code>#{ K1 => V1, .., Kn => Vn }</code> - <p> - An empty map is constructed by not associating any terms with each other: - </p> - <code>#{}</code> - <p> - All keys and values in the map are terms. Any expression is first evaluated and - then the resulting terms are used as <em>key</em> and <em>value</em> respectively. - </p> - <p> - Keys and values are separated by the <c>=></c> arrow and associations are - separated by <c>,</c>. - </p> - - <p> - Examples: - </p> - <code> -M0 = #{}, % empty map -M1 = #{a => <<"hello">>}, % single association with literals -M2 = #{1 => 2, b => b}, % multiple associations with literals -M3 = #{k => {A,B}}, % single association with variables -M4 = #{{"w", 1} => f()}. % compound key associated with an evaluated expression</code> - <p> - where, <c>A</c> and <c>B</c> are any expressions and <c>M0</c> through <c>M4</c> - are the resulting map terms. - </p> - <p> - If two matching keys are declared, the latter key will take precedence. - </p> - <p> - Example: - </p> - -<pre> -1> <input>#{1 => a, 1 => b}.</input> -#{1 => b } -2> <input>#{1.0 => a, 1 => b}.</input> -#{1 => b, 1.0 => a} -</pre> - <p> - The order in which the expressions constructing the keys and their - associated values are evaluated is not defined. The syntactic order of - the key-value pairs in the construction is of no relevance, except in - the above mentioned case of two matching keys. - </p> - </section> - - <section> - <title>Updating Maps</title> - <p> - Updating a map has similar syntax as constructing it. - </p> - <p> - An expression defining the map to be updated is put in front of the expression - defining the keys to be updated and their respective values. - </p> - <code>M#{ K => V }</code> - <p> - where <c>M</c> is a term of type map and <c>K</c> and <c>V</c> are any expression. - </p> - <p> - If key <c>K</c> does not match any existing key in the map, a new association - will be created from key <c>K</c> to value <c>V</c>. If key <c>K</c> matches - an existing key in map <c>M</c> its associated value will be replaced by the - new value <c>V</c>. In both cases the evaluated map expression will return a new map. - </p> - <p> - If <c>M</c> is not of type map an exception of type <c>badmap</c> is thrown. - </p> - <p> - To only update an existing value, the following syntax is used, - </p> - <code>M#{ K := V } </code> - <p> - where <c>M</c> is an term of type map, <c>V</c> is an expression and <c>K</c> - is an expression which evaluates to an existing key in <c>M</c>. - </p> - <p> - If key <c>K</c> does not match any existing keys in map <c>M</c> an exception - of type <c>badarg</c> will be triggered at runtime. If a matching key <c>K</c> - is present in map <c>M</c> its associated value will be replaced by the new - value <c>V</c> and the evaluated map expression returns a new map. - </p> - <p> - If <c>M</c> is not of type map an exception of type <c>badmap</c> is thrown. - </p> - <p> - Examples: - </p> - <code> -M0 = #{}, -M1 = M0#{a => 0}, -M2 = M1#{a => 1, b => 2}, -M3 = M2#{"function" => fun() -> f() end}, -M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code> - <p> - where <c>M0</c> is any map. It follows that <c>M1 .. M4</c> are maps as well. - </p> - <p> - More Examples: - </p> -<pre> -1> <input>M = #{1 => a}.</input> -#{1 => a } -2> <input>M#{1.0 => b}.</input> -#{1 => a, 1.0 => b}. -3> <input>M#{1 := b}.</input> -#{1 => b} -4> <input>M#{1.0 := b}.</input> -** exception error: bad argument -</pre> - <p> - As in construction, the order in which the key and value expressions - are evaluated is not defined. The - syntactic order of the key-value pairs in the update is of no - relevance, except in the case where two keys match, in which - case the latter value is used. - </p> - </section> - - <section> - <title>Maps in Patterns</title> - <p> - Matching of key-value associations from maps is done in the following way: - </p> - - <code>#{ K := V } = M</code> - <p> - where <c>M</c> is any map. The key <c>K</c> has to be an expression with bound - variables or a literals, and <c>V</c> can be any pattern with either bound or - unbound variables. - </p> - <p> - If the variable <c>V</c> is unbound, it will be bound to the value associated - with the key <c>K</c>, which has to exist in the map <c>M</c>. If the variable - <c>V</c> is bound, it has to match the value associated with <c>K</c> in <c>M</c>. - </p> - <p> Example: </p> -<code> -1> <input>M = #{"tuple" => {1,2}}.</input> -#{"tuple" => {1,2}} -2> <input>#{"tuple" := {1,B}} = M.</input> -#{"tuple" => {1,2}} -3> <input>B.</input> -2.</code> - <p> - This will bind variable <c>B</c> to integer <c>2</c>. - </p> - <p> - Similarly, multiple values from the map may be matched: - </p> - <code>#{ K1 := V1, .., Kn := Vn } = M</code> - <p> - where keys <c>K1 .. Kn</c> are any expressions with literals or bound variables. If all - keys exist in map <c>M</c> all variables in <c>V1 .. Vn</c> will be matched to the - associated values of their respective keys. - </p> - <p> - If the matching conditions are not met, the match will fail, either with - </p> - <list> - <item> - a <c>badmatch</c> exception, if used in the context of the matching operator - as in the example, - </item> - <item> - or resulting in the next clause being tested in function heads and - case expressions. - </item> - </list> - <p> - Matching in maps only allows for <c>:=</c> as delimiters of associations. - The order in which keys are declared in matching has no relevance. - </p> - <p> - Duplicate keys are allowed in matching and will match each pattern associated - to the keys. - </p> - <code>#{ K := V1, K := V2 } = M</code> - <p> - Matching an expression against an empty map literal will match its type but - no variables will be bound: - </p> - <code>#{} = Expr</code> - <p> - This expression will match if the expression <c>Expr</c> is of type map, otherwise - it will fail with an exception <c>badmatch</c>. - </p> - <section> - <title>Matching syntax: Example with literals in function heads</title> - <p> - Matching of literals as keys are allowed in function heads. - </p> - <code> -%% only start if not_started -handle_call(start, From, #{ state := not_started } = S) -> -... - {reply, ok, S#{ state := start }}; - -%% only change if started -handle_call(change, From, #{ state := start } = S) -> -... - {reply, ok, S#{ state := changed }};</code> - </section> - </section> - <section> - <title>Maps in Guards</title> - <p> - Maps are allowed in guards as long as all sub-expressions are valid guard expressions. - </p> - <p> - Two guard BIFs handles maps: - </p> - <list> - <item> - <seealso marker="erts:erlang#is_map/1">is_map/1</seealso> - </item> - <item> - <seealso marker="erts:erlang#map_size/1">map_size/1</seealso> - </item> - </list> - </section> -</chapter> diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml index f0ec7ef165..5cb0c11371 100644 --- a/system/doc/reference_manual/modules.xml +++ b/system/doc/reference_manual/modules.xml @@ -194,8 +194,7 @@ behaviour_info(callbacks) -> Callbacks.</pre> </p> <pre> -type my_type() :: atom() | integer(). --spec my_function(integer()) -> integer(). - </pre> +-spec my_function(integer()) -> integer().</pre> <p>Read more in <seealso marker="typespec">Types and Function specifications</seealso>. </p> <p> @@ -229,13 +228,9 @@ behaviour_info(callbacks) -> Callbacks.</pre> <p>The <c>module_info/0</c> function in each module returns a list of <c>{Key,Value}</c> tuples with information about the module. Currently, the list contain tuples with the following - <c>Key</c>s: <c>attributes</c>, <c>compile</c>, - <c>exports</c>, and <c>imports</c>. The order and number of tuples + <c>Key</c>s: <c>module</c>, <c>attributes</c>, <c>compile</c>, + <c>exports</c> and <c>md5</c>. The order and number of tuples may change without prior notice.</p> - - <warning><p>The <c>{imports,Value}</c> tuple may be removed in a future - release because <c>Value</c> is always an empty list. - Do not write code that depends on it being present.</p></warning> </section> <section> @@ -246,6 +241,11 @@ behaviour_info(callbacks) -> Callbacks.</pre> <p>The following values are allowed for <c>Key</c>:</p> <taglist> + <tag><c>module</c></tag> + <item> + <p>Return an atom representing the module name.</p> + </item> + <tag><c>attributes</c></tag> <item> <p>Return a list of <c>{AttributeName,ValueList}</c> tuples, @@ -267,10 +267,9 @@ behaviour_info(callbacks) -> Callbacks.</pre> <seealso marker="stdlib:beam_lib#strip/1">beam_lib(3)</seealso>.</p> </item> - <tag><c>imports</c></tag> + <tag><c>md5</c></tag> <item> - <p>Always return an empty list. The <c>imports</c> key may not - be supported in future release.</p> + <p>Return a binary representing the MD5 checksum of the module.</p> </item> <tag><c>exports</c></tag> diff --git a/system/doc/reference_manual/part.xml b/system/doc/reference_manual/part.xml index 36fb888748..ee8f3dd7eb 100644 --- a/system/doc/reference_manual/part.xml +++ b/system/doc/reference_manual/part.xml @@ -36,7 +36,6 @@ <xi:include href="typespec.xml"/> <xi:include href="expressions.xml"/> <xi:include href="macros.xml"/> - <xi:include href="maps.xml"/> <xi:include href="records.xml"/> <xi:include href="errors.xml"/> <xi:include href="processes.xml"/> diff --git a/system/doc/reference_manual/processes.xml b/system/doc/reference_manual/processes.xml index 20bab1eb48..95ae0672ec 100644 --- a/system/doc/reference_manual/processes.xml +++ b/system/doc/reference_manual/processes.xml @@ -114,8 +114,8 @@ spawn(Module, Name, Args) -> pid() <p>Two processes can be <em>linked</em> to each other. A link between two processes <c>Pid1</c> and <c>Pid2</c> is created by <c>Pid1</c> calling the BIF <c>link(Pid2)</c> (or vice versa). - There also exists a number a <c>spawn_link</c> BIFs, which spawns - and links to a process in one operation.</p> + There also exist a number of <c>spawn_link</c> BIFs, which spawn + and link to a process in one operation.</p> <p>Links are bidirectional and there can only be one link between two processes. Repeated calls to <c>link(Pid)</c> have no effect.</p> <p>A link can be removed by calling the BIF <c>unlink(Pid)</c>.</p> diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index cc35c6eb21..d1584d2b98 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -103,7 +103,7 @@ | Map | Tuple | Union - | UserDefined %% described in Section 6.3 + | UserDefined %% described in Section 7.3 Atom :: atom() | Erlang_Atom %% 'foo', 'bar', ... @@ -217,6 +217,9 @@ <cell><c>iolist()</c></cell><cell><c>maybe_improper_list(byte() | binary() | iolist(), binary() | [])</c></cell> </row> <row> + <cell><c>function()</c></cell><cell><c>fun()</c></cell> + </row> + <row> <cell><c>module()</c></cell><cell><c>atom()</c></cell> </row> <row> @@ -261,8 +264,10 @@ its violation results in a compilation error. </p> <note> - The following built-in list types also exist, - but they are expected to be rarely used. Hence, they have long names: + <p> + The following built-in list types also exist, + but they are expected to be rarely used. Hence, they have long names: + </p> </note> <pre> nonempty_maybe_improper_list() :: nonempty_maybe_improper_list(any(), any()) @@ -501,7 +506,9 @@ -spec foo({X, integer()}) -> X when X :: atom() ; ([Y]) -> Y when Y :: number().</pre> <note> + <p> For backwards compatibility the following form is also allowed: + </p> <pre> -spec id(X) -> X when is_subtype(X, tuple()).</pre> <p> but its use is discouraged. It will be taken out in a future diff --git a/system/doc/reference_manual/xmlfiles.mk b/system/doc/reference_manual/xmlfiles.mk index 181e6f8042..6886c8c7cf 100644 --- a/system/doc/reference_manual/xmlfiles.mk +++ b/system/doc/reference_manual/xmlfiles.mk @@ -24,7 +24,6 @@ REF_MAN_CHAPTER_FILES = \ functions.xml \ expressions.xml \ macros.xml \ - maps.xml \ records.xml \ errors.xml \ processes.xml \ diff --git a/system/doc/system_architecture_intro/sys_arch_intro.xml b/system/doc/system_architecture_intro/sys_arch_intro.xml index 62add510ca..3e88548861 100644 --- a/system/doc/system_architecture_intro/sys_arch_intro.xml +++ b/system/doc/system_architecture_intro/sys_arch_intro.xml @@ -150,7 +150,7 @@ <item>Chapter 8: "Operation and Management Principles" describes the model for operation and maintenance of sub-systems.</item> <item>Chapter 9: "Tutorial" gives an orientation of the different interoperability mechanism, which can be used when integrating an - Erlang program with a program written in an other programming language.</item> + Erlang program with a program written in another programming language.</item> </list> </section> diff --git a/system/doc/system_principles/create_target.xmlsrc b/system/doc/system_principles/create_target.xmlsrc index b5f8d8ac4d..a8ee2d1245 100644 --- a/system/doc/system_principles/create_target.xmlsrc +++ b/system/doc/system_principles/create_target.xmlsrc @@ -91,7 +91,7 @@ {pea, "1.0"}]}.</code> <p>The listed applications are not only original Erlang/OTP applications but possibly also new applications that you have - written yourself (here examplified by the application + written yourself (here exemplified by the application <c>pea</c>). </p> <p><em>Step 2.</em> From the directory where the <c>mysystem.rel</c> file reside, start the Erlang/OTP system:</p> @@ -251,7 +251,7 @@ os> <input>/usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI <c>target_system:create/1</c>. In fact, if you create, in the current directory, not only the <c>mysystem.rel</c> file, but also a <c>sys.config</c> file, that latter file will be tacitly - put in the apropriate directory.</p> + put in the appropriate directory.</p> </section> <section> @@ -408,7 +408,7 @@ heart: Tue Apr 1 12:15:11 2014: Executed "/usr/local/erl-target/bin/start /usr/ Erlang/OTP has Changed</seealso> for more infomation about this. </p> <p> - The node will be accessable via a new pipe: + The node will be accessible via a new pipe: </p> <pre> os> <input>/usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2</input></pre> diff --git a/system/doc/system_principles/system_principles.xml b/system/doc/system_principles/system_principles.xml index 70c69b1dab..79ed86cd9f 100644 --- a/system/doc/system_principles/system_principles.xml +++ b/system/doc/system_principles/system_principles.xml @@ -109,7 +109,7 @@ init:stop()</pre> <p>Loads the code for and starts the applications Kernel and STDLIB, skips loading the <c>.erlang</c> file. Useful for scripts and other tools that should be behave the - same irregardless of user preferences. + same regardless of user preferences. </p> </item> </taglist> diff --git a/system/doc/system_principles/versions.xml b/system/doc/system_principles/versions.xml index c63913d867..ff042f4a3b 100644 --- a/system/doc/system_principles/versions.xml +++ b/system/doc/system_principles/versions.xml @@ -67,7 +67,7 @@ suffix corresponds to the OTP version of the base system that has been patched. Note that if a development system is updated by other means than <c>otp_patch_apply</c>, the <c>OTP_VERSION</c> file - may identify wrong OTP version.</p> + may identify an incorrect OTP version.</p> <p>No <c>OTP_VERSION</c> file will be placed in a <seealso marker="create_target">target system</seealso> created diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc index 421ea63f33..2fd6fb0aac 100644 --- a/system/doc/tutorial/c_portdriver.xmlsrc +++ b/system/doc/tutorial/c_portdriver.xmlsrc @@ -35,7 +35,7 @@ <section> <title>Port Drivers</title> - <p>A port driver is a linked in driver, that is accessible as a + <p>A port driver is a linked in driver that is accessible as a port from an Erlang program. It is a shared library (SO in Unix, DLL in Windows), with special entry points. The Erlang runtime calls these entry points, when the driver is started and when diff --git a/system/doc/tutorial/distribution.xml b/system/doc/tutorial/distribution.xml index 6a0ea759c4..ced8e4a545 100644 --- a/system/doc/tutorial/distribution.xml +++ b/system/doc/tutorial/distribution.xml @@ -58,7 +58,6 @@ <item>global_group - Grouping nodes to global name registration groups.</item> <item>net_adm - Various net administration routines.</item> <item>net_kernel - Networking kernel.</item> - <item>pg - Distributed named process groups, experimental implementation.</item> <item>pg2 - Distributed named process groups.</item> <item>pool - Load distribution facility.</item> <item>slave - Functions for starting and controlling slave nodes.</item> |