Errata

Erlang Programming

Errata for Erlang Programming

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
vidi
9.2.2

"A function that takes a fun as an argument is called a higher-order function."

should be either

"A function that takes a fun as an argument OR RETURNS A FUN is called a higher-order function."

(Erlang specific) or

"A function that takes a funCTION as an argument OR RETURNS A FUNCTION is called a higher-order function."

(general).

Note from the Author or Editor:
That's right. Should read "A function that takes a function as an argument or returns a function as result is called a higher-order function."

Marc van Woerkom  Aug 18, 2009 
Other Digital Version
example files
header

It seems that all the example files downloaded
for this book contain Francesco's name spelled wrong:

%% Francecso Cesarini and Simon Thompson
^^^^^^^^^

F Fernandes  Aug 31, 2009 
1
1.3.1

You write:

"Another aspect of Erlang is that functions (or closures) are first-class data. They can be bound to a variable and can be treated just like any other data item: stored in a list, returned by a function, or communicated between processes."

Considering there is also distributed Erlang, I can easily send a string to a different node, but can I send a function over to another node of a cluster? If not, is it not a little bit less than first class?

BTW I found no page number within Safari, so I entered 1 to make this form happy

Note from the Author or Editor:
Good point! Yes, you can send closures between different Erlang nodes: the only thing that you need to be careful about is if your fun refers to any functions these need to accessible at the remote node. We talk about this in detail in Chapter 11.

Marc van Woerkom  Aug 15, 2009 
Printed
Page 1
page 237

implementation of delete_usr function is missing

Note from the Author or Editor:
Correct: could treat this as an exercise. What does deleting a user require to be removed?

Anonymous  Sep 16, 2009 
3.3.6
4th & 5th code block

4> io:format("the sum of ~w is ~w.~n", [[2,3,4],ioExs:sum([2,3,4])]).

should be:

4> io:format("the sum of ~w is ~w.~n", [[2,3,4],lists:sum([2,3,4])]).

*and*

sum of ~W is ~.2f.~n", [[2,3,math:pi()],3,ioExs:sum([2,3,math:pi()])]]}]).

should be:

sum of ~W is ~.2f.~n", [[2,3,math:pi()],3,lists:sum([2,3,math:pi()])]]}]).

psykoTRON  Aug 04, 2009 
PDF
Page 15
bottom paragraph

The second sentence: The base is an integer between 2 and 16, ...

It should be: The base is an integer between 2 and 36, ...

1> 36#zz.
1295
2> 37#zz.
* 1: illegal base '37'

Hynek Vychodil  Aug 14, 2009 
Printed
Page 19
2nd Paragraph

In the first paragraph of the "Atoms" section, erlang atoms are compared to "enums" in Ruby. However, I do not believe that Ruby has enums. I am an Erlang novice; however based on my experience working through the book's examples, Erlang atoms strike me as being very similar to Ruby *symbols*.

Note from the Author or Editor:
I am not a Ruby expert, but after reading this introduction to Ruby symbols, http://www.troubleshooters.com/codecorn/ruby/symbols.htm it's clear that they are not exactly the same as Erlang atoms. Probably the best thing here is to remove all comparisons to Ruby constructs.

Jason Smith  Aug 31, 2009 
Printed
Page 19
Last paragraph

Insert the sentence "Any atom containing a full stop will need to be quoted when typed in the Erlang shell." before the sentence "Pay special attention ..."

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
Printed
Page 20, 378
378: list "Boolean Operators" allowed in guards

I can not find a discussion of operator precedence in the Index. If the concept is called something else, I think it should also be indexed as "operator precedence" since erlang.org calls it that

http://www.erlang.org/doc/reference_manual/expressions.html#6.25

The example that I was looking at is the lower precedence of "andalso" vs. "and". It seems to be a common error (e.g. when they ran Dialyzer on Wrangler) that expressions connected by "and" are under-parenthesized and the fix is to use "andalso"

http://www.it.uu.se/research/group/hipe/dialyzer/publications/wrangler.pdf

Note from the Author or Editor:
Yes! Good idea. We should also say something about the order of precedence of the logical operators that appear in table 2-2 (pp 20-21) according to the reference http://www.erlang.org/doc/reference_manual/expressions.html#6.25

Gene Tani  Oct 17, 2009 
PDF
Page 26
2nd code block

1> [monday, tuesday, Wednesday].

There is accidentally upper case. It should be:

1> [monday, tuesday, wednesday].

Hynek Vychodil  Aug 15, 2009 
Printed
Page 35
Line numbered 10

Replace line numbered 10 by

10> {Elem, Elem, X} = {1,2,3}.

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
PDF
Page 36
bottom

3. pp36, Variable names, Name and Surname in command 15,
Since the command numbers are sequential, we should
naturally think that Erlang shell is used contiguously.
The variables "Name" and "Surname" are bound in command 12,
and no variable flush (f()) is called. So, In command 15,
"Name" and "Surname" can not freshly bound, but should be
match error.
The variable name in command 15 should be changed, or
command line should be re-initialized.

Note from the Author or Editor:
Suggestion:

