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.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

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

Version Location Description Submitted by Date submitted
Printed Page index
index

From the reader reporting the error:

I'm new to the Erlang language, and I was looking up the "||" operator,
and the index in "Erlang Programming" only points to its use in
bitstream comprehensions, not to its far-more-common use in list
comprehensions.

Anonymous  Nov 13, 2011 
Chapter 3 - Runtime Errors
badmatch

The text example given for badmatch error is unrelated. The discussion is about the return tuple from keysearch/3, and what may happen when the key is not present. However, the example code below the discussion is a trivial example of an attempt to assign to a tuple with an element already bound.

1> Tuple = {1, two, 3}.{1,two,3}
2> {1, two, 3, Four} = Tuple.
** exception error: no match of right hand side value {1,two,3}

Dale Keener  Feb 14, 2017 
Printed Page 25
The bottom indented region.

The lines

7> lists:delete(2,[1,2,3,2,4,2]).
[1,3,2,4,2]

are ambiguous. They seem to indicate that the deletion is occurring on the second element rather than being pattern matched to the integer 2. If this were written as

7> lists:delete(b,[a,b,c]).
[a,c]

or

7> lists:delete(2, [1,1,1,1,1,1,1,1,1,2,1,1,1,1])
[1,1,1,1,1,1,1,1,1,1,1,1,1]

it would be clearer.

Fred  Dec 05, 2010 
PDF Page 66
definition of merge

Its seems tome that the second clause of mergeR/3 definition breaks the function definition.
calling merge/2 with first list longer by 1 item than the second,
will not raise an exception.

Shimon Cohen  Jun 08, 2012 
Printed Page 101
2nd paragraph (jist before diagram).

In this paragraph, the authors use "Pid" to refer to the process identifier of the parent (when talking about what receive in the loop/0 function does). Should each of the uses of "Pid" not read "From" as per the code on page 100?

Paul Barry
Paul Barry
 
May 17, 2011 
Printed Page 137
execution log

I think the io_handler should be added before raise_alarm as the raise_alarm code is not executed otherwise.

John-Olof Bauner  Jul 22, 2010 
Printed Page 148
Just before Table 6-1

This is an errata errata. I think the errata posted for this page is wrong, there is no error in the printed version. The sentence:

"This will ensure that process trapping exists are NOT terminated if one of the peers in its link set is killed unconditionally."

is right, because the first process receives a 'kill' signal, but is transformed to a 'killed' signal when is propagated to the peers in its linksets. If no kill->killed transformation were done, then the linked process will die unconditionally, but is not the case, as the "NOT" in the original sentence correctly denotes.

Nahuel Greco  May 16, 2010 
PDF Page 151
exited/2 function

In the text following this code sample it is stated that the exited function checks to see if the frequency has already been placed in the Allocated list because of a possible race condition where the client process exits before the server process finishes deallocating the frequency and unlinking the client process.

Is this correct? I don't believe the possibility of a race condition exists here.

Since the server process is trapping exit signals, the client's exit signal is delivered to the server's mailbox. Since the deallocate function (including the unlink operation) is executed from the message loop in response to a deallocate message, no other messages (including the exit message) will be processed until the deallocation and unlink completes.

While the code should still check the Allocated list, the reason (I believe) is only because of a client that may have neglected to deallocate a frequency before it terminated.

Josh Perry  Feb 11, 2012 
Printed Page 162
Code sample - command 7

Following the code sample on pages 161 to 162 in the shell, the following line

7> NewPerson = Person#person{name=#name{first="Mike", surname="Williams"}}.

will actually result in the following error:

** exception error: no match of right hand side value
#person{name = #name{first = "Mike",surname = "Williams"},
age = 30,phone = []}

Using a different name for the variable will resolve the issue:

> NewPerson2 = Person#person{name=#name{first="Mike", surname="Williams"}}.
#person{name = #name{first = "Mike",surname = "Williams"},
age = 30,phone = []}

Clifford Hung  Dec 30, 2011 
Printed Page 187
Last line on page

