diff options
Diffstat (limited to 'system/doc/efficiency_guide/functions.xml')
| -rw-r--r-- | system/doc/efficiency_guide/functions.xml | 141 | 
1 files changed, 76 insertions, 65 deletions
diff --git a/system/doc/efficiency_guide/functions.xml b/system/doc/efficiency_guide/functions.xml index ec1a45eaa9..9616df554e 100644 --- a/system/doc/efficiency_guide/functions.xml +++ b/system/doc/efficiency_guide/functions.xml @@ -8,17 +8,17 @@        <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. - +      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 +      distributed under the License is distributed on an "AS IS" BASIS, +      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +      See the License for the specific language governing permissions and +      limitations under the License.      </legalnotice>      <title>Functions</title> @@ -30,17 +30,18 @@    </header>    <section> -    <title>Pattern matching</title> -    <p>Pattern matching in function head and in <c>case</c> and <c>receive</c> -     clauses are optimized by the compiler. With a few exceptions, there is nothing -     to gain by rearranging clauses.</p> +    <title>Pattern Matching</title> +    <p>Pattern matching in function head as well as in <c>case</c> and +    <c>receive</c> clauses are optimized by the compiler. With a few +    exceptions, there is nothing to gain by rearranging clauses.</p>      <p>One exception is pattern matching of binaries. The compiler -    will not rearrange clauses that match binaries. Placing the -    clause that matches against the empty binary <em>last</em> will usually -    be slightly faster than placing it <em>first</em>.</p> +    does not rearrange clauses that match binaries. Placing the +    clause that matches against the empty binary <em>last</em> is usually +    slightly faster than placing it <em>first</em>.</p> -    <p>Here is a rather contrived example to show another exception:</p> +    <p>The following is a rather unnatural example to show another +    exception:</p>      <p><em>DO NOT</em></p>      <code type="erl"> @@ -53,27 +54,30 @@ atom_map1(five) -> 5;  atom_map1(six) -> 6.</code>       <p>The problem is the clause with the variable <c>Int</c>. -     Since a variable can match anything, including the atoms -     <c>four</c>, <c>five</c>, and <c>six</c> that the following clauses -     also will match, the compiler must generate sub-optimal code that will -     execute as follows:</p> +     As a variable can match anything, including the atoms +     <c>four</c>, <c>five</c>, and <c>six</c>, which the following clauses +     also match, the compiler must generate suboptimal code that +     executes as follows:</p> -     <p>First the input value is compared to <c>one</c>, <c>two</c>, and +     <list type="bulleted"> +     <item>First, the input value is compared to <c>one</c>, <c>two</c>, and       <c>three</c> (using a single instruction that does a binary search;       thus, quite efficient even if there are many values) to select which -     one of the first three clauses to execute (if any).</p> +     one of the first three clauses to execute (if any).</item> + +     <item>>If none of the first three clauses match, the fourth clause +     match as a variable always matches.</item> -     <p>If none of the first three clauses matched, the fourth clause -     will match since a variable always matches. If the guard test -     <c>is_integer(Int)</c> succeeds, the fourth clause will be -     executed.</p> +     <item>If the guard test <c>is_integer(Int)</c> succeeds, the fourth +     clause is executed.</item> -     <p>If the guard test failed, the input value is compared to +     <item>If the guard test fails, the input value is compared to       <c>four</c>, <c>five</c>, and <c>six</c>, and the appropriate clause -     is selected. (There will be a <c>function_clause</c> exception if -     none of the values matched.)</p> +     is selected. (There is a <c>function_clause</c> exception if none of +     the values matched.)</item> +     </list> -     <p>Rewriting to either</p> +     <p>Rewriting to either:</p>       <p><em>DO</em></p>       <code type="erl"><![CDATA[ @@ -85,7 +89,7 @@ atom_map2(five) -> 5;  atom_map2(six) -> 6;  atom_map2(Int) when is_integer(Int) -> Int.]]></code> -     <p>or</p>  +     <p>or:</p>       <p><em>DO</em></p>       <code type="erl"><![CDATA[ @@ -97,9 +101,9 @@ atom_map3(four) -> 4;  atom_map3(five) -> 5;  atom_map3(six) -> 6.]]></code> -     <p>will give slightly more efficient matching code.</p> +     <p>gives slightly more efficient matching code.</p> -     <p>Here is a less contrived example:</p> +     <p>Another example:</p>       <p><em>DO NOT</em></p>       <code type="erl"><![CDATA[ @@ -116,7 +120,8 @@ map_pairs1(Map, [X|Xs], [Y|Ys]) ->       match anything, the compiler is not allowed to rearrange the clauses,       but must generate code that matches them in the order written.</p> -     <p>If the function is rewritten like this</p> +     <p>If the function is rewritten as follows, the compiler is free to +     rearrange the clauses:</p>       <p><em>DO</em></p>       <code type="erl"><![CDATA[ @@ -127,8 +132,7 @@ map_pairs2(_Map, [_|_]=Xs, [] ) ->  map_pairs2(Map, [X|Xs], [Y|Ys]) ->      [Map(X, Y)|map_pairs2(Map, Xs, Ys)].]]></code> -    <p>the compiler is free to rearrange the clauses. It will generate code -    similar to this</p> +    <p>The compiler will generate code similar to this:</p>      <p><em>DO NOT (already done by the compiler)</em></p>      <code type="erl"><![CDATA[ @@ -145,31 +149,35 @@ explicit_map_pairs(Map, Xs0, Ys0) ->  	    Ys0      end.]]></code> -    <p>which should be slightly faster for presumably the most common case +    <p>This is slightly faster for probably the most common case      that the input lists are not empty or very short. -    (Another advantage is that Dialyzer is able to deduce a better type -    for the variable <c>Xs</c>.)</p> +    (Another advantage is that Dialyzer can deduce a better type +    for the <c>Xs</c> variable.)</p>    </section>    <section> -    <title>Function Calls </title> +    <title>Function Calls</title> -    <p>Here is an intentionally rough guide to the relative costs of -    different kinds of calls. It is based on benchmark figures run on +    <p>This is an intentionally rough guide to the relative costs of +    different calls. It is based on benchmark figures run on      Solaris/Sparc:</p>      <list type="bulleted">      <item>Calls to local or external functions (<c>foo()</c>, <c>m:foo()</c>) -    are the fastest kind of calls.</item> +    are the fastest calls.</item> +      <item>Calling or applying a fun (<c>Fun()</c>, <c>apply(Fun, [])</c>) -    is about <em>three times</em> as expensive as calling a local function.</item> +    is about <em>three times</em> as expensive as calling a local +    function.</item> +      <item>Applying an exported function (<c>Mod:Name()</c>, -    <c>apply(Mod, Name, [])</c>) is about twice as expensive as calling a fun, -    or about <em>six times</em> as expensive as calling a local function.</item> +    <c>apply(Mod, Name, [])</c>) is about twice as expensive as calling +    a fun or about <em>six times</em> as expensive as calling a local +    function.</item>      </list>      <section> -       <title>Notes and implementation details</title> +       <title>Notes and Implementation Details</title>         <p>Calling and applying a fun does not involve any hash-table lookup.         A fun contains an (indirect) pointer to the function that implements @@ -178,42 +186,44 @@ explicit_map_pairs(Map, Xs0, Ys0) ->         <warning><p><em>Tuples are not fun(s)</em>.         A "tuple fun", <c>{Module,Function}</c>, is not a fun.         The cost for calling a "tuple fun" is similar to that -       of <c>apply/3</c> or worse. Using "tuple funs" is <em>strongly discouraged</em>, -       as they may not be supported in a future release, -       and because there exists a superior alternative since the R10B -       release, namely the <c>fun Module:Function/Arity</c> syntax.</p></warning> +       of <c>apply/3</c> or worse. +       Using "tuple funs" is <em>strongly discouraged</em>, +       as they might not be supported in a future Erlang/OTP release, +       and because there exists a superior alternative from R10B, +       namely the <c>fun Module:Function/Arity</c> syntax.</p></warning>         <p><c>apply/3</c> must look up the code for the function to execute -       in a hash table. Therefore, it will always be slower than a +       in a hash table. It is therefore always slower than a         direct call or a fun call.</p>         <p>It no longer matters (from a performance point of view) -       whether you write</p> +       whether you write:</p>         <code type="erl">  Module:Function(Arg1, Arg2)</code> -       <p>or</p> +       <p>or:</p>         <code type="erl">  apply(Module, Function, [Arg1,Arg2])</code> -       <p>(The compiler internally rewrites the latter code into the former.)</p> +       <p>The compiler internally rewrites the latter code into the +       former.</p> -       <p>The following code</p> +       <p>The following code is slightly slower because the shape of the +       list of arguments is unknown at compile time.</p>         <code type="erl">  apply(Module, Function, Arguments)</code> -       <p>is slightly slower because the shape of the list of arguments -       is not known at compile time.</p>      </section>    </section>    <section> -    <title>Memory usage in recursion</title> -    <p>When writing recursive functions it is preferable to make them -      tail-recursive so that they can execute in constant memory space.</p> +    <title>Memory Usage in Recursion</title> +    <p>When writing recursive functions, it is preferable to make them +      tail-recursive so that they can execute in constant memory space:</p> +      <p><em>DO</em></p>      <code type="none">  list_length(List) -> @@ -224,13 +234,14 @@ list_length([], AccLen) ->  list_length([_|Tail], AccLen) ->      list_length(Tail, AccLen + 1). % Tail-recursive</code> +      <p><em>DO NOT</em></p> +      <code type="none">  list_length([]) ->      0. % Base case  list_length([_ | Tail]) ->      list_length(Tail) + 1. % Not tail-recursive</code>    </section> -  </chapter>  | 