change the next to last line on p36 to
15 {person, N, S} = Var.
ALSO
change line 3 of p37 to read
N being bound to the string "Francesco" and the variable S to "Cesarini".

NOTE that in this line the words
N, "Francesco", S, "Cesarini"
should all be in typewrite font

Francesco Cesarini
Francesco Cesarini
 
Apr 12, 2010 
Printed, PDF, , Other Digital Version
Page 36
bottom of page.

15 {person, Name, Surname} = Var.
should be:
15> {person, Name, Surname} = Var.

psykoTRON  Jul 19, 2010 
Printed
Page 41
2nd full paragraph

BEAM in fact stands for Bogdan's Erlang Abstract Machine, as it was devised by Bogumil (Bogdan) Hausman. In recent years Bjorn has taken on the implementation of the VM. Thanks to Bjarne Dacker for this correction.

Simon Thompson
Simon Thompson
 
Nov 21, 2009 
Printed
Page 44
Exercise 2.3

First paragraph of Exercise 2.3 says "Write a module boolean.erl..." while later references to the module say "bool:", not "boolean:"

Alexei Nekrassov  Aug 07, 2009 
PDF
Page 44
Exercise 2-3

"Write a module boolean.erl that takes logical expressions and ..."

It should be bool.erl because bool module name is assumed in following text. Otherwise fix following text to boolean module name.

Hynek Vychodil  Aug 16, 2009 
Printed
Page 46
2nd paragraph of The case Construct

The general case expression is illustrated in a wrong way. It should look like this:

case conditional-expression of
Pattern1 -> expression11, expression12, .. ;
Pattern2 -> expression21, expression22, .. ;
...
Patternn -> expressionn1, expressionn2, ..
end

Note: the current illustration in the book suggests as if the same expression1, expression2, ... should appear for all the Patternis. (What apparently makes no sense.)

Moreover there is a typo in the second line:
Pattern1 -> expression1, expression2, .. ;,
The ',' should be removed from the end.

P.Tury  Sep 08, 2009 
PDF
Page 46
case pattern

4. pp46, general case expression's form. TYPO
The extra comma at the end of first pattern (Pattern1)
should be deleted.

Note from the Author or Editor:
Already noted at the end of an earlier erratum entry, but this makes it a separate issue.

Anonymous  Apr 12, 2010 
PDF
Page 48
1st code block, second line

Code block contain guard expression and `when` keyword. The keyword has not been mentioned nor referenced in neighbor text. Guard section is just two pages ahead but it can be minor hitch for newcomers to language. (Example code would work well without guards even it would not be perfect.)

Note from the Author or Editor:
Yes; we should include forward reference to the section in a footnote. If it is confusing, it is possible to delete the "when N>0" from each of the three variants of the program and for these still to have the same meaning as each other.

Hynek Vychodil  Aug 16, 2009 
48
2nd to last paragraph

The line:
the clause?that is, Y+X, Y*X?whereas the scope of Y is the remainder of the body after

looks as though it should be:
the clause?that is, Y=X+1, Y*X?whereas the scope of Y is the remainder of the body after

to match the statement above it:
f(X) -> Y=X+1, Y*X.

Note from the Author or Editor:
Yes, that's right, because it would be possible to pattern match against X at this point.

psykoTRON  Jul 21, 2010 
PDF
Page 49
Last para - "The if Construct"

When explaining the 'if' construct, you illustrate the example with guard expressions numbered from 1..n and expressions numbered 1 to (unknown) - yet in the bottom line on that page you reuse the variable 'n' to illustrate that all expressions that match the 'Guard_i' expression will be executed. Under a strict reading, using conventional matrix math notation, one might interpret that to assume that only as many expressions will be evaluated as there are guard conditions (since the variable 'n' is reused). It'd be better to use the conventional "m x n" notation - i.e. Guard_1 .. Guard_m, and expression_1 .. expression_n.

Thanks.

Note from the Author or Editor:
change the last letter on the page from "n" to "m"

Anonymous  Sep 08, 2009 
Printed
Page 51
para -2

The guard(X,Y) example is somewhat in isolation, is not clarified or explained further. I assumed (wrongly), that I could use 'and' and 'or' constructs in a guard statement. The caveat in para -2 is clear, but does not list what is allowed, nor define 'user-defined' functions.
p52 describes (but no examples which would have helped me) the use of ", " and "; " for 'and' and 'or'.

http://www.erlang.org/doc/reference_manual/expressions.html#6.24 provides the definitive list which is quite restrictive and explicit.

For me this needed clarification. Others may find the same.

DaveP

Note from the Author or Editor:
The material earlier on page 51 provides a detailed list of what can be used in a guard expression, and this is illustrated in the guard(X,Y) function given at the foot of the page. It is apparent from this that "and", "or" and "not" can be used in guard expressions.

Page 52 discusses the use of ";" and "," and gives an example of their use by rewriting the guard(X,Y) (presented in the middle of p52)

Dave Pawson
 
Jul 24, 2009 
Printed
Page 51
Last but one paragraph

The name of the example 'guard' function is very confusing. Erlang newbies just want to understand here what are 'guards'. This naming here confuses them suggesting that guards are some functions (with the name 'guard'...!?)