After doing the code:app_patha in command 5, you need to do the code:load_file before you proceed to command 6 my_db:code_upgrade. At least that is what I found.

ninaj  Sep 02, 2009 
PDF Page 187
Bottom of the page

Is there some command or setting I need to change in the console to
> get it to recognize/load the revised db.beam file?
> I added the patches directory to the path as described (the only
> difference being that I added it as a relative path "./patches", but
> that is also how the "ebin" directory is in the path), and then I run
> the convert routine and get an error:
> =ERROR REPORT==== 26-May-2010::11:59:48 ===
> Error in process <0.45.0> with exit value: {undef,[{db,convert,[list,
> [{rec1,"Steve"},{rec2,"Steve2"}]]},{db_server,loop,1}]}
>
> Which is what happens if I call the (non-existent) convert method on
> the old class. :(
>
> TIA
>

Francesco Cesarini
Francesco Cesarini
 
Jun 02, 2010 
Printed Page 191
last code sample

In last code sample for filter function:
I think

filter(P,[])->[];

should be
filter(_P,[])->[];

in order to avoid compiler warning message.

Jaeho Lee  Jul 21, 2011 
Printed Page 204
'An endian value'

The definitions of big- and little-endian appear to have been transposed.

Should read

In the big-endian case the first byte is the most-significant one, in little-endian the first byte is the least significant.

Raphael Mankin  Nov 22, 2011 
Printed Page 210
footnote 1, bottom of page

"each incarnation of node, references are allocated to be integers starting at 0"

this is unclear. I think several points could clarify:

- references are used like GUID's, can be paired with any erlang entity in the runtime, not just a node

- references are 4 to 7 words, not integers, per

http://erlang.mirror.su.se/doc/efficiency_guide/advanced.html

- The integer starting at 0 is some kind of seed value, not the reference's value.

gene tani  Sep 17, 2009 
Printed Page 223
First code exammple

The form

prettyIndexNext(Entry, {Word, Lines}=IndexEntry) ->

with a match pattern in the function header is nowhere described. This is the first use of it.

Raphael Mankin  Nov 22, 2011 
Printed Page 292
First example

The module should be 'my_db_gen' and not 'my_db'.

Roberto Aloi  Jan 31, 2012 
Printed Page 292
Exercise 12-2

Exercise 12-2 states DETS are used in exercise 12-1, where students are told to use LISTS instead.

Roberto Aloi  Jan 31, 2012 
PDF Page 314
center

debian squeeze
erlang erts-5.8

What can I do?

>microblog:start().

exception error: {load_driver,"symbol _ZN16wxStyledTextCtrl7SendMsgEill, version WXU_2.8 not defined in file libwx_gtk2u_stc-2.8.so.0 with link time reference"}
in function wxe_server:start/0
in call from wx:new/1
in call from microblog:start/

douglasv  Aug 01, 2011 
Printed, PDF Page 319
book, page 319, wx#{id?UNDO...

wx#{id=?UNDO....} ->
{StartPos,EndPos} = lastLineRange(Text),
...

lastLineRange(Text) not declared

where does this exist?


Thank you,
Douglas

Douglas V  Mar 14, 2011 
Printed Page 329
last paragraph

The text makes a special point of noting:

---
Note how the get request/3 function receives the binary chunks in batches of 100 bytes.
---

Is it really possibly to know that the chunks are 100 bytes long? It's my understanding that when a message is sent through a TCP connection, you have to assume that a message can be split into arbitrarily sized chunks, so each 100 byte message could be split into multiple chunks.

And, when you specify {packet,0}, which I think is the default (it would be better if that was explicit in the code rather than implicit), Erlang isn't going to bundle the received chunks into a complete 100 byte message for you. Now, if the code had specified {packet, 1|2|4}, then I think gen_tcp:recv(Socket, 0, Timeout) *would* return whole, 100 byte messages.

7stud  May 18, 2017 
Printed Page 330
First sentence

The text says:

---
....start the server using tcp:start()...
---

The module name 'tcp' sounds like a library module, and I actually confused 'tcp' with 'gen_tcp'. I assume 'tcp' is supposed to be a user module that contains the example code for the client and the server--but nowhere in the text does it say that the example code is in a module named ’tcp'. It would have been clearer if the module name had been 'my' instead of 'tcp'. It’s better to make it glaringly obvious that a module isn’t a library module.

Furthermore, there is no start() function in the example code, which again might lead a reader to believe that 'tcp' is a library module and that somehow tcp:start() magically starts the server. I think someone changed the names of the functions in the example code and didn't update the text. I actually think start() would have been a better function name than server() because I found that the function names in the example code made it hard to figure out what was going on. Here are the names I would suggest:

server_init() -> %instead of server()
{ok, ListenSocket} = ...
...

server(ListenSocket, Count) -> %instead of wait_connect()
...
spawn(?MODULE, server, [ListenSocket, Count+1]
...

7stud  May 18, 2017 
Printed Page 330
options list in the middle of the page

Arguably, the two most import options for TCP and UDP connections are:

{active, true|false}
-------------------
true:
Messages sent to the socket will be read and placed in the mailbox, so you extract them with a receive block:
receive
{tcp, Socket, Data} -> ...
end

false:
Messages sent to the socket are not automatically read and placed in the mailbox. Instead, you read the messages directly from the socket by calling recv().


{packet, raw|0|1|2|4}
---------------------
1|2|4:
On send(), Erlang automatically calculates the length of the message and inserts the length into the number of bytes specified in the packet tuple, then appends the message.
On recv(), Erlang automatically strips off the length header and bundles the message chunks into a complete message.

raw|0 (equivalent):
On send(), Erlang does not prepend the message with the message's length.
On recv(), Erlang does not bundle chunks into a complete message (because the message length is not known). Requires a loop to read the complete message. The marker for the end of the message is when the other side closes the socket.

-------


But I cannot find anything in the chapter that mentions {packet, N}--even though the option is used in the example code!

7stud  May 19, 2017 
PDF Page 349
2nd line

Using Ruby 2.3 and erlectricity-1.1.1, I had this error :
.../receiver.rb:65:in `initialize': The given fd is not accessible because RubyVM reserves it (ArgumentError)

receiver.rb opens two IO streams :
input ||= IO.new(3)
output ||= IO.new(4)

It seams that file descriptors 3 to 6 are reserved by the Ruby VM.

In the following line of echoFac.erl :

Port = open_port({spawn, Cmd}, [{packet, 4}, use_stdio, exit_status, binary]),

just replace use_stdio by nouse_stdio, and it woks.

Bernard Kaiflin  Jan 14, 2017 
Printed Page 396
2nd paragraph

"Constant functions" should be changed to "arity 0 functions".

Anonymous  Jul 31, 2011 
PDF Page 428
Example at the end of the page

The example at the end of page 428 illustrates (according to the previous paragraph) how to safely handle timeouts without accumulating unhandled (late) answers and without mistaking them for answers to more recent calls. However, the example lacks a "timeout" clause in the "wait_reply" function.

Sam  Mar 01, 2011 
Printed Page 440
The first verion of even_multiple/2 code

even_multiple(List, Multiple) ->
Even = lists:filter(fun(X) -> (X rem 2) == 0 end, List),
Multiple = lists:map(fun(X) -> X * Multiple end, Even),
lists:sum(Multiple).

Multiple = lists:map(fun(X) -> X * Multiple end, Even) can't be right. I guess it should be

Multiple1 = lists:map(fun(X) -> X * Multiple end, Even), lists:sum(Multiple). (Assume the input parameter "Multiple" is a multiple). But need author's clarification.


qiulang  Oct 27, 2010 
Printed Page 451
Index entry for <=

Confusion in the index between <= and =<. The second entry fro <= should be for =<

On p466 for the 'rr/1' command add an entry for p161

Raphael Mankin  Nov 28, 2011