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 |
| Safari Books Online |
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 |
|
| Safari Books Online |
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 |
|
| Safari Books Online |
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
 |
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
 |
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
|
Apr 12, 2010 |
|
| Printed, PDF, Safari Books Online, 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
 |
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 |
|
| Safari Books Online |
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)
|
dpawson |
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, Safari Books Online, 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, Safari Books Online, 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
 |
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
 |
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
 |
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?
|
dpawson |
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
 |
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
 |
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, Safari Books Online, 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
|
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
 |
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
 |
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, Safari Books Online, 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
 |
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
 |
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
 |
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
 |
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ą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ą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
 |
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, Safari Books Online, 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
|
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, Safari Books Online, 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
 |
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, Safari Books Online, 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, Safari Books Online, Other Digital Version |
Page 410
first line |
"y" should be replaced by "Figure 18-3"
|
 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 |
|
|