Please rename that function. (For e.g. 'selective_add' or something.)

Note: current name doesn't make it impossible to understand what guards are, but makes it harder...

Note from the Author or Editor:
Yes, this is a very good suggestion - thanks for this.

So, should substitute "my_add" for "guard" in the last code example on p51 AND "my_add2" for "guard2" in the first code example on p52. In both cases it's a single substitution for a function name.

P.Tury  Sep 08, 2009 
Printed
Page 56
Last paragraph

Once it mentiones 'now/1' instead of 'now/0'.

P.Tury  Sep 08, 2009 
Printed, PDF, , Other Digital Version
Page 63
Tail-Recursive Functions, second code snippet

Missing closing parenthesis.

Note from the Author or Editor:
Yes, just to be clear,

sum([2,3,4] = 2 + sum([3,4])

should be replaced by

sum([2,3,4]) = 2 + sum([3,4])

Roberto Aloi  Aug 31, 2010 
Printed
Page 67
First sentence

'This helper function takes two accumulators, one used to store the sum
and the other to store the average.' --- the other accumulator in fact
stores the length, not the average. The rest of the text in that
section correctly refers to the 'length' accumulator.

Ben North  Jul 17, 2009 
Printed
Page 69
last code section (7-4 lines from the bottom)

The text refers to an error that can occur "when you match to retrieve parts of a result from a function call".
But the code shows different kind of scenario, not involving function calls.

Note from the Author or Editor:
Yes, the example code should be replaced by

1> lists:keysearch(1,1,[{1,2},{2,4}]).
{value,{1,2}}
2> lists:keysearch(3,1,[{1,2},{2,4}]).
false
3> {value,Tuple}=lists:keysearch(3,1,[{1,2},{2,4}]).
** exception error: no match of right hand side value false

Alexei Nekrassov  Aug 09, 2009 
Printed, PDF, , Other Digital Version
Page 71
upper code block

the upper try ... catch code block

try Exprs of
Pattern1 [when Guard1] ->
ExpressionBody1;
Pattern2 [when Guard2] ->
ExpressionBody2
catch
[Class1:]ExceptionPattern1
[when ExceptionGuardSeq1] ->
ExceptionBody1;
[ClassN:]ExceptionPatternN
[when ExceptionGuardSeqN] ->
ExceptionBodyN
end

should be as follows

try Exprs of
Pattern1 [when Guard1] ->
ExpressionBody1;
...
PatternN [when GuardN] ->
ExpressionBodyN
catch
[Class1:]ExceptionPattern1
[when ExceptionGuardSeq1] ->
ExceptionBody1;
...
[ClassM:]ExceptionPatternM
[when ExceptionGuardSeqM] ->
ExceptionBodyM
end

Simon Thompson
Simon Thompson
 
Jul 31, 2010 
PDF
Page 72
Three lines from bottom.

this line should read
-export([return_error/1,try_return/1,try_wildcard/1,try_return2/1]).

Simon Thompson
Simon Thompson
 
Jun 20, 2009 
Printed
Page 74
under "Using Catch" header

"Richard Carlson" should be: "Richard Carlsson"

Anonymous  Oct 30, 2009 
Printed
Page 81
3rd paragraph, 1st sentence

Extra "now": "Now that we are now..."

Note from the Author or Editor:
Yes! Let's say "Now that we are done with ...."

Alexei Nekrassov  Aug 09, 2009 
Printed
Page 82-83
Bottom of 82, top of 83

The second part of exercise 3-1 is confusing:

Write a function sum/2 which, given two integers N and M, where N =< M, will return the sum of the interval between N and M. Then the examples are:

sum(1,3) => 6.
sum(6,6) => 6.

How can the interval between 6 and 6 be 6? Am I not understanding the question or is this a typo?

Thanks
Nina

Note from the Author or Editor:
It would be clearer for us to say "return the sum of the integers in the interval from N to M, including the endpoints"

ninaj  Aug 05, 2009 
Printed
Page 84
exercise 3-5

Hint: you will have to use a help function" => "helper"

Note from the Author or Editor:
Also "helper" should not be in typewrite font (as "help" currently is).

Anonymous  Aug 31, 2009 
Printed
Page 90
Caution section at the bottom of the page

The caution warns that the arguments passed to the spawn function have to be a list, and compares two code sections as follows:

-------------------
"spawn(m, f, [a])"

Not

"not spawn(m, f, a)".
-------------------

The "not" in the second line of code should not be there. It should instead read as follows:

------------------
"spawn(m, f, [a])"

Not

"spawn(m, f, a)"
------------------

Lincoln Bryant  Jul 05, 2009 
Printed
Page 92
3rd paragraph from bottom

"Guarantee not extended to messages sent from different processes"...

This could be a little clearer.

"messages sent from multiple processes to a single receiver are not guaranteed to be received in the order sent"

Note from the Author or Editor:
OK, we should change the sentence "The guarantee is not ..." to

"However, messages sent from different processes to the same receiver are not guaranteed to be received in same order that they were sent, and in this case the ordering is VM-dependent."

Gene tani  Sep 05, 2009 
Printed
Page 98
1st paragraph; last sentence

"unbound variable DigitList in Figure 4-5" should refer to Figure 4-4

Note from the Author or Editor:
with the unbound variable DigitList in the same figure

Alexei Nekrassov  Aug 10, 2009 
Printed
Page 98

I think a diagram has gone astray from page 98. The fist para says,
"... contrast the bound variable Pid in figure 4-4 with the unbound
variable DigitList in figure 4-5, ..". There is a figure 4-5, but
it's not the one being referred to here.

Is there a missing figure, or could that be talking about the unbound
variable DigitList, also in figure 4-4? In which case that's a typo
in the text.

I think that's only the third typo I've come across so far (also p44:
boolean.erl for bool.erl; p58 unexplained ioExs), all fairly minor.
Three typos in a hundred pages is extremely impressive for a computer
book these days.

Best wishes

Ivan Uemlianin

[Posted to here from the google group by SImon Thompson]

Note from the Author or Editor:
Change the line
variable Pid in Figure 4-4 with the unbound variable DigitList in Figure 4-5, which
to
variable Pid in Figure 4-4 with the unbound variable DigitList in the same figure, which

Simon Thompson
Simon Thompson
 
Jan 20, 2010 
Printed
Page 106
first code segment

flush(),
db ! ...
receive
code should be atomic. Is it something that is taken care of automatically in Erlang? I think this deserves a footnote one way or another...

Note from the Author or Editor:
In a production example, this would be dealt with using OTP and references, and would then be handled atomically. We discuss OTP in Chapter 12 and the Mnesia database in Chapter 13.

Alexei Nekrassov  Aug 10, 2009 
Printed
Page 107
Last line of 'Benchmarking' section

Last line of 'Benchmarking' section should not be bold

Alexei Nekrassov  Aug 10, 2009 
Printed
Page 107
1st code example

Line 11 of the code example says:

NPid = spawn(?MODULE, start_proc, [Num-1, Pid]),

Macros like ?MODULE are not introduced until p. 166. Unless I've missed a mention of them before p. 107, it might be worth adding a note to the effect that this is a macro, or even rewriting the line as:

NPid = spawn(myring, start_proc, [Num-1, Pid]),

Best wishes

Ivan

Note from the Author or Editor:
Change line
NPid = spawn(?MODULE, start_proc, [Num-1, Pid]),
to
NPid = spawn(myring, start_proc, [Num-1, Pid]),

Ivan Uemlianin  Feb 23, 2010 
Printed
Page 114
'The Process Manager'; 2nd paragrpah; beginning of 3rd sentence

Change 'Your can also redirect...' to 'You can also redirect...'

Alexei Nekrassov  Aug 11, 2009 
Printed
Page 123
para 2

"where Frequencies is the loop data containing a tuple of allocated and available frequencies"
This is the wrong way round wrt code, and would be minor if you had not stated it the right way round in para 1 above?

Dave Pawson
 
Aug 26, 2009 
Printed
Page 123
Paragraph beginning "Deallocation works in a similar way."

replace
{request, Pid, deallocate}
by
{request, Pid, {deallocate,Freq}}
in second line of the paragraph

replace the occurrences of "Frequency" in typewriter font in lines 3 and 4 of the para by "Freq" in typewriter font.

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
Printed
Page 125
Last code example

The module in this example is called "server", but there is a call to spawn/3 with "generic_handler" as the module name. This can be found on page 125, last line.

Note from the Author or Editor:
To fix this, replace last line on p125 by
Pid = spawn(server, init, [Data]),

Dirceu Pereira Tiegs  Aug 03, 2009 
Printed
Page 126
explanation of the code, first bullet

"state variable" at the end of the sentence should be corrected to "State variable", with "State" in typewriter font

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
Printed
Page 134
1st paragraph

Line that reads "Pay particular attention to the send_event/2 call" should read "Pay particular attention to the event/2 call".

pnye  Jul 22, 2009 
Printed
Page 146
subsection "the exit BIFS"

isn't the Pid in the exit signal,{'EXIT', Pid, Reason}, generated by exit/2 the pid of the exit/2 caller? (based on Joe Armstrong's book page 155 and my own experiment)

