aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/getting_started/seq_prog.xml
diff options
context:
space:
mode:
Diffstat (limited to 'system/doc/getting_started/seq_prog.xml')
-rw-r--r--system/doc/getting_started/seq_prog.xml1231
1 files changed, 1231 insertions, 0 deletions
diff --git a/system/doc/getting_started/seq_prog.xml b/system/doc/getting_started/seq_prog.xml
new file mode 100644
index 0000000000..bc1758d855
--- /dev/null
+++ b/system/doc/getting_started/seq_prog.xml
@@ -0,0 +1,1231 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2003</year><year>2009</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>Sequential Programming</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>seq_prog.xml</file>
+ </header>
+
+ <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
+ 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>
+ <pre>
+% <input>erl</input>
+Erlang (BEAM) emulator version 5.2 [source] [hipe]
+
+Eshell V5.2 (abort with ^G)
+1></pre>
+ <p>Now type in "2 + 5." as shown below.</p>
+ <pre>
+1> <input>2 + 5.</input>
+7
+2></pre>
+ <p>In Windows, the shell is started by double-clicking on the Erlang
+ shell icon.</p>
+ <p>You'll notice that the Erlang shell has numbered the lines that
+ can be entered, (as 1&gt; 2&gt;) and that it has correctly told you
+ that 2 + 5 is 7! Also notice that you have to tell it you are
+ done entering code by finishing with a full stop "." and a
+ carriage return. If you make mistakes writing things in the shell,
+ you can delete things by using the backspace key as in most
+ shells. There are many more editing commands in the shell
+ (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>
+ <p>Now let's try a more complex calculation.</p>
+ <pre>
+2> <input>(42 + 77) * 66 / 3.</input>
+2618.0</pre>
+ <p>Here you can see the use of brackets and the multiplication
+ operator "*" and division operator "/", just as in normal
+ arithmetic (see the chapter
+ <seealso marker="doc/reference_manual:expressions">"Arithmetic Expressions"</seealso> in the Erlang Reference Manual).</p>
+ <p>To shutdown the Erlang system and the Erlang shell type
+ Control-C. You will see the following output:</p>
+ <pre>
+BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
+ (v)ersion (k)ill (D)b-tables (d)istribution
+<input>a</input>
+%</pre>
+ <p>Type "a" to leave the Erlang system.</p>
+ <p>Another way to shutdown the Erlang system is by entering
+ <c>halt()</c>:</p>
+ <pre>
+3> <input>halt().</input>
+% </pre>
+ </section>
+
+ <section>
+ <title>Modules and Functions</title>
+ <p>A programming language isn't much use if you can just run code
+ from the shell. So here is a small Erlang program. Enter it into
+ a file called <c>tut.erl</c> (the file name <c>tut.erl</c> is
+ important, also make sure that it is in the same directory as
+ the one where you started <c>erl</c>) using a suitable
+ text editor. If you are lucky your editor will have an Erlang
+ mode which will make it easier for you to enter and format your
+ code nicely (see the chapter
+ <seealso marker="tools:erlang_mode_chapter">"The Erlang mode for Emacs"</seealso> in Tools User's Guide), but you can manage
+ perfectly well without. Here's the code to enter:</p>
+ <code type="none">
+-module(tut).
+-export([double/1]).
+
+double(X) ->
+ 2 * X.</code>
+ <p>It's not hard to guess that this "program" doubles the value of
+ numbers. I'll get back to the first two lines later. Let's compile
+ the program. This can be done in your Erlang shell as shown below:</p>
+ <pre>
+3> <input>c(tut).</input>
+{ok,tut}</pre>
+ <p>The <c>{ok,tut}</c> tells you that the compilation was OK. If it
+ said "error" instead, you have made some mistake in the text you
+ 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>
+ <pre>
+4> <input>tut:double(10).</input>
+20</pre>
+ <p>As expected double of 10 is 20.</p>
+ <p>Now let's get back to the first two lines. Erlang programs are
+ written in files. Each file contains what we call an Erlang
+ <em>module</em>. The first line of code in the module tells us
+ the name of the module (see the chapter
+ <seealso marker="doc/reference_manual:modules">"Modules"</seealso>
+ in the Erlang Reference Manual).</p>
+ <code type="none">
+-module(tut).</code>
+ <p>This tells us that the module is called <em>tut</em>. Note
+ the "." at the end of the line. The files which are used to store
+ the module must have the same name as the module but with
+ the extension ".erl". In our case the file name is <c>tut.erl</c>.
+ When we use a function in another module, we use the syntax,
+ <c>module_name:function_name(arguments)</c>. So</p>
+ <pre>
+4> <input>tut:double(10).</input></pre>
+ <p>means call function <c>double</c> in module <c>tut</c> with
+ argument "10".</p>
+ <p>The second line:</p>
+ <code type="none">
+-export([double/1]).</code>
+ <p>says that the module <c>tut</c> contains a function called
+ <c>double</c> which takes one argument (<c>X</c> in our example)
+ and that this function can be called from outside the module
+ <c>tut</c>. More about this later. Again note the "." at the end
+ of the line.</p>
+ <p>Now for a more complicated example, the factorial of a number
+ (e.g. factorial of 4 is 4 * 3 * 2 * 1). Enter the following code
+ in a file called <c>tut1.erl</c>.</p>
+ <code type="none">
+-module(tut1).
+-export([fac/1]).
+
+fac(1) ->
+ 1;
+fac(N) ->
+ N * fac(N - 1).</code>
+ <p>Compile the file</p>
+ <pre>
+5> <input>c(tut1).</input>
+{ok,tut1}</pre>
+ <p>And now calculate the factorial of 4.</p>
+ <pre>
+6> <input>tut1:fac(4).</input>
+24</pre>
+ <p>The first part:</p>
+ <code type="none">
+fac(1) ->
+ 1;</code>
+ <p>says that the factorial of 1 is 1. Note that we end this part
+ with a ";" which indicates that there is more of this function to
+ come. The second part:</p>
+ <code type="none">
+fac(N) ->
+ N * fac(N - 1).</code>
+ <p>says that the factorial of N is N multiplied by the factorial of
+ N - 1. Note that this part ends with a "." saying that there are
+ no more parts of this function.</p>
+ <p>A function can have many arguments. Let's expand the module
+ <c>tut1</c> with the rather stupid function to multiply two
+ numbers:</p>
+ <code type="none">
+-module(tut1).
+-export([fac/1, mult/2]).
+
+fac(1) ->
+ 1;
+fac(N) ->
+ N * fac(N - 1).
+
+mult(X, Y) ->
+ X * Y.</code>
+ <p>Note that we have also had to expand the <c>-export</c> line
+ with the information that there is another function <c>mult</c>
+ with two arguments.</p>
+ <p>Compile:</p>
+ <pre>
+7> <input>c(tut1).</input>
+{ok,tut1}</pre>
+ <p>and try it out:</p>
+ <pre>
+8> <input>tut1:mult(3,4).</input>
+12</pre>
+ <p>In the example above the numbers are integers and the arguments
+ in the functions in the code, <c>N</c>, <c>X</c>, <c>Y</c> are
+ 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
+ <c>Number</c>, <c>ShoeSize</c>, <c>Age</c> etc.</p>
+ </section>
+
+ <section>
+ <title>Atoms</title>
+ <p>Atoms are another data type in Erlang. Atoms start with a small
+ letter ((see the chapter
+ <seealso marker="doc/reference_manual:data_types">"Atom"</seealso>
+ in the Erlang Reference Manual)), for example: <c>charles</c>,
+ <c>centimeter</c>, <c>inch</c>. Atoms are simply names, nothing
+ else. They are not like variables which can have a value.</p>
+ <p>Enter the next program (file: <c>tut2.erl</c>) which could be
+ useful for converting from inches to centimeters and vice versa:</p>
+ <code type="none">
+-module(tut2).
+-export([convert/2]).
+
+convert(M, inch) ->
+ M / 2.54;
+
+convert(N, centimeter) ->
+ N * 2.54.</code>
+ <p>Compile and test:</p>
+ <pre>
+9> <input>c(tut2).</input>
+{ok,tut2}
+10> <input>tut2:convert(3, inch).</input>
+1.1811023622047243
+11> <input>tut2:convert(7, centimeter).</input>
+17.78</pre>
+ <p>Notice that I have introduced decimals (floating point numbers)
+ without any explanation, but I guess you can cope with that.</p>
+ <p>See what happens if I enter something other than centimeter or
+ inch in the convert function:</p>
+ <pre>
+12> <input>tut2:convert(3, miles).</input>
+** exception error: no function clause matching tut2:convert(3,miles)</pre>
+ <p>The two parts of the <c>convert</c> function are called its
+ clauses. Here we see that "miles" is not part of either of
+ the clauses. The Erlang system can't <em>match</em> either of
+ the clauses so we get an error message <c>function_clause</c>.
+ The shell formats the error message nicely, but the error tuple
+ is saved in the shell's history list and can be output by the shell
+ command <c>v/1</c>:</p>
+ <pre>
+13> <input>v(12).</input>
+{'EXIT',{function_clause,[{tut2,convert,[3,miles]},
+ {erl_eval,do_apply,5},
+ {shell,exprs,6},
+ {shell,eval_exprs,6},
+ {shell,eval_loop,3}]}}</pre>
+
+ </section>
+
+ <section>
+ <title>Tuples</title>
+ <p>Now the <c>tut2</c> program is hardly good programming style.
+ 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
+ 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>
+ <p>So we can write <c>{inch,3}</c> to denote 3 inches and
+ <c>{centimeter,5}</c> to denote 5 centimeters. Now let's write a
+ new program which converts centimeters to inches and vice versa.
+ (file <c>tut3.erl</c>).</p>
+ <code type="none">
+-module(tut3).
+-export([convert_length/1]).
+
+convert_length({centimeter, X}) ->
+ {inch, X / 2.54};
+convert_length({inch, Y}) ->
+ {centimeter, Y * 2.54}.</code>
+ <p>Compile and test:</p>
+ <pre>
+14> <input>c(tut3).</input>
+{ok,tut3}
+15> <input>tut3:convert_length({inch, 5}).</input>
+{centimeter,12.7}
+16> <input>tut3:convert_length(tut3:convert_length({inch, 5})).</input>
+{inch,5.0}</pre>
+ <p>Note on line 16 we convert 5 inches to centimeters and back
+ again and reassuringly get back to the original value. I.e
+ the argument to a function can be the result of another function.
+ Pause for a moment and consider how line 16 (above) works.
+ The argument we have given the function <c>{inch,5}</c> is first
+ matched against the first head clause of <c>convert_length</c>
+ i.e. <c>convert_length({centimeter,X})</c> where it can be seen
+ that <c>{centimeter,X}</c> does not match <c>{inch,5}</c>
+ (the head is the bit before the "-&gt;"). This having failed, we try
+ the head of the next clause i.e. <c>convert_length({inch,Y})</c>,
+ this matches and <c>Y</c> get the value 5.</p>
+ <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>
+ <code type="none">
+{moscow, {c, -10}}
+{cape_town, {f, 70}}
+{paris, {f, 28}}</code>
+ <p>Tuples have a fixed number of things in them. We call each thing
+ in a tuple an element. So in the tuple <c>{moscow,{c,-10}}</c>,
+ element 1 is <c>moscow</c> and element 2 is <c>{c,-10}</c>. I
+ have chosen <c>c</c> meaning Centigrade (or Celsius) and <c>f</c>
+ meaning Fahrenheit.</p>
+ </section>
+
+ <section>
+ <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
+ in the world could be:</p>
+ <code type="none">
+[{moscow, {c, -10}}, {cape_town, {f, 70}}, {stockholm, {c, -4}},
+ {paris, {f, 28}}, {london, {f, 36}}]</code>
+ <p>Note that this list was so long that it didn't fit on one line.
+ This doesn't matter, Erlang allows line breaks at all "sensible
+ places" but not, for example, in the middle of atoms, integers
+ etc.</p>
+ <p>A very useful way of looking at parts of lists, is by using "|".
+ This is best explained by an example using the shell.</p>
+ <pre>
+17> <input>[First |TheRest] = [1,2,3,4,5].</input>
+[1,2,3,4,5]
+18> <input>First.</input>
+1
+19> <input>TheRest.</input>
+[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>
+ <p>Another example:</p>
+ <pre>
+20> <input>[E1, E2 | R] = [1,2,3,4,5,6,7].</input>
+[1,2,3,4,5,6,7]
+21> <input>E1.</input>
+1
+22> <input>E2.</input>
+2
+23> <input>R.</input>
+[3,4,5,6,7]</pre>
+ <p>Here we see the use of | to get the first two elements from
+ the list. Of course if we try to get more elements from the list
+ than there are elements in the list we will get an error. Note
+ also the special case of the list with no elements [].</p>
+ <pre>
+24> <input>[A, B | C] = [1, 2].</input>
+[1,2]
+25> <input>A.</input>
+1
+26> <input>B.</input>
+2
+27> <input>C.</input>
+[]</pre>
+ <p>In all the examples above, I have been using new variable names,
+ not reusing the old ones: <c>First</c>, <c>TheRest</c>, <c>E1</c>,
+ <c>E2</c>, <c>R</c>, <c>A</c>, <c>B</c>, <c>C</c>. The reason
+ for this is that a variable can only be given a value once in its
+ context (scope). I'll get back to this later, it isn't so
+ peculiar as it sounds!</p>
+ <p>The following example shows how we find the length of a list:</p>
+ <code type="none">
+-module(tut4).
+
+-export([list_length/1]).
+
+list_length([]) ->
+ 0;
+list_length([First | Rest]) ->
+ 1 + list_length(Rest).</code>
+ <p>Compile (file <c>tut4.erl</c>) and test:</p>
+ <pre>
+28> <input>c(tut4).</input>
+{ok,tut4}
+29> <input>tut4:list_length([1,2,3,4,5,6,7]).</input>
+7</pre>
+ <p>Explanation:</p>
+ <code type="none">
+list_length([]) ->
+ 0;</code>
+ <p>The length of an empty list is obviously 0.</p>
+ <code type="none">
+list_length([First | Rest]) ->
+ 1 + list_length(Rest).</code>
+ <p>The length of a list with the first element <c>First</c> and
+ 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>
+ <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
+ use linked lists in other languages).</p>
+ <p>Erlang does not have a string date type, instead strings can be
+ represented by lists of ASCII characters. So the list
+ <c>[97,98,99]</c> is equivalent to "abc". The Erlang shell is
+ "clever" and guesses the what sort of list we mean and outputs it
+ in what it thinks is the most appropriate form, for example:</p>
+ <pre>
+30> <input>[97,98,99].</input>
+"abc"</pre>
+ </section>
+
+ <section>
+ <title>Standard Modules and Manual Pages</title>
+ <p>Erlang has a lot of standard modules to help you do things. For
+ example, the module <c>io</c> contains a lot of functions to help
+ you do formatted input/output. To look up information about
+ standard modules, the command <c>erl -man</c> can be used at
+ the operating shell or command prompt (i.e. at the same place as
+ that where you started <c>erl</c>). Try the operating system
+ shell command:</p>
+ <pre>
+% <input>erl -man io</input>
+ERLANG MODULE DEFINITION io(3)
+
+MODULE
+ io - Standard I/O Server Interface Functions
+
+DESCRIPTION
+ This module provides an interface to standard Erlang IO
+ servers. The output functions all return ok if they are suc-
+ ...</pre>
+ <p>If this doesn't work on your system, the documentation is
+ included as HTML in the Erlang/OTP release, or you can read
+ the documentation as HTML or download it as PDF from either of
+ the sites www.erlang.se (commercial Erlang) or www.erlang.org
+ (open source), for example for release R9B:</p>
+ <code type="none">
+http://www.erlang.org/doc/r9b/doc/index.html</code>
+ </section>
+
+ <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>
+ <pre>
+31> <input>io:format("hello world~n", []).</input>
+hello world
+ok
+32> <input>io:format("this outputs one Erlang term: ~w~n", [hello]).</input>
+this outputs one Erlang term: hello
+ok
+33> <input>io:format("this outputs two Erlang terms: ~w~w~n", [hello, world]).</input>
+this outputs two Erlang terms: helloworld
+ok
+34> <input>io:format("this outputs two Erlang terms: ~w ~w~n", [hello, world]).</input>
+this outputs two Erlang terms: hello world
+ok</pre>
+ <p>The function <c>format/2</c> (i.e. <c>format</c> with two
+ arguments) takes two lists. The first one is nearly always a list
+ written between " ". This list is printed out as it stands,
+ except that each ~w is replaced by a term taken in order from
+ the second list. Each ~n is replaced by a new line.
+ The <c>io:format/2</c> function itself returns the atom <c>ok</c>
+ if everything goes as planned. Like other functions in Erlang, it
+ crashes if an error occurs. This is not a fault in Erlang, it is
+ a deliberate policy. Erlang has sophisticated mechanisms to
+ handle errors which we will show later. As an exercise, try to
+ make <c>io:format</c> crash, it shouldn't be difficult. But
+ notice that although <c>io:format</c> crashes, the Erlang shell
+ itself does not crash.</p>
+ </section>
+
+ <section>
+ <title>A Larger Example</title>
+ <p>Now for a larger example to consolidate what we have learnt so
+ far. Assume we have a list of temperature readings from a number
+ of cities in the world. Some of them are in Celsius (Centigrade)
+ and some in Fahrenheit (as in the previous list). First let's
+ convert them all to Celsius, then let's print out the data neatly.</p>
+ <code type="none">
+%% This module is in file tut5.erl
+
+-module(tut5).
+-export([format_temps/1]).
+
+%% Only this function is exported
+format_temps([])-> % No output for an empty list
+ ok;
+format_temps([City | Rest]) ->
+ print_temp(convert_to_celsius(City)),
+ format_temps(Rest).
+
+convert_to_celsius({Name, {c, Temp}}) -> % No conversion needed
+ {Name, {c, Temp}};
+convert_to_celsius({Name, {f, Temp}}) -> % Do the conversion
+ {Name, {c, (Temp - 32) * 5 / 9}}.
+
+print_temp({Name, {c, Temp}}) ->
+ io:format("~-15w ~w c~n", [Name, Temp]).</code>
+ <pre>
+35> <input>c(tut5).</input>
+{ok,tut5}
+36> <input>tut5:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+moscow -10 c
+cape_town 21.11111111111111 c
+stockholm -4 c
+paris -2.2222222222222223 c
+london 2.2222222222222223 c
+ok</pre>
+ <p>Before we look at how this program works, notice that we have
+ added a few comments to the code. A comment starts with a %
+ character and goes on to the end of the line. Note as well that
+ the <c>-export([format_temps/1]).</c> line only includes
+ the function <c>format_temps/1</c>, the other functions are
+ <em>local</em> functions, i.e. they are not visible from outside
+ the module <c>tut5</c>.</p>
+ <p>Note as well that when testing the program from the shell, I had
+ to spread the input over two lines as the line was too long.</p>
+ <p>When we call <c>format_temps</c> the first time, <c>City</c>
+ gets the value <c>{moscow,{c,-10}}</c> and <c>Rest</c> is
+ the rest of the list. So we call the function
+ <c>print_temp(convert_to_celsius({moscow,{c,-10}}))</c>.</p>
+ <p>Here we see a function call as
+ <c>convert_to_celsius({moscow,{c,-10}})</c> as the argument to
+ the function <c>print_temp</c>. When we <em>nest</em> function
+ calls like this we execute (evaluate) them from the inside out.
+ I.e. we first evaluate <c>convert_to_celsius({moscow,{c,-10}})</c>
+ which gives the value <c>{moscow,{c,-10}}</c> as the temperature
+ is already in Celsius and then we evaluate
+ <c>print_temp({moscow,{c,-10}})</c>. The function
+ <c>convert_to_celsius</c> works in a similar way to
+ the <c>convert_length</c> function in the previous example.</p>
+ <p><c>print_temp</c> simply calls <c>io:format</c> in a similar way
+ to what has been described above. Note that ~-15w says to print
+ the "term" with a field length (width) of 15 and left justify it.
+ (<seealso marker="stdlib:io#fwrite/1">io(3)</seealso>).</p>
+ <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
+ 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. [],
+ which causes the first clause <c>format_temps([])</c> to match.
+ This simply returns (results in) the atom <c>ok</c>, so
+ the program ends.</p>
+ </section>
+
+ <section>
+ <title>Matching, Guards and Scope of Variables</title>
+ <p>It could be useful to find the maximum and minimum temperature
+ in lists like this. Before extending the program to do this,
+ let's look at functions for finding the maximum value of
+ the elements in a list:</p>
+ <code type="none">
+-module(tut6).
+-export([list_max/1]).
+
+list_max([Head|Rest]) ->
+ list_max(Rest, Head).
+
+list_max([], Res) ->
+ Res;
+list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
+ list_max(Rest, Head);
+list_max([Head|Rest], Result_so_far) ->
+ list_max(Rest, Result_so_far).</code>
+ <pre>
+37> <input>c(tut6).</input>
+{ok,tut6}
+38> <input>tut6:list_max([1,2,3,4,5,7,4,3,2,1]).</input>
+7</pre>
+ <p>First note that we have two functions here with the same name
+ <c>list_max</c>. However each of these takes a different number
+ of arguments (parameters). In Erlang these are regarded as
+ completely different functions. Where we need to distinguish
+ between these functions we write <c>name/arity</c>, where
+ <c>name</c> is the name of the function and <c>arity</c> is
+ the number of arguments, in this case <c>list_max/1</c> and
+ <c>list_max/2</c>.</p>
+ <p>This is an example where we walk through a list "carrying" a
+ value with us, in this case <c>Result_so_far</c>.
+ <c>list_max/1</c> simply assumes that the max value of the list
+ is the head of the list and calls <c>list_max/2</c> with the rest
+ of the list and the value of the head of the list, in the above
+ this would be <c>list_max([2,3,4,5,7,4,3,2,1],1)</c>. If we tried
+ to use <c>list_max/1</c> with an empty list or tried to use it
+ with something which isn't a list at all, we would cause an error.
+ Note that the Erlang philosophy is not to handle errors of this
+ type in the function they occur, but to do so elsewhere. More
+ about this later.</p>
+ <p>In <c>list_max/2</c> we walk down the list and use <c>Head</c>
+ instead of <c>Result_so_far</c> when <c>Head</c> &gt;
+ <c>Result_so_far</c>. <c>when</c> is a special word we use before
+ the -&gt; in the function to say that we should only use this part
+ of the function if the test which follows is true. We call tests
+ of this type a <em>guard</em>. If the guard isn't true (we say
+ the guard fails), we try the next part of the function. In this
+ case if <c>Head</c> isn't greater than <c>Result_so_far</c> then
+ it must be smaller or equal to is, so we don't need a guard on
+ the next part of the function.</p>
+ <p>Some useful operators in guards are, &lt; less than, &gt;
+ greater than, == equal, &gt;= greater or equal, =&lt; less or
+ 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 &lt; instead of &gt;. (But it would be wise to change
+ 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
+ OK since every time we call <c>list_max/2</c> we create a new
+ scope and one can regard the <c>Result_so_far</c> as a completely
+ different variable in each scope.</p>
+ <p>Another way of creating and giving a variable a value is by using
+ the match operator = . So if I write <c>M = 5</c>, a variable
+ called <c>M</c> will be created and given the value 5. If, in
+ the same scope I then write <c>M = 6</c>, I'll get an error. Try
+ this out in the shell:</p>
+ <pre>
+39> <input>M = 5.</input>
+5
+40> <input>M = 6.</input>
+** exception error: no match of right hand side value 6
+41> <input>M = M + 1.</input>
+** exception error: no match of right hand side value 6
+42> <input>N = M + 1.</input>
+6</pre>
+ <p>The use of the match operator is particularly useful for pulling
+ apart Erlang terms and creating new ones.</p>
+ <pre>
+43> <input>{X, Y} = {paris, {f, 28}}.</input>
+{paris,{f,28}}
+44> <input>X.</input>
+paris
+45> <input>Y.</input>
+{f,28}</pre>
+ <p>Here we see that <c>X</c> gets the value <c>paris</c> and
+ <c>Y</c><c>{f,28}</c>.</p>
+ <p>Of course if we try to do the same again with another city, we
+ get an error:</p>
+ <pre>
+46> <input>{X, Y} = {london, {f, 36}}.</input>
+** exception error: no match of right hand side value {london,{f,36}}</pre>
+ <p>Variables can also be used to improve the readability of
+ programs, for example, in the <c>list_max/2</c> function above,
+ we could write:</p>
+ <code type="none">
+list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
+ New_result_far = Head,
+ list_max(Rest, New_result_far);</code>
+ <p>which is possibly a little clearer.</p>
+ </section>
+
+ <section>
+ <title>More About Lists</title>
+ <p>Remember that the | operator can be used to get the head of a
+ list:</p>
+ <pre>
+47> <input>[M1|T1] = [paris, london, rome].</input>
+[paris,london,rome]
+48> <input>M1.</input>
+paris
+49> <input>T1.</input>
+[london,rome]</pre>
+ <p>The | operator can also be used to add a head to a list:</p>
+ <pre>
+50> <input>L1 = [madrid | T1].</input>
+[madrid,london,rome]
+51> <input>L1.</input>
+[madrid,london,rome]</pre>
+ <p>Now an example of this when working with lists - reversing
+ the order of a list:</p>
+ <code type="none">
+-module(tut8).
+
+-export([reverse/1]).
+
+reverse(List) ->
+ reverse(List, []).
+
+reverse([Head | Rest], Reversed_List) ->
+ reverse(Rest, [Head | Reversed_List]);
+reverse([], Reversed_List) ->
+ Reversed_List.</code>
+ <pre>
+52> <input>c(tut8).</input>
+{ok,tut8}
+53> <input>tut8:reverse([1,2,3]).</input>
+[3,2,1]</pre>
+ <p>Consider how <c>Reversed_List</c> is built. It starts as [], we
+ then successively take off the heads of the list to be reversed
+ and add them to the the <c>Reversed_List</c>, as shown in
+ the following:</p>
+ <code type="none">
+reverse([1|2,3], []) =>
+ reverse([2,3], [1|[]])
+
+reverse([2|3], [1]) =>
+ reverse([3], [2|[1])
+
+reverse([3|[]], [2,1]) =>
+ reverse([], [3|[2,1]])
+
+reverse([], [3,2,1]) =>
+ [3,2,1]</code>
+ <p>The module <c>lists</c> contains a lot of functions for
+ manipulating lists, for example for reversing them, so before you
+ 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
+ structured approach this time. First let's convert the whole list
+ to Celsius as follows and test the function:</p>
+ <code type="none">
+-module(tut7).
+-export([format_temps/1]).
+
+format_temps(List_of_cities) ->
+ convert_list_to_c(List_of_cities).
+
+convert_list_to_c([{Name, {f, F}} | Rest]) ->
+ Converted_City = {Name, {c, (F -32)* 5 / 9}},
+ [Converted_City | convert_list_to_c(Rest)];
+
+convert_list_to_c([City | Rest]) ->
+ [City | convert_list_to_c(Rest)];
+
+convert_list_to_c([]) ->
+ [].</code>
+ <pre>
+54> <input>c(tut7).</input>
+{ok, tut7}.
+55> <input>tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+[{moscow,{c,-10}},
+ {cape_town,{c,21.11111111111111}},
+ {stockholm,{c,-4}},
+ {paris,{c,-2.2222222222222223}},
+ {london,{c,2.2222222222222223}}]</pre>
+ <p>Looking at this bit by bit:</p>
+ <code type="none">
+format_temps(List_of_cities) ->
+ convert_list_to_c(List_of_cities).</code>
+ <p>Here we see that <c>format_temps/1</c> calls
+ <c>convert_list_to_c/1</c>. <c>convert_list_to_c/1</c> takes off
+ the head of the <c>List_of_cities</c>, converts it to Celsius if
+ needed. The | operator is used to add the (maybe) converted
+ to the converted rest of the list:</p>
+ <code type="none">
+[Converted_City | convert_list_to_c(Rest)];</code>
+ <p>or</p>
+ <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>
+ <code type="none">
+convert_list_to_c([]) ->
+ [].</code>
+ <p>Now we have converted the list, we add a function to print it:</p>
+ <code type="none">
+-module(tut7).
+-export([format_temps/1]).
+
+format_temps(List_of_cities) ->
+ Converted_List = convert_list_to_c(List_of_cities),
+ print_temp(Converted_List).
+
+convert_list_to_c([{Name, {f, F}} | Rest]) ->
+ Converted_City = {Name, {c, (F -32)* 5 / 9}},
+ [Converted_City | convert_list_to_c(Rest)];
+
+convert_list_to_c([City | Rest]) ->
+ [City | convert_list_to_c(Rest)];
+
+convert_list_to_c([]) ->
+ [].
+
+print_temp([{Name, {c, Temp}} | Rest]) ->
+ io:format("~-15w ~w c~n", [Name, Temp]),
+ print_temp(Rest);
+print_temp([]) ->
+ ok.</code>
+ <pre>
+56> <input>c(tut7).</input>
+{ok,tut7}
+57> <input>tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+moscow -10 c
+cape_town 21.11111111111111 c
+stockholm -4 c
+paris -2.2222222222222223 c
+london 2.2222222222222223 c
+ok</pre>
+ <p>We now have to add a function to find the cities with
+ the maximum and minimum temperatures. The program below isn't
+ the most efficient way of doing this as we walk through the list
+ of cities four times. But it is better to first strive for
+ clarity and correctness and to make programs efficient only if
+ really needed.</p>
+ <code type="none"><![CDATA[
+-module(tut7).
+-export([format_temps/1]).
+
+format_temps(List_of_cities) ->
+ Converted_List = convert_list_to_c(List_of_cities),
+ print_temp(Converted_List),
+ {Max_city, Min_city} = find_max_and_min(Converted_List),
+ print_max_and_min(Max_city, Min_city).
+
+convert_list_to_c([{Name, {f, Temp}} | Rest]) ->
+ Converted_City = {Name, {c, (Temp -32)* 5 / 9}},
+ [Converted_City | convert_list_to_c(Rest)];
+
+convert_list_to_c([City | Rest]) ->
+ [City | convert_list_to_c(Rest)];
+
+convert_list_to_c([]) ->
+ [].
+
+print_temp([{Name, {c, Temp}} | Rest]) ->
+ io:format("~-15w ~w c~n", [Name, Temp]),
+ print_temp(Rest);
+print_temp([]) ->
+ ok.
+
+find_max_and_min([City | Rest]) ->
+ find_max_and_min(Rest, City, City).
+
+find_max_and_min([{Name, {c, Temp}} | Rest],
+ {Max_Name, {c, Max_Temp}},
+ {Min_Name, {c, Min_Temp}}) ->
+ if
+ Temp > Max_Temp ->
+ Max_City = {Name, {c, Temp}}; % Change
+ true ->
+ Max_City = {Max_Name, {c, Max_Temp}} % Unchanged
+ end,
+ if
+ Temp < Min_Temp ->
+ Min_City = {Name, {c, Temp}}; % Change
+ true ->
+ Min_City = {Min_Name, {c, Min_Temp}} % Unchanged
+ end,
+ find_max_and_min(Rest, Max_City, Min_City);
+
+find_max_and_min([], Max_City, Min_City) ->
+ {Max_City, Min_City}.
+
+print_max_and_min({Max_name, {c, Max_temp}}, {Min_name, {c, Min_temp}}) ->
+ io:format("Max temperature was ~w c in ~w~n", [Max_temp, Max_name]),
+ io:format("Min temperature was ~w c in ~w~n", [Min_temp, Min_name]).]]></code><pre>
+58> <input>c(tut7).</input>
+{ok, tut7}
+59> <input>tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+moscow -10 c
+cape_town 21.11111111111111 c
+stockholm -4 c
+paris -2.2222222222222223 c
+london 2.2222222222222223 c
+Max temperature was 21.11111111111111 c in cape_town
+Min temperature was -10 c in moscow
+ok</pre>
+ </section>
+
+ <section>
+ <title>If and Case</title>
+ <p>The function <c>find_max_and_min</c> works out the maximum and
+ minimum temperature. We have introduced a new construct here
+ <c>if</c>. If works as follows:</p>
+ <code type="none">
+if
+ Condition 1 ->
+ Action 1;
+ Condition 2 ->
+ Action 2;
+ Condition 3 ->
+ Action 3;
+ Condition 4 ->
+ Action 4
+end</code>
+ <p>Note there is no ";" before <c>end</c>! Conditions are the same
+ as guards, tests which succeed or fail. Erlang starts at the top
+ until it finds a condition which succeeds and then it evaluates
+ (performs) the action following the condition and ignores all
+ other conditions and action before the <c>end</c>. If no
+ condition matches, there will be a run-time failure. A condition
+ which always is succeeds is the atom, <c>true</c> and this is
+ often used last in an <c>if</c> meaning do the action following
+ the <c>true</c> if all other conditions have failed.</p>
+ <p>The following is a short program to show the workings of
+ <c>if</c>.</p>
+ <code type="none">
+-module(tut9).
+-export([test_if/2]).
+
+test_if(A, B) ->
+ if
+ A == 5 ->
+ io:format("A == 5~n", []),
+ a_equals_5;
+ B == 6 ->
+ io:format("B == 6~n", []),
+ b_equals_6;
+ A == 2, B == 3 -> %i.e. A equals 2 and B equals 3
+ io:format("A == 2, B == 3~n", []),
+ a_equals_2_b_equals_3;
+ A == 1 ; B == 7 -> %i.e. A equals 1 or B equals 7
+ io:format("A == 1 ; B == 7~n", []),
+ a_equals_1_or_b_equals_7
+ end.</code>
+ <p>Testing this program gives:</p>
+ <pre>
+60> <input>c(tut9).</input>
+{ok,tut9}
+61> <input>tut9:test_if(5,33).</input>
+A == 5
+a_equals_5
+62> <input>tut9:test_if(33,6).</input>
+B == 6
+b_equals_6
+63> <input>tut9:test_if(2, 3).</input>
+A == 2, B == 3
+a_equals_2_b_equals_3
+64> <input>tut9:test_if(1, 33).</input>
+A == 1 ; B == 7
+a_equals_1_or_b_equals_7
+65> <input>tut9:test_if(33, 7).</input>
+A == 1 ; B == 7
+a_equals_1_or_b_equals_7
+66> <input>tut9:test_if(33, 33).</input>
+** exception error: no true branch found when evaluating an if expression
+ in function tut9:test_if/2</pre>
+ <p>Notice that <c>tut9:test_if(33,33)</c> did not cause any
+ condition to succeed so we got the run time error
+ <c>if_clause</c>, here nicely formatted by the shell. See the chapter
+ <seealso marker="doc/reference_manual:expressions">"Guard Sequences"</seealso> in the Erlang Reference Manual for details
+ of the many guard tests available. <c>case</c> is another
+ construct in Erlang. Recall that we wrote the
+ <c>convert_length</c> function as:</p>
+ <code type="none">
+convert_length({centimeter, X}) ->
+ {inch, X / 2.54};
+convert_length({inch, Y}) ->
+ {centimeter, Y * 2.54}.</code>
+ <p>We could also write the same program as:</p>
+ <code type="none">
+-module(tut10).
+-export([convert_length/1]).
+
+convert_length(Length) ->
+ case Length of
+ {centimeter, X} ->
+ {inch, X / 2.54};
+ {inch, Y} ->
+ {centimeter, Y * 2.54}
+ end.</code>
+ <pre>
+67> <input>c(tut10).</input>
+{ok,tut10}
+68> <input>tut10:convert_length({inch, 6}).</input>
+{centimeter,15.24}
+69> <input>tut10:convert_length({centimeter, 2.5}).</input>
+{inch,0.984251968503937}</pre>
+ <p>Notice that both <c>case</c> and <c>if</c> have <em>return values</em>, i.e. in the above example <c>case</c> returned
+ either <c>{inch,X/2.54}</c> or <c>{centimeter,Y*2.54}</c>.
+ The behaviour of <c>case</c> can also be modified by using guards.
+ An example should hopefully clarify this. The following example
+ tells us the length of a month, given the year. We need to know
+ the year of course, since February has 29 days in a leap year.</p>
+ <code type="none">
+-module(tut11).
+-export([month_length/2]).
+
+month_length(Year, Month) ->
+ %% All years divisible by 400 are leap
+ %% Years divisible by 100 are not leap (except the 400 rule above)
+ %% Years divisible by 4 are leap (except the 100 rule above)
+ Leap = if
+ trunc(Year / 400) * 400 == Year ->
+ leap;
+ trunc(Year / 100) * 100 == Year ->
+ not_leap;
+ trunc(Year / 4) * 4 == Year ->
+ leap;
+ true ->
+ not_leap
+ end,
+ case Month of
+ sep -> 30;
+ apr -> 30;
+ jun -> 30;
+ nov -> 30;
+ feb when Leap == leap -> 29;
+ feb -> 28;
+ jan -> 31;
+ mar -> 31;
+ may -> 31;
+ jul -> 31;
+ aug -> 31;
+ oct -> 31;
+ dec -> 31
+ end.</code>
+ <pre>
+70> <input>c(tut11).</input>
+{ok,tut11}
+71> <input>tut11:month_length(2004, feb).</input>
+29
+72> <input>tut11:month_length(2003, feb).</input>
+28
+73> <input>tut11:month_length(1947, aug).</input>
+31</pre>
+ </section>
+
+ <section>
+ <title>Built In Functions (BIFs)</title>
+ <p>Built in functions BIFs are functions which for some reason is
+ built in to the Erlang virtual machine. BIFs often implement
+ functionality that is impossible to implement in Erlang or is to
+ 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>
+ <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
+ <c>trunc</c> (more later) to cut off any decimals. We then
+ multiply by 400 again and see if we get back the same value. For
+ example, year 2004:</p>
+ <code type="none">
+2004 / 400 = 5.01
+trunc(5.01) = 5
+5 * 400 = 2000</code>
+ <p>and we can see that we got back 2000 which is not the same as
+ 2004, so 2004 isn't divisible by 400. Year 2000:</p>
+ <code type="none">
+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
+ 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
+ after division. For example:</p>
+ <pre>
+74> <input>2004 rem 400.</input>
+4</pre>
+ <p>so instead of writing</p>
+ <code type="none">
+trunc(Year / 400) * 400 == Year ->
+ leap;</code>
+ <p>we could write</p>
+ <code type="none">
+Year rem 400 == 0 ->
+ leap;</code>
+ <p>There are many other built in functions (BIF) such as
+ <c>trunc</c>. Only a few built in functions can be used in guards,
+ and you cannot use functions you have defined yourself in guards.
+ (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>
+ <pre>
+75> <input>trunc(5.6).</input>
+5
+76> <input>round(5.6).</input>
+6
+77> <input>length([a,b,c,d]).</input>
+4
+78> <input>float(5).</input>
+5.0
+79> <input>is_atom(hello).</input>
+true
+80> <input>is_atom("hello").</input>
+false
+81> <input>is_tuple({paris, {c, 30}}).</input>
+true
+82> <input>is_tuple([paris, {c, 30}]).</input>
+false</pre>
+ <p>All the above can be used in guards. Now for some which can't be
+ used in guards:</p>
+ <pre>
+83> <input>atom_to_list(hello).</input>
+"hello"
+84> <input>list_to_atom("goodbye").</input>
+goodbye
+85> <input>integer_to_list(22).</input>
+"22"</pre>
+ <p>The 3 BIFs above do conversions which would be difficult (or
+ impossible) to do in Erlang.</p>
+ </section>
+
+ <section>
+ <title>Higher Order Functions (Funs)</title>
+ <p>Erlang, like most modern functional programming languages, has
+ higher order functions. We start with an example using the shell:</p>
+ <pre>
+86> <input>Xf = fun(X) -> X * 2 end.</input>
+#Fun&lt;erl_eval.5.123085357&gt;
+87> <input>Xf(5).</input>
+10</pre>
+ <p>What we have done here is to define a function which doubles
+ the value of number and assign this function to a variable. Thus
+ <c>Xf(5)</c> returned the value 10. Two useful functions when
+ working with lists are <c>foreach</c> and <c>map</c>, which are
+ defined as follows:</p>
+ <code type="none">
+foreach(Fun, [First|Rest]) ->
+ Fun(First),
+ foreach(Fun, Rest);
+foreach(Fun, []) ->
+ ok.
+
+map(Fun, [First|Rest]) ->
+ [Fun(First)|map(Fun,Rest)];
+map(Fun, []) ->
+ [].</code>
+ <p>These two functions are provided in the standard module
+ <c>lists</c>. <c>foreach</c> takes a list and applies a fun to
+ every element in the list, <c>map</c> creates a new list by
+ applying a fun to every element in a list. Going back to
+ the shell, we start by using <c>map</c> and a fun to add 3 to
+ every element of a list:</p>
+ <pre>
+88> <input>Add_3 = fun(X) -> X + 3 end.</input>
+#Fun&lt;erl_eval.5.123085357&gt;
+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
+ again):</p>
+ <pre>
+90> <input>Print_City = fun({City, {X, Temp}}) -> io:format("~-15w ~w ~w~n",</input>
+<input>[City, X, Temp]) end.</input>
+#Fun&lt;erl_eval.5.123085357&gt;
+91> <input>lists:foreach(Print_City, [{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+moscow c -10
+cape_town f 70
+stockholm c -4
+paris f 28
+london f 36
+ok</pre>
+ <p>We will now define a fun which can be used to go through a list
+ of cities and temperatures and transform them all to Celsius.</p>
+ <code type="none">
+-module(tut13).
+
+-export([convert_list_to_c/1]).
+
+convert_to_c({Name, {f, Temp}}) ->
+ {Name, {c, trunc((Temp - 32) * 5 / 9)}};
+convert_to_c({Name, {c, Temp}}) ->
+ {Name, {c, Temp}}.
+
+convert_list_to_c(List) ->
+ lists:map(fun convert_to_c/1, List).</code>
+ <pre>
+92> <input>tut13:convert_list_to_c([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+[{moscow,{c,-10}},
+ {cape_town,{c,21}},
+ {stockholm,{c,-4}},
+ {paris,{c,-2}},
+ {london,{c,2}}]</pre>
+ <p>The <c>convert_to_c</c> function is the same as before, but we
+ use it as a fun:</p>
+ <code type="none">
+lists:map(fun convert_to_c/1, List)</code>
+ <p>When we use a function defined elsewhere as a fun we can refer
+ to it as <c>Function/Arity</c> (remember that <c>Arity</c> =
+ number of arguments). So in the <c>map</c> call we write
+ <c>lists:map(fun convert_to_c/1, List)</c>. As you can see
+ <c>convert_list_to_c</c> becomes much shorter and easier to
+ understand.</p>
+ <p>The standard module <c>lists</c> also contains a function
+ <c>sort(Fun, List)</c> where <c>Fun</c> is a fun with two
+ arguments. This fun should return <c>true</c> if the the first
+ argument is less than the second argument, or else <c>false</c>.
+ We add sorting to the <c>convert_list_to_c</c>:</p>
+ <code type="none"><![CDATA[
+-module(tut13).
+
+-export([convert_list_to_c/1]).
+
+convert_to_c({Name, {f, Temp}}) ->
+ {Name, {c, trunc((Temp - 32) * 5 / 9)}};
+convert_to_c({Name, {c, Temp}}) ->
+ {Name, {c, Temp}}.
+
+convert_list_to_c(List) ->
+ New_list = lists:map(fun convert_to_c/1, List),
+ lists:sort(fun({_, {c, Temp1}}, {_, {c, Temp2}}) ->
+ Temp1 < Temp2 end, New_list).]]></code>
+ <pre>
+93> <input>c(tut13).</input>
+{ok,tut13}
+94> <input>tut13:convert_list_to_c([{moscow, {c, -10}}, {cape_town, {f, 70}},</input>
+<input>{stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).</input>
+[{moscow,{c,-10}},
+ {stockholm,{c,-4}},
+ {paris,{c,-2}},
+ {london,{c,2}},
+ {cape_town,{c,21}}]</pre>
+ <p>In <c>sort</c> we use the fun:</p>
+ <code type="none"><![CDATA[
+fun({_, {c, Temp1}}, {_, {c, Temp2}}) -> Temp1 < Temp2 end,]]></code>
+ <p>Here we introduce the concept of an <em>anonymous variable</em>
+ "_". This is simply shorthand for a variable which is going to
+ get a value, but we will ignore the value. This can be used
+ anywhere suitable, not just in fun's. <c><![CDATA[Temp1 < Temp2]]></c>
+ returns <c>true</c> if <c>Temp1</c> is less than <c>Temp2</c>.</p>
+ </section>
+</chapter>
+