aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/efficiency_guide/listhandling.xml
diff options
context:
space:
mode:
Diffstat (limited to 'system/doc/efficiency_guide/listhandling.xml')
-rw-r--r--system/doc/efficiency_guide/listhandling.xml120
1 files changed, 62 insertions, 58 deletions
diff --git a/system/doc/efficiency_guide/listhandling.xml b/system/doc/efficiency_guide/listhandling.xml
index 9112738b18..b950f55ad1 100644
--- a/system/doc/efficiency_guide/listhandling.xml
+++ b/system/doc/efficiency_guide/listhandling.xml
@@ -18,10 +18,9 @@
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>List handling</title>
+ <title>List Handling</title>
<prepared>Bjorn Gustavsson</prepared>
<docno></docno>
<date>2007-11-16</date>
@@ -30,19 +29,18 @@
</header>
<section>
- <title>Creating a list</title>
+ <title>Creating a List</title>
- <p>Lists can only be built starting from the end and attaching
- list elements at the beginning. If you use the <c>++</c> operator
- like this</p>
+ <p>Lists can only be built starting from the end and attaching list
+ elements at the beginning. If you use the "<c>++</c>" operator as
+ follows, a new list is created that is a copy of the elements in
+ <c>List1</c>, followed by <c>List2</c>:</p>
<code type="erl">
List1 ++ List2</code>
- <p>you will create a new list which is copy of the elements in <c>List1</c>,
- followed by <c>List2</c>. Looking at how <c>lists:append/1</c> or <c>++</c> would be
- implemented in plain Erlang, it can be seen clearly that the first list
- is copied:</p>
+ <p>Looking at how <c>lists:append/1</c> or <c>++</c> would be
+ implemented in plain Erlang, clearly the first list is copied:</p>
<code type="erl">
append([H|T], Tail) ->
@@ -50,12 +48,12 @@ append([H|T], Tail) ->
append([], Tail) ->
Tail.</code>
- <p>So the important thing when recursing and building a list is to
- make sure that you attach the new elements to the beginning of the list,
- so that you build <em>a</em> list, and not hundreds or thousands of
- copies of the growing result list.</p>
+ <p>When recursing and building a list, it is important to ensure
+ that you attach the new elements to the beginning of the list. In
+ this way, you will build <em>one</em> list, not hundreds or thousands
+ of copies of the growing result list.</p>
- <p>Let us first look at how it should not be done:</p>
+ <p>Let us first see how it is not to be done:</p>
<p><em>DO NOT</em></p>
<code type="erl"><![CDATA[
@@ -67,11 +65,11 @@ bad_fib(0, _Current, _Next, Fibs) ->
bad_fib(N, Current, Next, Fibs) ->
bad_fib(N - 1, Next, Current + Next, Fibs ++ [Current]).]]></code>
- <p>Here we are not a building a list; in each iteration step we
- create a new list that is one element longer than the new previous list.</p>
+ <p>Here more than one list is built. In each iteration step a new list
+ is created that is one element longer than the new previous list.</p>
- <p>To avoid copying the result in each iteration, we must build the list in
- reverse order and reverse the list when we are done:</p>
+ <p>To avoid copying the result in each iteration, build the list in
+ reverse order and reverse the list when you are done:</p>
<p><em>DO</em></p>
<code type="erl"><![CDATA[
@@ -86,49 +84,45 @@ tail_recursive_fib(N, Current, Next, Fibs) ->
</section>
<section>
- <title>List comprehensions</title>
+ <title>List Comprehensions</title>
<p>Lists comprehensions still have a reputation for being slow.
They used to be implemented using funs, which used to be slow.</p>
- <p>In recent Erlang/OTP releases (including R12B), a list comprehension</p>
+ <p>In recent Erlang/OTP releases (including R12B), a list comprehension:</p>
<code type="erl"><![CDATA[
[Expr(E) || E <- List]]]></code>
- <p>is basically translated to a local function</p>
+ <p>is basically translated to a local function:</p>
<code type="erl">
'lc^0'([E|Tail], Expr) ->
[Expr(E)|'lc^0'(Tail, Expr)];
'lc^0'([], _Expr) -> [].</code>
- <p>In R12B, if the result of the list comprehension will <em>obviously</em> not be used,
- a list will not be constructed. For instance, in this code</p>
+ <p>In R12B, if the result of the list comprehension will <em>obviously</em>
+ not be used, a list will not be constructed. For example, in this code:</p>
<code type="erl"><![CDATA[
[io:put_chars(E) || E <- List],
ok.]]></code>
- <p>or in this code</p>
+ <p>or in this code:</p>
<code type="erl"><![CDATA[
-.
-.
-.
+...
case Var of
... ->
[io:put_chars(E) || E <- List];
... ->
end,
some_function(...),
-.
-.
-.]]></code>
+...]]></code>
- <p>the value is neither assigned to a variable, nor passed to another function,
- nor returned, so there is no need to construct a list and the compiler will simplify
- the code for the list comprehension to</p>
+ <p>the value is not assigned to a variable, not passed to another function,
+ and not returned. This means that there is no need to construct a list and
+ the compiler will simplify the code for the list comprehension to:</p>
<code type="erl">
'lc^0'([E|Tail], Expr) ->
@@ -139,14 +133,15 @@ some_function(...),
</section>
<section>
- <title>Deep and flat lists</title>
+ <title>Deep and Flat Lists</title>
<p><seealso marker="stdlib:lists#flatten/1">lists:flatten/1</seealso>
- builds an entirely new list. Therefore, it is expensive, and even
- <em>more</em> expensive than the <c>++</c> (which copies its left argument,
- but not its right argument).</p>
+ builds an entirely new list. It is therefore expensive, and even
+ <em>more</em> expensive than the <c>++</c> operator (which copies its
+ left argument, but not its right argument).</p>
- <p>In the following situations, you can easily avoid calling <c>lists:flatten/1</c>:</p>
+ <p>In the following situations, you can easily avoid calling
+ <c>lists:flatten/1</c>:</p>
<list type="bulleted">
<item>When sending data to a port. Ports understand deep lists
@@ -155,16 +150,19 @@ some_function(...),
<item>When calling BIFs that accept deep lists, such as
<seealso marker="erts:erlang#list_to_binary/1">list_to_binary/1</seealso> or
<seealso marker="erts:erlang#iolist_to_binary/1">iolist_to_binary/1</seealso>.</item>
- <item>When you know that your list is only one level deep, you can can use
+ <item>When you know that your list is only one level deep, you can use
<seealso marker="stdlib:lists#append/1">lists:append/1</seealso>.</item>
</list>
- <p><em>Port example</em></p>
+ <section>
+ <title>Port Example</title>
+
<p><em>DO</em></p>
<pre>
...
port_command(Port, DeepList)
...</pre>
+
<p><em>DO NOT</em></p>
<pre>
...
@@ -180,7 +178,7 @@ some_function(...),
port_command(Port, TerminatedStr)
...</pre>
- <p>Instead do like this:</p>
+ <p>Instead:</p>
<p><em>DO</em></p>
<pre>
@@ -188,47 +186,53 @@ some_function(...),
TerminatedStr = [String, 0], % String="foo" => [[$f, $o, $o], 0]
port_command(Port, TerminatedStr)
...</pre>
+ </section>
+
+ <section>
+ <title>Append Example</title>
- <p><em>Append example</em></p>
<p><em>DO</em></p>
<pre>
> lists:append([[1], [2], [3]]).
[1,2,3]
></pre>
+
<p><em>DO NOT</em></p>
<pre>
> lists:flatten([[1], [2], [3]]).
[1,2,3]
></pre>
+ </section>
</section>
<section>
- <title>Why you should not worry about recursive lists functions</title>
+ <title>Recursive List Functions</title>
- <p>In the performance myth chapter, the following myth was exposed:
- <seealso marker="myths#tail_recursive">Tail-recursive functions
- are MUCH faster than recursive functions</seealso>.</p>
+ <p>In Section 7.2, the following myth was exposed:
+ <seealso marker="myths#tail_recursive">Tail-Recursive Functions
+ are Much Faster Than Recursive Functions</seealso>.</p>
<p>To summarize, in R12B there is usually not much difference between
a body-recursive list function and tail-recursive function that reverses
the list at the end. Therefore, concentrate on writing beautiful code
- and forget about the performance of your list functions. In the time-critical
- parts of your code (and only there), <em>measure</em> before rewriting
- your code.</p>
-
- <p><em>Important note</em>: This section talks about lists functions that
- <em>construct</em> lists. A tail-recursive function that does not construct
- a list runs in constant space, while the corresponding body-recursive
- function uses stack space proportional to the length of the list.
- For instance, a function that sums a list of integers, should <em>not</em> be
- written like this</p>
+ and forget about the performance of your list functions. In the
+ time-critical parts of your code (and only there), <em>measure</em>
+ before rewriting your code.</p>
+
+ <note><p>This section is about list functions that <em>construct</em>
+ lists. A tail-recursive function that does not construct a list runs
+ in constant space, while the corresponding body-recursive function
+ uses stack space proportional to the length of the list.</p></note>
+
+ <p>For example, a function that sums a list of integers, is
+ <em>not</em> to be written as follows:</p>
<p><em>DO NOT</em></p>
<code type="erl">
recursive_sum([H|T]) -> H+recursive_sum(T);
recursive_sum([]) -> 0.</code>
- <p>but like this</p>
+ <p>Instead:</p>
<p><em>DO</em></p>
<code type="erl">