Note from the Author or Editor:
Correct, the Pid generated by the exit/2 is the Pid of the caller, and not the Pid of the receiving process.

Figure 6-7 needs updating, there the calling Pid is called PidA, the crashing Pid PidB. The exit/2 call should be exit(PidB, Reason) and the message itsself {'EXIT', PidA, Reason}.

ssyeoh  Aug 20, 2009 
Printed
Page 146
Figure 6-7

In your comment to ssyeoh:
Figure 6-7 needs updating, there the calling Pid is called PidA, the crashing Pid PidB. The exit/2 call should be exit(PidB, Reason) and the message itsself {'EXIT', PidA, Reason}

Shouldn't the message be {'EXIT', PidB, Reason}?

Note from the Author or Editor:
The picture as it stands is correct, but as you say we could make clear that Pid is the pid of the process on the left, and that the process in which the exit/2 call takes place has some pid different from Pid.

Alexei Nekrassov  Oct 07, 2009 
Printed
Page 148
Sentence just before table 6-1

Change
"not terminated if one of the peers in its link set is killed unconditionally."
to
"terminated if one of the peers in its link set is killed unconditionally."

Alexei Nekrassov  Oct 07, 2009 
Printed
Page 150
code section

in init() function, process_flag line should be indented.

Note from the Author or Editor:
This refers to the line
process_flag(trap_exit, true),
which is the sixth line from the bottom. No other lines need changing.

