~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to system/doc/programming_examples/list_comprehensions.xml

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="latin1" ?>
 
2
<!DOCTYPE chapter SYSTEM "chapter.dtd">
 
3
 
 
4
<chapter>
 
5
  <header>
 
6
    <copyright>
 
7
      <year>2003</year><year>2009</year>
 
8
      <holder>Ericsson AB. All Rights Reserved.</holder>
 
9
    </copyright>
 
10
    <legalnotice>
 
11
      The contents of this file are subject to the Erlang Public License,
 
12
      Version 1.1, (the "License"); you may not use this file except in
 
13
      compliance with the License. You should have received a copy of the
 
14
      Erlang Public License along with this software. If not, it can be
 
15
      retrieved online at http://www.erlang.org/.
 
16
    
 
17
      Software distributed under the License is distributed on an "AS IS"
 
18
      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
19
      the License for the specific language governing rights and limitations
 
20
      under the License.
 
21
    
 
22
    </legalnotice>
 
23
 
 
24
    <title>List Comprehensions</title>
 
25
    <prepared></prepared>
 
26
    <docno></docno>
 
27
    <date></date>
 
28
    <rev></rev>
 
29
    <file>list_comprehensions.xml</file>
 
30
  </header>
 
31
 
 
32
  <section>
 
33
    <title>Simple Examples</title>
 
34
    <p>We start with a simple example:</p>
 
35
    <pre>
 
36
> <input>[X || X &lt;- [1,2,a,3,4,b,5,6], X > 3].</input>
 
37
[a,4,b,5,6]</pre>
 
38
    <p>This should be read as follows:</p>
 
39
    <quote>
 
40
      <p>The list of X such that X is taken from the list
 
41
        <c>[1,2,a,...]</c> and X is greater than 3.</p>
 
42
    </quote>
 
43
    <p>The notation <c><![CDATA[X <- [1,2,a,...]]]></c> is a generator and
 
44
      the expression <c>X > 3</c> is a filter.</p>
 
45
    <p>An additional filter can be added in order to restrict
 
46
      the result to integers:</p>
 
47
    <pre>
 
48
> <input>[X || X &lt;- [1,2,a,3,4,b,5,6], integer(X), X > 3].</input>
 
49
[4,5,6]</pre>
 
50
    <p>Generators can be combined. For example, the Cartesian product
 
51
      of two lists can be written as follows:</p>
 
52
    <pre>
 
53
> <input>[{X, Y} || X &lt;- [1,2,3], Y &lt;- [a,b]].</input>
 
54
[{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}]</pre>
 
55
  </section>
 
56
 
 
57
  <section>
 
58
    <title>Quick Sort</title>
 
59
    <p>The well known quick sort routine can be written as follows:</p>
 
60
    <code type="none"><![CDATA[
 
61
sort([Pivot|T]) ->
 
62
    sort([ X || X <- T, X < Pivot]) ++
 
63
    [Pivot] ++
 
64
    sort([ X || X <- T, X >= Pivot]);
 
65
sort([]) -> [].]]></code>
 
66
    <p>The expression <c><![CDATA[[X || X <- T, X < Pivot]]]></c> is the list of
 
67
      all elements in <c>T</c>, which are less than <c>Pivot</c>.</p>
 
68
    <p><c><![CDATA[[X || X <- T, X >= Pivot]]]></c> is the list of all elements in
 
69
      <c>T</c>, which are greater or equal to <c>Pivot</c>.</p>
 
70
    <p>To sort a list, we isolate the first element in the list and
 
71
      split the list into two sub-lists. The first sub-list contains
 
72
      all elements which are smaller than the first element in
 
73
      the list, the second contains all elements which are greater
 
74
      than or equal to the first element in the list. We then sort
 
75
      the sub-lists and combine the results.</p>
 
76
  </section>
 
77
 
 
78
  <section>
 
79
    <title>Permutations</title>
 
80
    <p>The following example generates all permutations of
 
81
      the elements in a list:</p>
 
82
    <code type="none"><![CDATA[
 
83
perms([]) -> [[]];
 
84
perms(L)  -> [[H|T] || H <- L, T <- perms(L--[H])].]]></code>
 
85
    <p>We take take <c>H</c> from <c>L</c> in all possible ways.
 
86
      The result is the set of all lists <c>[H|T]</c>, where <c>T</c>
 
87
      is the set of all possible permutations of <c>L</c> with
 
88
      <c>H</c> removed.</p>
 
89
    <pre>
 
90
> <input>perms([b,u,g]).</input>
 
91
[[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]]</pre>
 
92
  </section>
 
93
 
 
94
  <section>
 
95
    <title>Pythagorean Triplets</title>
 
96
    <p>Pythagorean triplets are sets of integers <c>{A,B,C}</c> such
 
97
      that <c>A**2 + B**2 = C**2</c>.</p>
 
98
    <p>The function <c>pyth(N)</c> generates a list of all integers
 
99
      <c>{A,B,C}</c> such that <c>A**2 + B**2 = C**2</c> and where
 
100
      the sum of the sides is equal to or less than <c>N</c>.</p>
 