Ivan Uemlianin  Apr 18, 2010 
Printed
Page 151
loop(Frequencies) function

'EXIT' block should be indented.

Note from the Author or Editor:
This refers to the line
{'EXIT', Pid, _Reason} ->
towards the middle of the page. The code following it should keep the indentation that it currently has.

Ivan Uemlianin  Apr 18, 2010 
Printed, PDF, , Other Digital Version
Page 151
deallocate function

allocate can allocate multiple frequencies per client, deallocate deallocates only one and always unlink the pid. This way if you allocate two frequencies and deallocate one, client and server will be unlinked. deallocate should check it's going to delete the last allocate frequency for that client.

Note from the Author or Editor:
This is a good point. There's an implicit invariant that each client will only ask for a single frequency, but this observation is right in the case where the invariant is broken.

Federico Galassi  Aug 21, 2010 
Printed
Page 153
Last paragraph

"the synchronous client function stop/0" should be changed to "the synchronous client function stop/1"

Andrey Paramonov  Nov 16, 2009 
Printed
Page 154
First sentence of "Exercise 6-2: A Reliable Mutex Semaphore"

The sentence is referring to "...the mutex semaphore from the section "Finite State Machines on page 126 in Chapter 5..." I believe the mutex semaphore in question is on page 129 (description) or 130 (code and diagram).

Note from the Author or Editor:
Yes, should say "on page 129 in Chapter 5"

ninaj  Aug 17, 2009 
Printed
Page 154
Erercise 6-2

try .. catch will not add anything here, as we are trapping exits. link will work, and an exit signal with reason noproc will be sent to the process.

Note from the Author or Editor:
The paragraph should read:

In the first version of this exercise, use the link(Pid) BIF. Make sure you handle the case where a process you are linked to terminates before you unlink from it.

Francesco Cesarini
Francesco Cesarini
 
Sep 21, 2009 
Printed
Page 155
Second bullet point, last sentence

I am just a bit confused about the instruction in exercise 6.3. In the second bullet point, I am to "remove the child from the child list if the module is not available". However, I would have thought that if something went wrong on line 22 of my_supervisor.erl, it would not have been added to the list, so there is nothing to remove?

My interpretation of the start_children/1 is that if we get anything other than {ok, Pid} returned from the apply call, we call ourselves again with a list that does NOT contain the new process, because a process only gets added to the list when successfully spawned. So there isn't anything to remove. Or have I misunderstood this?

start_children([]) -> [];
start_children([{M, F, A} | ChildSpecList]) ->
case (catch apply(M,F,A)) of
{ok, Pid} ->
[{Pid, {M,F,A}}|start_children(ChildSpecList)];
_ ->
start_children(ChildSpecList)
end.

Thanks
Nina

Note from the Author or Editor:
The scenario we were thinking of here is one in which the process is started and then the module subsequently becomes unavailable. This will lead to the "infinite restart" scenario.

First sentence should therefore read "What happens if the supervisor starts a child which always exits soon after being spawned?"

ninaj  Aug 18, 2009 
Printed
Page 155
First bullet point of exercise 6-3

"If a child terminates both normally and abnormally"

should read something like:

"If a child terminates, either normally or abnormally".

Ivan Uemlianin  Apr 18, 2010 
Printed
Page 156
Fourth bulletpoint, second sentence

The sentence reads "You will get pid from the return value of the start_child function." There is no start_child function though, it should probably be one of restart_child or start_children.

Note from the Author or Editor:
Yes, we meant "start_child" here, because we asked you to define this in the third bullet point on page 155.

ninaj  Aug 18, 2009 
PDF
Page 158
Second line of the code for the tuples1 example

This line should be
-export([test1/0, test2/0]).
rather than
-export([test/1, test/2]).

Simon Thompson
Simon Thompson
 
Jun 20, 2009 
Printed
Page 159
definition of record

Wrong bracket type, brackets missing, full stop missing:

-record{name, {field1 [ = default1 ],
field2 [ = default2 ],
...
fieldn [ = defaultn ] }

should be

-record(name, {field1 [ = default1 ],
field2 [ = default2 ],
...
fieldn [ = defaultn ] } ).

Ivan Uemlianin  May 03, 2010 
Printed
Page 167
second line

The "call" in "the second call will be..." should be corrected to "Call" in typewriter font.

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
Printed
Page 169
Excercise 7-3, line 3

-record{data,{key,data}).

should be

-record(data, {key,data})

i.e. the first curly bracket should be a normal parenthesis.

ninaj  Aug 20, 2009 
Printed
Page 169
1st paragraph

Exercise 7-2 introduces the BIF record/2 - this should probably be changed to is_record/2, as the current erlang release (R13X) deprecates record/2 (the compiler issues a warning):

[...]
./shapes.erl:22: Warning: record/2 obsolete
./shapes.erl:24: Warning: record/2 obsolete
[...]

Note from the Author or Editor:
Change the record(...) BIF to is_record(...).

Tom Regner  Sep 21, 2009 
Printed
Page 169
Exercise 7-2, top of page

"Using the record BIF record(P, person)..."
should be
"Using the record BIF is_record(P, person)..."

Steven Wicklund  May 11, 2010 
PDF
Page 178
Shell statement numbers 5 and 6

The shell statement numbers 5 and 6 indicate that the user is to continue their shell session. However, executing these commands in the same shell session results in an error.

The problem is that there was no fully-qualified call from the loop process to load the third version (that has a fully-qualified call to a/1). And since statement 5 compiles the v3 of the module, the version being run by the process (v1) has been unloaded, the process dies, and the statement in line 6 fails because foo is no longer the registered name of a running process.

Note from the Author or Editor:
You are correct. The text should read:


the effect of the same software upgrade will be evident after recompilation in command line 4, where we change a(N) -> N + 2. back to a(N) -> N. When trying it out in the shell, make sure you start with a new one so as to avoid side effects from the old module versions of the previous examples:

1> c(modtest2).
{ok,modtest2}
2> modtest2:main().
true
3> modtest2:do(99).
101
4> c(modtest2).
{ok,modtest2}
5> modtest2:do(99).
99

Phil Jerkins  Aug 18, 2009 
Printed
Page 187
Paragraph numbered "2"

"2. Add the client function code_upgrade() to the my_db.erl server module."

Does the author mean that we should use the my_db module from a previous chapter, or should that be db_server.erl, which is in chapter 8's code samples?

Note from the Author or Editor:
No, we are referring to the my_db module in exercise 5-1, page 137. We should add a cross reference to this in the next release.

ninaj  Aug 23, 2009 
Printed, PDF, , Other Digital Version
Page 194
Note at the middle of the page

The note at the middle of the page states you can't spawn a dynamically created function, and gives no example. But at least with R14A it seems you can, also closures with bound values can be spawned.

Note from the Author or Editor:
Yes, quite right. We should add that we can spawn a dynamically created function (which takes no arguments) using the spawn/1 function, as in

spawn(fun () -> ok end).

Nahuel Greco  Aug 01, 2010 
Printed
Page 195
code of foo() function

The third line "Bump = fun(X) -> X+1 end." should be corrected
to "Bump = fun(X) -> X+1 end,".
The final character should be a comma, not a full stop.

Simon Thompson
Simon Thompson
 
Apr 21, 2010 
Printed
Page 197
top of the page, shell entry 18>

Technically speaking, this is not definition of positive function, it's a definition of non-negative function. In that regard the "true" result of lists:all(Positive, [0,1,2,3,4]) in shell line 20 might be misleading.

Note from the Author or Editor:
In the lines numbered 18, 19, 20 and 21 change all occurrences of "Positive: to "NonNegative"

Andrey Paramonov  Nov 27, 2009 
Printed
Page 200
2nd paragraph, "multiple Generators"

"next, X is given the value ___ and Y ranges through [2,3]

Should say "2" in there

gene tani  Aug 29, 2009 
Printed
Page 201
whole chapter

The usage of the terms 'binaries' and 'bitstrings' is not consistent.

Throughout the chapter the terms binary/binaries are often used where bitstring/bitstrings would be correct.

As bitstring is the more general type, and binary is a "subtype" of it, applying only to bistrings where bit size is a multiple of 8.

Note from the Author or Editor:
Thanks! We will take a careful look for the next iteration.

Paul Hoesli  Aug 02, 2009 
PDF
Page 204
Following the line "The following code snippet shows these types in action:"

None of the code in this block should be italicised.

Simon Thompson
Simon Thompson
 
Jun 20, 2009 
Printed
Page 205
second to last section

The statement

<<X:7/binary,Y:1/binary>> will never match...

is just not true!

e.g. the following extract from the shell shows that it will match:

1> <<X:7/binary,Y:1/binary>> = <<1,2,3,4,5,6,7,8>>.
<<1,2,3,4,5,6,7,8>>
2> X.
<<1,2,3,4,5,6,7>>
3> Y.
<<

Note from the Author or Editor:
Thanks very much for sorting out this confusion on our side.

Paul Hoesli  Aug 02, 2009 
Printed
Page 209
Figure 9-1

In the code snippet the comma is missing after 5th closing brace. The correct code is

{node,
{node,
{leaf,cat},
{node,
{leaf,dog},
{leaf,emu}
}
},
{leaf,fish}
}.

Andrey Paramonov  Nov 28, 2009 
Printed
Page 220
code snippet in 2nd paragraph

regexp module is deprecated. The example should use re module. Also, the definition of Punctuation seems to be over-backslashed. It's not necessarily to escape space, comma, and (semi)column in regex patterns.

Note from the Author or Editor:
Finally got my head around the re package. OK, here's the update ?

Replace the line
-define(Punctuation,"(\\ |\\,|\\.|\\;|\\:|\\t|\\n|\\(|\\))+").
by
-define(Punctuation,"[ |,|\\.|;|:|\\t|\\n|\\(|\\)]+").

Replace the function

processLine(Line,N) ->
case regexp:split(Line,?Punctuation) of
{ok,Words} ->
processWords(Words,N) ;
_ -> []
end.

by the function

processLine(Line,N) ->
Words = re:split(Line,?Punctuation,[{return,list}]),
processWords(Words,N).

Andrey Paramonov  Nov 30, 2009 
Printed
Page 222
paragraph starting with "The traversal is set up..."

Incorrect arity of prettyIndex and prettyIndexNext functions. They must be prettyIndex/0 and prettyIndexNext/2.

Note from the Author or Editor:
The reason for this was a change in the interface - whether or not to pass the table id - which has not been completely implemented.

Change line
The traversal is set up by prettyIndex/1, which reads the first field, {Word,N}, and builds
to
The traversal is set up by prettyIndex/0, which reads the first field, {Word,N}, and builds

Change line
are passed to the worker function prettyIndexNext/3, which performs the traversal:
to
are passed to the worker function prettyIndexNext/2, which performs the traversal:

Also on p223, change line
prettyIndexNext(TabId,Entry,{Word, Lines}=IndexEntry) ->
to
prettyIndexNext(Entry,{Word, Lines}=IndexEntry) ->

Andrey Paramonov  Dec 01, 2009 
PDF
Page 223
first block of code

the first line of the code block should read
prettyIndexNext(Entry,{Word, Lines}=IndexEntry) ->
rather than
prettyIndexNext(TabId,Entry,{Word, Lines}=IndexEntry) ->

Simon Thompson
Simon Thompson
 
Jun 21, 2009 
PDF
Page 237
10th line of first code block

This line should read
[#usr{status=disabled, id = CustId}] ->
rather than
usr{status=disabled, id = CustId}] ->

Note from the Author or Editor:

Simon Thompson
Simon Thompson
 
Jun 21, 2009 
PDF
Page 248
3rd paragraph

Missing space.

Is:
"A similar command, erl-sname bar, will set up a second node on the STC system."

Should be:
"A similar command, erl -sname bar, will set up a second node on the STC system."

Note from the Author or Editor:
Just to be clear, this is saying that there needs to be a space between "erl" and "-sname" in this case.

Mietek B&#261;k  Aug 19, 2009 
Printed
Page 248
4th paragraph

change "module dist.er1" (digit "one" at the end) to
"module dist.erl" (letter "ell" at the end)

Alexei Nekrassov  Nov 19, 2009 
PDF
Page 255
2nd code listing

Node name mix-up.

Is:
(beta@STC)2> nodes(connected).
['beta@STC']

Should be:
(beta@STC)2> nodes(connected).
['alpha@STC']

Mietek B&#261;k  Aug 19, 2009 
Printed
Page 260
under "epmd process" header, in italics

3rd line of paragra[ph: "port mapper deamon" >> "daemon"

gene tani  Aug 29, 2009 
PDF
Page 271
In the code block

before the line
-export([start_link/0, start_link/1, stop/0]).
insert the line
-module(usr).

Simon Thompson
Simon Thompson
 
Jun 21, 2009 
Printed
Page 276
4th and 5th paragraph

supervisor:start/3 and supervisor:start/2 don't seem to exist.

Note from the Author or Editor:
Yes, indeed. Should make the following edits on 276

1. delete the lines
supervisor:start(ServerName, CallBackModule, Arguments)
supervisor:start(CallBackModule, Arguments)

2. modify the line
You start a supervisor using the start or start_link function:
to
You start a supervisor using the start_link function:

3. Modify the line
functions of arity two.
to
function of arity two.
from this page.

and at the top of p277 should change

Note that the supervisor, unlike the gen_server, does not take any options. The start and start_link functions will spawn ?

to

Note that the supervisor, unlike the gen_server, does not take any options. The start_link function will spawn ?

Anonymous  Mar 07, 2010 
Printed, PDF, , Other Digital Version
Page 278
The paragraph headed "Restart" in the "Child Specification" section.

The text describing child restart strategy transposes the meanings of 'temporary' and 'transient'.

The erroneous text reads : "Transient processes are never restarted. Temporary processes are restarted only if..."

It should read : "Temporary processes are never restarted. Transient processes are restarted only if..."

Tim Lewis  Aug 24, 2010 
Printed
Page 283
3rd paragraph, 5th row

instead of inets.app should be *.app or app,
because every application will have its own app file, not an inets.app file

Note from the Author or Editor:
In the "also have an inets.app file", change to "also have an app file".

Anonymous  Sep 17, 2009 
Printed
Page 288
2nd paragraph

Text refers to systools:make_rel(Name, Options) in the second sentence of the second paragraph and also in the next to the last sentence of the third paragraph. I think this should be systools:make_script/2. To the best of my knowledge, the Erlang error handler, and the most recent documentation, there is no systools:make_rel function.

K5KDN  Oct 05, 2009 
Printed
Page 288
middle / bottom

The function systools:make_rel(Name, Options) and systools:make_rel/2 is depreciated and should be replaced with systools:make_script(Name, Options) and systools:make_script/2

Note from the Author or Editor:
make_rel functions should be replaced with systools:make_script/2. systools:make_rel is depreciated.

Francesco Cesarini
Francesco Cesarini
 
Sep 02, 2010 
Printed
Page 306
Command 4, line 3

{disc_copies [foo@localhost, bar@localhost}]).

should be

{disc_copies, [foo@localhost, bar@localhost]}]).