101
    <code type="none"><![CDATA[
 
102
pyth(N) ->
 
103
    [ {A,B,C} ||
 
104
        A <- lists:seq(1,N),
 
105
        B <- lists:seq(1,N),
 
106
        C <- lists:seq(1,N),
 
107
        A+B+C =< N,
 
108
        A*A+B*B == C*C 
 
109
    ].]]></code>
 
110
    <pre>
 
111
> <input>pyth(3).</input>
 
112
[].
 
113
> <input>pyth(11).</input>
 
114
[].
 
115
> <input>pyth(12).</input>
 
116
[{3,4,5},{4,3,5}]
 
117
> <input>pyth(50).</input>
 
118
[{3,4,5},
 
119
 {4,3,5},
 
120
 {5,12,13},
 
121
 {6,8,10},
 
122
 {8,6,10},
 
123
 {8,15,17},
 
124
 {9,12,15},
 
125
 {12,5,13},
 
126
 {12,9,15},
 
127
 {12,16,20},
 
128
 {15,8,17},
 
129
 {16,12,20}]</pre>
 
130
    <p>The following code reduces the search space and is more
 
131
      efficient:</p>
 
132
    <code type="none"><![CDATA[
 
133
pyth1(N) ->
 
134
   [{A,B,C} ||
 
135
       A <- lists:seq(1,N-2),
 
136
       B <- lists:seq(A+1,N-1),
 
137
       C <- lists:seq(B+1,N),
 
138
       A+B+C =< N,
 
139
       A*A+B*B == C*C ].]]></code>
 
140
  </section>
 
141
 
 
142
  <section>
 
143
    <title>Simplifications with List Comprehensions</title>
 
144
    <p>As an example, list comprehensions can be used to simplify some
 
145
      of the functions in <c>lists.erl</c>:</p>
 
146
    <code type="none"><![CDATA[
 
147
append(L)   ->  [X || L1 <- L, X <- L1].
 
148
map(Fun, L) -> [Fun(X) || X <- L].
 
149
filter(Pred, L) -> [X || X <- L, Pred(X)].]]></code>
 
150
  </section>
 
151
 
 
152
  <section>
 
153
    <title>Variable Bindings in List Comprehensions</title>
 
154
    <p>The scope rules for variables which occur in list
 
155
      comprehensions are as follows:</p>
 
156
    <list type="bulleted">
 
157
      <item>all variables which occur in a generator pattern are
 
158
       assumed to be "fresh" variables</item>
 
159
      <item>any variables which are defined before the list
 
160
       comprehension and which are used in filters have the values
 
161
       they had before the list comprehension</item>
 
162
      <item>no variables may be exported from a list comprehension.</item>
 
163
    </list>
 
164
    <p>As an example of these rules, suppose we want to write
 
165
      the function <c>select</c>, which selects certain elements from
 
166
      a list of tuples. We might write
 
167
      <c><![CDATA[select(X, L) ->  [Y || {X, Y} <- L].]]></c> with the intention
 
168
      of extracting all tuples from <c>L</c> where the first item is
 
169
      <c>X</c>.</p>
 
170
    <p>Compiling this yields the following diagnostic:</p>
 
171
    <code type="none">
 
172
./FileName.erl:Line: Warning: variable 'X' shadowed in generate</code>
 
173
    <p>This diagnostic warns us that the variable <c>X</c> in
 
174
      the pattern is not the same variable as the variable <c>X</c>
 
175
      which occurs in the function head.</p>
 
176
    <p>Evaluating <c>select</c> yields the following result:</p>
 
177
    <pre>
 
178
> <input>select(b,[{a,1},{b,2},{c,3},{b,7}]).</input>
 
179
[1,2,3,7]</pre>
 
180
    <p>This result is not what we wanted. To achieve the desired
 
181
      effect we must write <c>select</c> as follows:</p>
 
182
    <code type="none"><![CDATA[
 
183
select(X, L) ->  [Y || {X1, Y} <- L, X == X1].]]></code>
 
184
    <p>The generator now contains unbound variables and the test has
 
185
      been moved into the filter. This now works as expected:</p>
 
186
    <pre>
 
187
> <input>select(b,[{a,1},{b,2},{c,3},{b,7}]).</input>
 
188
[2,7]</pre>
 
189
    <p>One consequence of the rules for importing variables into a
 
190
      list comprehensions is that certain pattern matching operations
 
191
      have to be moved into the filters and cannot be written directly
 
192
      in the generators. To illustrate this, do not write as follows:</p>
 
193
    <code type="none"><![CDATA[
 
194
f(...) ->
 
195
    Y = ...
 
196
    [ Expression || PatternInvolving Y  <- Expr, ...]
 
197
    ...]]></code>
 
198
    <p>Instead, write as follows:</p>
 
199
    <code type="none"><![CDATA[
 
200
f(...) ->
 
201
    Y = ...
 
202
    [ Expression || PatternInvolving Y1  <- Expr, Y == Y1, ...]
 
203
    ...]]></code>
 
204
  </section>
 
205
</chapter>
 
206