ninaj  Sep 02, 2009 
Printed
Page 326
last parag

It should be noted that the 3 ways to specify IP address for gen_udp are not completely equivalent re: DNS lookups

http://groups.google.com/group/erlang-programming/msg/59a3f7d8052d39c7

Note from the Author or Editor:
replace "IP address." on the third line from the bottom by "IP address; in high-throughput applications passing the tuple form will be more efficient than passing a string."

gene tani  Oct 09, 2009 
Printed
Page 346
1st complete paragraph under "Erlang from Unix Shell"

1st line of paragraph

"erl_interface" shd be printed as one word, not broken over 2 lines

gene t  Oct 10, 2009 
Printed, PDF, , Other Digital Version
Page 351
lower half

just the brackets missing at the when(..) and f.send!(...) and it works like a charm in ruby 1.8.7 with current gem of erlectricity

require 'rubygems'
require 'erlectricity'
require 'stringio'

def fac n
if (n<= 0) then 1 else n*(fac(n-1)) end
end

receive do |f|
f.when([:fac, String]) do |text|
n = text.to_i
f.send!([:result, "#{n}!=#{(fac n)}"])
f.receive_loop
end
end

Thanks very much to Mark Jones for pointing this out.

Simon Thompson
Simon Thompson
 
Mar 23, 2011 
Printed
Page 368
last paragraph

Text says: "dbg:stop/0 will not clear the trace flags"

According to Erlang docs, dbg:stop/0 does clear the trace flags. dbg:stop_clear/0 is the same as dbg:stop/0, but also clears trace patterns.

Note from the Author or Editor:
Modify the final line to say:
not clear the trace patterns. For this purpose as well as clearing the trace flags, use dbg:stop_clear/0.

Andrey Paramonov  Dec 25, 2009 
Printed, PDF, , Other Digital Version
Page 392
4th and 5th paragraphs

The first average fun is non-tail-recursive and the
2nd fun is tail-recursive. Either the code samples
or the description got mixed.

Also there's a syntax typo:
wrong
len({_ | Tail]) -> 1 + len(Tail).
right
len([_ | Tail]) -> 1 + len(Tail).

Anonymous  Oct 04, 2010 
Printed
Page 399

The book does not mention that to be able to use TypEr, you first have to create a Persistent Lookup Table with Dialyzer. Adding this information may be difficult, as TypEr is presented before Dialyzer.

Also page 401 says that generating the PLT takes some minutes. On our Sun workstation it takes about 2 hours and Dialyzer gives no indication of progress, giving the impression of having crashed.

Note from the Author or Editor:
Good point! We should look again at the order of this material.

Olaf Chitil  Sep 08, 2009 
Printed
Page 402, 404
footprint, bottom p 402, "@spec" paragraph, top p 404

Maybe it's premature to write -spec's, but it's mentioned multiple times, so could you give a reference for the "@spec" vs. "-spec"

The only thing i found (it's a difficult issue to google

http://www.erlang.se/euc/08/1400Kostis.pdf

http://www.erlang.org/eeps/eep-0008.html

Note from the Author or Editor:
p404, fifth full line: add to the end of the line a footnote reference to the following footnote:
More details of this proposal are in Erlang Enhancement Proposal 8, http://www.erlang.org/eeps/eep-0008.html

gene tani  Oct 10, 2009 
Printed, PDF, , Other Digital Version
Page 410
first line

"y" should be replaced by "Figure 18-3"

Simon Thompson
Simon Thompson
 
Jun 29, 2010 
Printed
Page 424
1st paragraph

compile:file(foo, [compile_all, ...]).

should be, instead:

compile:file(foo, [export_all, ...]).

Roberto Aloi  Nov 26, 2009 
Printed
Page 428
2nd paragraph

The text warns that if you do not handle unknown messages, "you will notice that the CPU usage of your system will start to increase and that the response time will decrease". The explanation is that Erlang will have to traverse an increasing amount of messages waiting in the process's mailbox. But if that's the case, won't that increase the response time rather than decreasing it? Decreasing the response time means Erlang will perform faster rather than slower...

Note from the Author or Editor:
Yes ? we should have said that the responsiveness will decrease, because the response time will increase.

Rob Walker  Sep 08, 2010 
Printed
Page 451
Index

<= (less than or equal to) operator, 28, 378
>>
>> which should of course be
>>
>> =< (less than or equal to) operator, 28, 378

Note from the Author or Editor:
Just to clarify the above (too many >s !!!) change index line
<= (less than or equal to) operator, 28, 378
to
=< (less than or equal to) operator, 28, 378

Anonymous  Apr 12, 2010 
Printed
Page 469
1st column; 8th and 9th lines from the bottom

Tiring test, 340
Turing, Alan, 340

should both refer to p 341

Alexei Nekrassov  Aug 01, 2009