By Developers, For Developers

Historical errata for Programming Erlang

PDF PgPaper PgTypeDescriptionFixed onComments
30ERROR

I posted the following question to the Erlang questions email group. Any help would be appreciated. Thanks!


I’m learning Erlang using the Programming Erlang (2d ed) text from Pragmatic Bookshelf. Chapter two, “A Whirlwind Tour of Erlang” includes a file server sample that’s failing to work as the book suggests, and I’m afraid I’m not getting anywhere figuring it out. First, here’s the server code:

-module(afile_server).
-export([start/1]).

start(Dir) -> spawn(afile_server, loop, [Dir]).

loop(Dir) ->
receive
{Client, list_dir} ->
Client ! {self(), file:list_dir(Dir)};
{Client, {get_file, File}} ->
Full = filename:join(Dir, File),
Client ! {self(), file:read_file(Full)}
end,
loop(Dir).

That compiles (albeit with a warning saying “Warning: function loop/1 is unused”) but when I try to execute it from within the shell I get an error. For sake of reference the shell commands I’m issuing are:

Eshell V5.10.1 (abort with ^G)
1> c(afile_server).
afile_server.erl:7: Warning: function loop/1 is unused
{ok,afile_server}
2> FileServer = afile_server:start(“.”).
<0.39.0>
3>
=ERROR REPORT 10-Apr-2013::10:31:17 ===
Error in process <0.39.0> with exit value: {undef,[{afile_server,loop,[“.”],[]}]}

Can anyone suggest what might be wrong? I’m running under Windows 7 Professional x64 for sake of reference. Thanks in advance!

2013-04-14The export declaration in the program was wrong. \nIt should have read \n \n-export([start/1, loop/1]). \n \nThis is now fixed and will show up in the next beta draft \n \nThe error message {undef, [{afile_server, loop, ["."]}]} means that \nthe function loop in the module afile_server with one argument "." is undefined. \n \nThis is confusing. It's in the module but not exported so is treated as undefined. \n \nIt's like trying to call a private method from outside a class - it needs \nto be made public \n
24ERROR

The book says that pressing Ctrl + C or Ctrl + Break when executing the shell in Windows should produce output like the following:

BREAK: (a)bort ©ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution

But in reality it appears simply to exit the process. The following is copied from a console session in which I try those two keyboard shortcuts and find they both simply exit.

C:\\Users\\jwilliston>erl
Eshell V5.10.1 (abort with ^G)
1>
C:\\Users\\jwilliston>erl
Eshell V5.10.1 (abort with ^G)
1>
C:\\Users\\jwilliston>

2013-05-27 \nYou should use werl.exe not erl.exe \n \nerl.exe is equivalent to the unix command \n> erl -oldshell \n \nand is there for compatibility reasons \n \nIf you start the system from the Erlang start Icon in the \nwindows start menu things should work as described in the book
23TYPO

In Clarity section (bottom of page): “sequentaility” should be spelled “sequentiality”.

2013-04-14I think this was the error noted earlier on page 7
24TYPO

3r paragraph from bottom of page: “Choosing the objects that are needed to solve a problem is a recognized as
being a hard problem in object oriented design.” Drop the word “a” in front of “recognized”.

2013-04-14same error as reported on page 8 earlier
11TYPO

Paragraph before last: “Binding a variable means giving a variable a value, once it is has been bound that value cannot be changed later.” Remove the word “is”.

2013-04-13
420TYPO

Should
“If we wish to use the lists implementation we just change the line of code which created the module to Mod = adapter_db1:make(lists).”

be replaced by
“If we wish to use the lists implementation we just change the line of code which created the module to Mod = adapter_db1:new(lists).”

2013-04-14thank you - fixed
418TYPO

Statefull

should be

Stateful

2013-04-14thanks
432TYPO

send -> sent

“eventually contain information that is send back to the browser”

should be

“eventually contain information that is sent back to the browser”

2013-04-14corrected - thank you
58TYPO

afile_server.erl should also export loop/1
The current code gives a compiler warning and won’t run

2013-04-13fixed - same error as on page 11
15ERROR

The export list for afile_server must include loop/1 since it is the target of spawn/3.

2013-04-13My bad - fixed
58ERROR

afile_server.erl should also export loop/1
The current code gives a compiler warning and won’t run

2013-04-13fixed
18TYPO

This sends a {self(), list_dir() message to the file server process.

shoud be:

This sends a {self(), list_dir} message to the file server process.

2013-04-14fixed
79TYPO

Missed “)” at the end of expression:
count_characters(T, maps:extend(#{H~1}, X);

2013-04-14thanks
16TYPO

Second paragraph: “The is the standard way […]” replace “The” with “This”

2013-04-14thanks - fixed it
20TYPO

4th paragraph: “In the next chapter we’ll
start learning sequential programming by looking and the shell […]” should be “[…] looking at the shell […]”?

2013-04-14fixed
12TYPO

Paragraph before last: “Binding a variable means giving a variable a value, once it is has been bound that value cannot be changed later.” Remove the word “is”.

2013-04-13fixed
7TYPO

In Clarity section (bottom of page): “sequentaility” should be spelled “sequentiality”.

2013-04-14thanks, fixed
8TYPO

3rd paragraph from bottom of page: “Choosing the objects that are needed to solve a problem is a recognized as
being a hard problem in object oriented design.” Drop the word “a” in front of “recognized”.

2013-04-14thanks
30TYPO

4th paragraph: “Since Erlang variables immutable […]” should read “Since Erlang variables are immutable […]”

2013-04-14fixed
35ERROR

Unbalanced } in:

Person={person,{name,joe,armstrong}},{footsize,42}}.

Should read:

Person={person,{name,joe,armstrong},{footsize,42}}.

2013-04-14ooops - thanks you
38TYPO

Middle of page: " The notation \\x{2281}" should read " The notation \\x{221e}" to be consistent with the example.

2013-04-14Quite right. Thanks
51TYPO

To perform the same operation operation on every element of a list. — duplicated word ‘operation’

2013-04-14thanks - missed that one
283TYPO

In the third paragraph, “… in Chapter25, Third Party Programs, on page 425 To simplify…” . A period is missing after “on page 425”

2013-04-16thanks
283TYPO

In the beginning of the last paragraph, it says “In the rest of of this chapter,”. there are two “of”s.

2013-04-16thanks
284TYPO

In the second paragraph, a period is missing in this part: “../joearms/ezwebframe The browser code….”.

2013-04-16Thanks
284TYPO

At the beginning of the third paragraph, I think “Note: The code show here” should be “Note: The code shown here”.

2013-04-16Thanks
284TYPO

In the fifth paragraph, “If Erlang wants to the browser ..” should be “If Erlang wants the browser…” ?

2013-04-16You're right, there's an extra "to" - thanks
284TYPO

In the last paragraph, there are duplicated “we” in “this is so that we we can ..”.

2013-04-16yes - how come I didn't see this?
286TYPO

The first sentence “This code is build up from..” should be “This code is built up from ..” ?

2013-04-16thanks
286TYPO

In the middle of the page, It says “The click handlers sends messages..”. “sends” should be “send” ?
Also in the next paragraph, “All this is achieve by” should be “All this is achieved by”.

2013-04-16yes - two errors - thanks
287TYPO

The code “Browser ! <{ cmd ~ fill_div, id clock, txt current_time()}>” looks different from “Browser ! #{cmd ~ fill_div, id ~ clock, txt ~ current_time()}” in the previous page.

Also it looks there is a type here: “If a <{clicked ~ ”stop“>>}> message is…”.

2013-04-16Thanks - this syntax is not finalised so will probably change \nbefore the final beta and book is published.
287TYPO

In the last paragraph, “carriage return a message is send” should be “carriage return a message is sent”.

2013-04-16fixed - thanks
292TYPO

At the beginning of second paragraph, it says: “This code hooks an an event..”. “an” is duplicated.

2013-04-16thanks
292TYPO

In the third paragraph, “We have to respond to two message,” should be “We have to respond to two messages,”.

2013-04-16thanks
299TYPO

In the previous paragraph from the last, it says “For each object x in the list the system checks is there is a function”. It looks it should be “For each object x in the list the system checks if there is a function..” ?

2013-04-16You're right again! - thanks
300TYPO

In the second paragraph, “is” is duplicated here: “in websocket.erl where is is converted to a frame”.

Also, in the third paragraph, “our” is duplicated here: “This adds a sense of order and unity to our our programs making..”.

2013-04-16Should be "it is" not "is is" \nThanks \n
197TYPO

In “If something goes wrong in the middle or a transaction we simple abort …”, “simple” should be “simply”

2013-04-28thanks
197TYPO

In “It simplifies the system architecture, so we can thing about the application”, “thing” should be “think”

2013-04-28thanks
484TYPO

A2.4 SEE Implementation “deatils” => A2.4 SEE Implementation details

2013-04-28Thanks
80TYPO

In the last paragraph (about maps:without), the word any is duplicated (“… but with any any elements…”).

2013-04-28thank you
7TYPO

The word “Scaleability” has an extra “e”.

2013-04-28thanks
412TYPO

“we’ll look mat some programming idioms that that are..” should be “we’ll look at some programming idioms that are..”.: “mat” and “that that”

2013-04-28thanks
415TYPO

In third paragraph from the last, “..file transfer is support by..” should be “..file transfer is supported by..”

2013-04-28thanks
418TYPO

In last line, “then create a instance..” should be “then create an instance..” ?

2013-04-28an instance is correct - thanks
423TYPO

In fifth paragraph, “find is called when..” means “fetch is called when..” ?

2013-04-28Yes - my mistake - thanks
423TYPO

In the last paragraph, “Extent the adapter..” should be “Extend the adapter…”

2013-04-28yes - thanks
138SUGGEST

In chapter 9 Type annotations are discussed, and said to be useful. Yet, examples from the following chapters lack any type annotation. This is rather confusing. Would it be possible to clarify why these annotations are missing in the subsequent chapters, or why they’re not needed in the first place?

2013-05-30Good point. I general I haven't added additional type annotations where the type isn't obvious from the context - I'll read through the book and see if I can find places where additional type declarations would be helpful.
19TYPO

second paragraph: tying should probably read trying

2013-04-28yes - thanks
35TYPO

Code in the book reads:
1> Person={person,{name,joe,armstrong}},{footsize,42}}.

it should be:
1> Person={person,{name,joe,armstrong},{footsize,42}}.

2013-04-28thanks
70TYPO

In problem #4, “… in the Python datetime class can be implement using” : should be “implemented”.

2013-04-28thanks
4TYPO

…(that’s whats “/1” means…

should be

…(that’s what “/1” means

2013-04-28thank you
5TYPO

“Means start a parallel process…”

should be

“means start a parallel process…”

2013-04-28
5SUGGEST

“All the processes execute concurrently…”

A better wording might be:

“The difference is that all the Erlang processes…”

While the original sentence does reference the Erlang processes this makes things more explicit.

2013-04-28Yes - and it emphasises that it is *erlang* processes (ie not OS processes)
5SUGGEST

“Remember that in Erlang, …”

The fact that Erlang processes do not share memory is only briefly mentioned in the “Introduction” which some people might not read at all. This leaves the reader wondering what he has missed in the first chapter of the book.

A better wording would be:

“In Erlang, …”

2013-04-28I agree
6TYPO

“For Susannahs process to receive…” and “When Susannahs process receives…”

should be:

“For Susannah’s process to receive…” and “When Susannah’s process receives…”

2013-04-28
0TYPO

In the table of contents (as seen from the website), the title for this section appears to be misspelled.

Paralleizeing computations with mapreduce

2013-04-28fixed
268TYPO

If {active, true} is specified, then an active socket will be created; {active false} specifies a passive socket.

=> There should be a comma between “{active false}”

2013-04-28thanks
21TYPO

Part II intro: “Well cover all of sequential Erlang […]”: replace “Well” with “We’ll” or “We will”.

2013-04-28thanks
24TYPO

If you follow the book and type the commands in the Erlang shell, the second one answers 40 rather than 20 as we set X to 20 a few lines earlier:

2> X + 20. and this is a comment
40

2013-04-28You're right of course. What a silly error for me to make. Thanks
43TYPO

Common Errors 1st paragraph: “Commands like c(gemomtery).” “gemomtery” -> “geometry”

2013-04-28thanks
6TYPO

“…so that Susannah knows who the message came from”

The sentence is missing the full stop character (“.”).

2013-04-28How could I miss that?
6TYPO

“Rather that extending the model, …”

should be

“Rather than extending the model, …”

2013-04-28thanks
7TYPO

“A top end processor, has 64 cores…”

should be

“A top end processor has 64 cores…”

2013-04-28thanks
7TYPO

“Erlang programs written for sequential machine…”

should be

“Erlang programs written for sequential machines…”

2013-04-28thanks
8TYPO

“Now that you’ve seen these benefits, we’d try…”

should be

“Now that you’ve seen these benefits, we’ll try…”

2013-04-28thank you
8SUGGEST

Paragraph 4 from bottom: “This act of identifying the processes we call Modelling Concurrency.”

The sentence would read better when rephrased like this:

“We call this act of identifying the processes Modelling Concurrency.”

2013-04-28yes
8TYPO

3rd paragraph from bottom of the page: “The difference between a good and bad processes model…”

Use “process model” instead.

2013-04-28thanks
8SUGGEST

The definition of concurrent programs and concurrent programming languages are mutually cyclic - one refers to another.

A good idea might be to include a short phrase about the qualities of concurrent programs (i.e., describe them as sets of independent processes).

2013-04-28No sure about this. Concurrent programs are not necessarily sets of independent processes - I don't want to end up confusing people
9TYPO

Paragraph 3 from the bottom: “Erlang concurrency works the the same way…”

Drop one “the”.

2013-04-28thanks
9SUGGEST

Paragraph 2 from the bottom: “…and solve our problems, this allows …”

I think it would be better to introduce either a full stop or a semi-colon here - it would read better. Thus:

“…and solve our problems. This allows…”

2013-04-28I agree - thanks
9TYPO

Last paragraph: “…, we’ll take whirlwind tour…”

There is a missing “a”. It should read as follows:

“…, we’ll take a whirlwind tour…”

2013-04-28how did I miss that? - thanks
10TYPO

Last sentence in 3rd paragraph: “…please send mail to the Erlang mailing list, …”

There is a missing “a”. It should read as follows:

“…please send a mail…”

2013-04-28I added a "a" - not sure about this one. Very interesting - I think \nmail can be singular or plural.
12TYPO

3rd paragraph - either put the comma character (“,”) after the parentheses or rephrase the sentence as follows:

“We can assign (bind) values to variables using the ”=" operator like this:"

2013-04-28I added the comma
13SUGGEST

2nd paragraph - make the note in parentheses a footnote.

2013-04-28Unfortunately footnotes can only contain URLs - this is the pragmatic press "house style" and has to do with formatting the book for epub readers
80TYPO

The word `surprise’ doubled in phrase “… But surprise surprise, x has changed to…”

2013-04-28But this is not an error - "surprise surprise" is a common english expression not an inadvertent error
15SUGGEST

2nd paragraph in section 2.3: “A file server has two parts, a client which runs on one machine. And a server which runs on a second machine.”

Change the comma to a dash, and the first full stop to a comma, so that it reads as follows:

“A file server has two parts - a client which runs on one machine, and a server which runs on a second machine.”

2013-04-28That looks better, thanks
83ERROR

“…We know about lists as containers for a fixed number of items…”

Lists are containers for a variable number of items. This is obviously a typo.

2013-04-28My bad - silly mistake - thanks
139TYPO

“…Once we’ve happy…” Should be “we’re”

2013-04-28thanks
15TYPO

First paragraph in “The File Server Process” subsection: “…, process and modules are like classes and objects.”

Change “process” to “processes”. Furthermore, consider swapping the position of either “processes and modules” or “classes and objects”, so that the reader does not try to pattern match “processes” onto “classes” (it will read better).

2013-04-28Excellent - I swapped the order - thanks
16SUGGEST

2nd paragraph: Please consider changing “last call optimization” to “tail call optimization” - the latter seems to be more frequently used than the former.

2013-04-28Ok - I had a long think abou this one :-)
141TYPO

“…Addition type variables…”

Shouldn’t be there something like “…Additional…” or “…In addition, …”?

2013-04-28Yes "additional" - thanks
142TYPO

“…FileName and Modes and on…” Should be “ on”

2013-04-28thanks
142TYPO

Double `by’ in “…was being opened by by using…”

2013-04-28thanks
151TYPO

`Runing’ should be `Running’

2013-04-28thanks
18TYPO

Last paragraph: “This gives us the freedom to change to underlying protocols…” — change the second “to” to “the”

2013-04-28
26TYPO

4th paragraph: “…(for details see see…).” — drop one “see”

2013-05-13thanks
28TYPO

3rd paragraph from bottom: “Here’s some examples:” — change “Here’s” to “Here are”

2013-05-13yes - thanks
30TYPO

4th paragraph: “…, we just have to inspect the program to the find the place…”

should read

“…, we just have to inspect the program to find the place…”

2013-05-13fixed - thanks
35TYPO

2nd paragraph: “…we’d represent the days using the the atoms…” — drop one of the two consequent “the”

2013-05-13thanks
199TYPO

“If the processes terminated without an error when Why will be the atom normal, otherwise Why describes the error.” should perhaps be : “If the processes terminated without an error then Why will be the atom normal, otherwise Why describes the error.”

2013-05-13thanks
200TYPO

“The left hand side of the figure shows the how the processes are linked together ” should be “The left hand side of the figure shows how the processes are linked together”

2013-05-13fixed
36SUGGEST

Example in “Defining Lists” section: Please consider introducing a line where you define ThingsToBuy. It’s obvious from the evaluated expression what the list was set to, but since you’re using numbered erl lines for others to follow along and try things out the expression would end up with an error since ThingsToBuy hasn’t been defined yet.

2013-05-14I've reworded this. See the next release. Thanks for the idea
37TYPO

3rd paragraph from bottom - the sentence is missing the closing bracket “)”, and the colon should not be on a separate line all by itself.

2013-05-13
39SUGGEST

Please consider moving the “Exercises” section to page 40 - it will look better with all the exercises on a single page.

2013-06-02The final typography will be fixed later -
39TYPO

Last paragraph: “…and pattern matching, so we can step up the tempo…” — remove the comma and “so”

2013-05-13thanks
41TYPO

First paragraph: “Modules and functions, are the basic units…” — remove the comma

2013-05-13done :-)
209TYPO

“To illustrate thse steps” should be “To illustrate these steps”.

2013-05-13thanks
43TYPO

2nd paragraph: “…we used in the shell example, have become…” — remove the comma

2013-05-13yes thanks
47TYPO

4th paragraph from bottom: “Comma is a sort-range symbol, …” — should be “short-range symbol”

2013-05-13fixed
50TYPO

First paragraph in section 4.3 — there is a full stop missing after “…in Erlang is called a fun”

2013-05-13Thanks
51TYPO

2nd bullet point: “Erlang, has for example, no for loop.” should read “Erlang has, for example, no for loop.”

2013-05-13Yes - thanks
204ERROR

I think there is an ‘after’ missing in the start(Fs) function :
“start(Fs) ->
spawn(fun() ->
[spawn_link(F) || F <- Fs],
receive
infinity -> true
end
end).”
should be
“start(Fs) ->
spawn(fun() ->
[spawn_link(F) || F <- Fs],
receive
after infinity -> true
end
end).”

2013-05-13Thank you
222TYPO

Last line : “this basic code structure in central to many applications” should be : “this basic code structure is central to many applications”

2013-05-13thanks
262SUGGEST

When testing nano_get_url() you get a 302 code, perhaps it should be pointed out that it is not the expected response. It might be a good exercise for the reader to handle the redirection. Also, in the nano_get_url/1 function, a Host should be added to the GET string, otherwise connecting to google.x will always fail and major sites (e.g. apple or bing) will return 400.

2013-05-30I've added some comments and a new exercise at the end of the \nchapter. Fixing this makes a nice exercise. \n
78TYPO

In the paragraph description for maps:extend/2, the line “The Keys K1, K2 do not have to pre-eist in M1” has a typo. I’m guessing “pre-eist” should actually be “pre-exist”

2013-05-13This part has been rewritten to reflect a last-minute change in syntax
81TYPO

Under the section “The JSON bridge”, in the description for maps:to_json/1. There is a line “map_to_json fails if any of the keys or values cannot be represented in JSON”. Shouldn’t “map_to_json” be “maps:to_json”?

2013-05-13yes - thanks
431ffSUGGEST

I’ve followed the cowboy example along, and after adding the terminate/3 function, I tried running the small sample server, following the rebar conventions in the previous section (i.e. add a rebar.config file with dependencies for cowboy, rebar get-deps, rebar compile and then launching via

erl -noshell -pa “deps/cowboy/ebin” -pa “deps/ranch/ebin” -pa “./ebin” -s simple_web_server start 4000

).

To my dismay cowboy started, but never bound to any port, just sat there looking at me. After re-reading the section up to the point where the mochiweb JSON functions are introduced and a few trial and error attempts, I found out that cowboy expects the port to be an integer, and when started via the commandline, the options are given as a list of atoms.

This is probably mentioned elsewhere in the book - however for novices who have a grasp of the basics and are jumping around, it would be helpful to have either a comment in the code or an attention box stating this fact and that the two code lines

[ PortAtom | _ ] = Port,
RealPort = list_to_integer( atom_to_list( PortAtom ) ),
and subsequently bind to RealPort, not Port

in the start function will result the expected behavior when launching with the port as a commandline argument.

2013-05-18This is now fixed. You'll see the result in the next release. \n \nI have added a couple of extra paragraphs and a small bit of extra \ncode to deal with this. \n \nThe way of converting arguments was on page 161 in the section \n"Programs with command line arguments" (in section 10.2) \nBut it's a good idea to remind people at this point with an example. \n \nThanks for pointing this out. \n \n \n
61TYPO

BIFs section, second paragraph: “BIFs provided interfaces to the operating system or perform operations that are impossible or very inefficient to program in Erlang.” replace “BIFs provided” with “BIFs provide”.

2013-05-13thanks
63TYPO

First paragraph after the bullet list: “They are include
in this tables for completeness.” “include” -> “included”.

2013-05-13thanks
67TYPO

Penultimate paragraph: “This might lead to a problem in Erlang because if is a expression”: “a expression” -> “an expression”

2013-05-13thanks
67TYPO

Last paragraph: “In the case where A is less or equal
to zero then the if expression would have no value.” rephrase to “In the case where A is less or equal
to zero, the if expression has no value.”

2013-05-13thanks
69TYPO

First paragraph: “The best thing thing to do is […]” delete duplicate “thing”.

2013-05-13thanks
70TYPO

3rd paragraph: “It also has supports records.” rephrase to “It also has a data type called records.” or “It also supports records.”

2013-05-13thanks
85TYPO

Second paragraph: “In a sequential language with only one processes”: “processes” -> “process”.

2013-05-13thanks
85TYPO

Second paragraph: “If we have large numbers of
processes it is not so important if one processes crashes”: second “processes” -> “process”

2013-05-13I reworded this a bit
91TYPO

End of section 6.3: “If you compare this with the output from the try…catch section, you’ll see that that two methods provide differing amounts of debug information.”: “that that” -> “that the”.

2013-05-13thanks
94TYPO

3rd paragraph from bottom: “One the other hand the user […]”: “One” -> “On”.

2013-05-13thanks
435SUGGEST

(In the following // has been replaced with .. in URLs to circumvent pragprogs anti-spam measures)

The text doesn’t specify how the example should be called - some people (such as I) will try to call the html file in the browser directly via file:…path/to/test2.html.

And then nothing will be displayed, as the same origin policy doesn’t recognize file:… and http:..localhost to be the same. Thus the response is filtered out by the browser - and if you’re not thinking about same origin policies, it’s a real headache to figure out (but was essentially my own fault for trying to short circuit the example to get to the part which was of interest to me faster).

Please consider stating explicitly that the page should be called via http:..hostname:1234/test2.html

2013-05-13I've changed the text - see next edition
123TYPO

Bottom of page: “To see the result of pre-
procssing […]”: “pre-procssing” -> “pre-processing”

2013-05-13yes
138TYPO

Explanation of spec plan_route: “Means that if the function plan_route/2 is called with two input input arg-ments”: “input input arg-ments”> “input arguments”.

2013-05-14
146TYPO

Last paragraph: “If
factorial is called with a negative argument the program the program”: delete second “the program”.

2013-05-14thanks
198TYPO

On section 13.2 it is written
process_flag(trap_exits, true)
trap_exits should be corrected to trap_exit
This error appears only once in the book, so it is easy to correct
best
yehuda

2013-05-18thanks
23SUGGEST

In reference to #51265 below: There are two shells available in the Windows distribution. The command-line shell erl.exe indeed does just abort when Ctrl-G is pressed. The GUI shell werl.exe, which is what you get when you click the Erlang icon as suggested, produces the menu described in the book. It might be clearer if you replace “erl icon” with “Erlang icon” since this is what appears in the Windows Start Menu.

2013-05-27Thanks - I've made this change. \n \nThe version of erlang described in the book is werl.exe \n \nerl.exe is equivalent to starting \n \n$ erl -oldshell \n \non a unix system
395TYPO

The supervisor tree is specified with a function of this form:

init(…) ->
{ok, {RestartStrategy, MaxRestarts, Time},
[Worker1, Worker2, …]}.

The init callback method should be:

init(…) ->
{ok, {{RestartStrategy, MaxRestarts, Time},
[Worker1, Worker2, …]}}.

2013-05-18thanks
56TYPO

There’s an extra “you” in the following sentence:
“Do not under any circumstance try to make your own module called lists since if you you make any mistakes in lists you could easily seriously damage the system.”

2013-05-24thanks
58TYPO

Last sentence needs a comma between “generator” and “a bitstring generator”:
“X is an arbitrary expression, and each qualifier is either a generator a bitstring generator or a filter.”

2013-05-24thanks
12TYPO

Maps have talked about -> Maps have been talked about

2013-05-27My goodness somebody reads the change logs - you do have sharp eyes :-) \n \nThanks \n \n
27TYPO

The link to the installation page is wrong

“Object not found”

2013-05-27Some of these links will be wrong. \n \n \nThe book defines where the content will be. Then we'll \nfix the web site. Right now they are out of phase. \n \n \nThe link is now to http://joearms.github.io/installing.html \n
31SUGGEST

“A file server has two parts - a client which runs on one machine, and a server which runs on a second machine. ”

I’d say the program will have two parts. A file server is one of those.

2013-05-27Reformulated as \n \n To transfer files between two machines we need two programs. A client which runs on one machine, and a server which runs on a second machine. \n \n
14SUGGEST

In the shell session at the top of this page, it would be good to show the use of halt(). to exit.

2013-05-27Yup - did this \n
53TYPO

Top of the page: “We call operations such as map and filter that do something to an entire list in one function call as list-at-a-time operations.” - the word ‘as’ is not needed.

2013-05-27Reformulated as \n \nWe refer to ...
58TYPO

c(geomtery) should eb c(geometry).

BTW, the page numbers I use are the physical ones. So 58 is not the page marked 58, but the 58th page (marked 43). This holds ofr all my comments.

2013-05-30Fixed
59SUGGEST

More of a comment really. You say:

“We can easily add tests and perform test driven development without any additional tools. All we need is pattern matching and “=”."

Nice, but if you put your tets code in the same module as your regular functionality, how do you deploy code without its test code? ANd if you put tests in a separate module, they cannot test private functions directly, which is sometimes a problem. Maybe the answer comes later?

2013-05-30I've added a longer comment after this paragraph which will appear \nin the next version. Basically what I describe is just for quick-and-dirty testing. For production code we use different tools.
229TYPO

“number of bits in the expression is be evenly divisible by 8” -> “number of bits in the expression is evenly divisible by 8”

2013-05-30thanks
592TYPO

“Note: The code show here, is a simplified version” ->
“Note: The code shown here, is a simplified version”

2013-05-30thanks
60TYPO

Last sentence should have a colon before the code listing for lib_misc.erl (perms), as used on other listings.
“Let’s use Erlang to find all the permutations of a string
using the beautiful little function perms”

2013-05-30thanks
61TYPO

“perm is pretty neat.” Should be “perms is pretty neat.”

2013-05-30thank you
84SUGGEST

lib_misc.erl

I think the first definition in the eample should be

odds_and_evens(L) ->
odds_and_evens_acc(L, [], []).

rather than

odds_and_evens_acc(L) ->
odds_and_evens_acc(L, [], []).

That avoids relying on overloading and gives the function a sensible name

2013-05-30Yes - it should have a sensible name :-) \n
173TYPO

First sentence: “Let’s forget about programming for while […]”: “for while” -> “for a while”.

2013-05-30yes - thanks
192ERROR

In concurrent program template, the start() method should read:

start() ->
spawn(?MODULE, loop, []).

2013-05-30thanks
210SUGGEST

I’m brand new to Erlang. When the key-value server (socket_dist/kvs.erl) was introduced in Chapter 14, I interpreted the atom kvs as representing the process id everywhere the atom was used throughout the module, including the pattern matches.

With help from the folks on the erlang-questions mailing list, I now know this interpretation is wrong. The atom only represents the pid when used with the send operator (just like the erlang man page says). Everywhere else, in particular, the pattern matches, it’s just an atom.

Because it’s so easy to fall into this trap, I’d like to suggest that it might be helpful to point this out in the text, or in a sidebar, or even in a footnote… unless this is seen as part of the learning process :)

2013-05-30The problem is that atom ! Msg (as opposed to Pid ! Msg) occurs \nmany times in the book. I can't add footnotes to *every* occurrence this would be painful. Getting it right is part of the learning experience. \n
107TYPO

AT the end of section 6.5
“The important thing to remember let it crash.” -> ’The important thing to remember is let it crash."

2013-05-30How could I get that wrong?
113TYPO

“segement” -> “segment”

2013-05-30
189ERROR

I note that the area example given in geometry.erl differs from the process version in area_server0.erl in that the former deals with rectangles and squares while the latter handles rectangles and circles. This is a bit contrary to the text that says “we take the two patterns that were the arguments to the area function and rearrange then”. Also note is ays “then” and should say “them”.

2013-06-02Thanks - fixed now.
195TYPO

“this time we use span(Fun)” should be spawn(Fun)

2013-06-01I re-wrote this bit
94TYPO

In the last paragraph, the sentence “At this point we have only covered errors in sequential programs,” should terminate with a period instead of a comma.

2013-06-01thanks
95TYPO

Replace “loose” with “lose” in “so we never loose them”.

2013-06-01fixed
101TYPO

In the sentence “If the size of a segement is not specified a default value will be assumed.”, segment is misspelled.

2013-06-01thanks
xiiiTYPO

“non” should be “none” in the last sentence.

2013-06-01thanks
430SUGGEST

I’m doing the same according to “Making a local copy of the dependencies.” and found the dependencies with code:get_path().

Then I created a project with rebar, writing rebar.config in this project to use the dependency which is already defined at $home/erl_imports. When I entered “rebar compile”, it told me that “Dependency not available”.

Can you describe more details about this?

2013-06-01The dependencies are the listed in rebar.config file. This has nothing to do with code:get_path(). Dependency not available means can't the \nright files. Best check your rebar.config, delete all fetched files \nand try again. \n
7TYPO

Excessive comma, odd pluralisation, “Erlang was designed for building fault-tolerant Telecoms system, but the same technology can equally well be applied to building fault-tolerant scalable web systems, or cloud services.” I suggest “telecom systems” and deleting both commas.

2013-06-02
17TYPO

Missing period, capitalization, “… identifier of the the server) this identifier is added”. I suggest “… server). This …”

2013-06-02
18TYPO

“freedom to change to underlying protocols” reads oddly, I suggest “… to change the …”

2013-06-02
20TYPO

“(ie which processes known about each”, I suggest “i.e.” and “know about”.

2013-06-02
24TYPO

“In Line two the percent (%) …” I suggest “In line two the …”

2013-06-02
29SUGGEST

Consider including the examples “16 = X + Y.” and “X + Y = 16.” in the pattern matching introduction.

2013-06-02
49TYPO

“The call shop1:total([{milk,3}]) Matches the clause:” I suggest “… matches …”

2013-06-02
50TYPO

“… and the data type that represent a function in Erlang …” I suggest “… represents …”

2013-06-02
70SUGGEST

Final paragraph before Exercises discusses maps and records, but begins with “Erlang has one more data type…” Consider re-writing the paragraph with maps and records on an equal footing.

2013-06-02
73TYPO

“… maps, and in Lua they are called tables, and in Python dictionaries.” I suggest deleting the ‘and’ just before ‘in Lua’.

2013-06-02
76TYPO

“Maps were made available as from version R17 of Erlang.” I suggest removing “as”.

2013-06-02
76TYPO

“… (fully ground means that, that there are no unbound variables in the term).” I suggest “fully grounded” and deleting the comma.

2013-06-02
76TYPO

“… keys are not changed, is a space efficient …” I suggest deleting the comma.

2013-06-02
78TYPO

Is the space between “#” and “{” legal in the Henry8 shell interaction, line 2?

2013-06-02
92SUGGEST

count_characters/2 is more complicated than most code seen so far, and the new maps syntax complicates it further. I suggest explaining small pieces, or showing a version using proplists for comparison.

2013-06-02
79SUGGEST

I don’t see a function in the maps module that returns a default value if the key does not exist. This is quite useful in other languages (Ruby’s Hash.new(…), or Python’s get(key [,default])). Perhaps an explanation of why count_characters/2 works would help me understand why this function is missing from Erlang. (Or, at least, not introduced here.)

2013-06-02maps are still being discussed and implemented. There probably will \nbe such a function in the future but I can't say what now.
81ERROR

“If A and B are maps of unequal size then A < B if maps:to_list(A) < maps:to_list(B).” — the previous line handled unequal sizes. This line should handle equal size maps.

2013-06-02
81TYPO

“continuiously” -> “continuously”

2013-06-02
82SUGGEST

Is the type “map()” correct in the type “json_value()” definition? Or should it be replaced with “json_map()”?

2013-06-02
85SUGGEST

The lead paragraph feels choppy and forced. “… fault-tolerant systems. Systems that …” is probably the point that felt the most awkward to me.

2013-06-02
85TYPO

“… after all, the entire computer …” — I suggest replacing the comma with a colon.

2013-06-02
86TYPO

Missing period at “This rule is called “Let it
crash”".

2013-06-02
126TYPO

Replace “occurrence” with “occurrences” in “Note that if some symbol X occurs only K times in B, then only the first K occurrence of X in A will be removed.”

2013-06-06
228TYPO

First line: three function -> three functions

2013-06-06
94TYPO

“Error messages are programmers gold-dust.” I suggest adding a ’ for “programmers’”

2013-06-06
97TYPO

“Binary are written and printed…” I suggest “Binaries …”

2013-06-06
98TYPO

“… functions from the module binary.erl …” — the “.erl” isn’t needed in this context; the sentence is missing its period.

2013-06-06
101SUGGEST

Immediately after “since the value of Size is unpacked from the first four bits of the binary, and then used to denote the size of the next segment in the binary.” I think it would be fair game to put in something along the lines of, “yes, this is awesome”. Anyone who’s ever seen similar parsing code in C, or worse Java, will be extremely impressed at this point. Might as well gloat a bit. :)

2013-07-15It is nice, but I don't really want to gloat here.
102SUGGEST

“End is big | little | native” — please include a note that the default, Big, is also known as network byte order.

2013-06-06
103TYPO

I suggest deleting the comma in “The final example, shows how to unpack an IPv4 Datagram.”

2013-06-06
108SUGGEST

I suggest re-writing the sentence “The next section covers bitstrings these are used to store sequences of bits.”

2013-06-06
113TYPO

“… we can create “modules with state” this …" I suggest adding a semicolon after “modules with state”.

2013-06-06
123SUGGEST

“Processes can simultaneously run old and new versions of the code.” I think this section needs to mention that code reloads happen with explicit module:function() calls. (Is it even the case that processes are killed when replacement code is compiled? That doesn’t sound right to me.) The sentence quoted gives the impression that a single process can execute both old and new code in a module. I suggest something like “Some processes can execute the old version while other processes execute the new version”.

2013-07-16I changed the text
128TYPO

“… when we compile the code This is …” needs a period.

2013-06-06
131SUGGEST

Some of those operators are definitely awkward for people coming from other languages — >= vs =< and =/= and so on — it might be nice to have some kind of description of the various operators and confirm them.

2013-07-16They are In table 6 page 134 (page number in beta 2) \n
131SUGGEST

“The process dictionary is an associative array …” — I think this section needs some re-writing now that maps are part of the language.

2013-07-16The process dictionary hasn't changed - I think this is ok
132SUGGEST

“References are globally unique Erlang terms.” I suggest being explicit about globally unique — with a cluster? among all Erlang servers everywhere in the world?

2013-06-06To be precise would need a lot of explanation here. \nToo advanced for this book
138TYPO

“… were of type point() We also …” is missing a period.

2013-06-06
143TYPO

In the code for module(a), “Hight::integer()” should be “Height::integer()”

2013-06-06
152SUGGEST

types1.erl bug1/2 and myand/2 example would be more satisfying if the proper -spec() were added and the bug discovered..

2013-07-16
236TYPO

Section 15,1 describes sending massages to ports. Intriguing, but perhaps you meant messages :-)

2013-07-15
161TYPO

Sidebar, “Note the using -compile(export_all)” should be “Note that …”

2013-07-15
163ERROR

Makefile.template uses ‘make’ rather than $(MAKE) to start make in subdirectories; this won’t properly start parallel jobs in the subdirectories, nor will it properly limit the number of jobs started with -j or -l, or pass along the -n, -t, or -q options. $(MAKE) will also use whichever make was used to handle the top-level Makefile, rather than whatever happens to be first in the $PATH.

2013-07-15
166TYPO

“We’ll see how to do this later.” — changing the code search path was already handled in section 10.1, earlier in the book.

2013-07-15You're right. Thanks
175TYPO

“… saying why the first process dies.” should be “died”.

2013-07-15
192SUGGEST

Sidebar “A Concurrent Program Template”; you say you almost always start with that template, but I’d expect actual programs to be written with OTP instead. Is this really a template you use outside of educational examples? :)

2013-07-15No. I think before use the OTP templates you should code in raw Erlang to get a feeling for what is going on.
195TYPO

“Handling Errors in concurrent programs …”, should be “errors”.

2013-07-15
195TYPO

[Same sentence as previous, sorry, bad notes.] “… completely different way of thinking to handling errors in sequential programs.” I suggest adding “than”: “… errors than in sequential …”

2013-07-15
197SUGGEST

The bullet points in “Why Crash?” are a bit awkward; I suggest removing “we just crash” from the first two bullet points.

2013-07-15A bit of repetition here, for emphasis
200SUGGEST

[Only checked in B2.0] The images on this page, and many other pages (but not all), are smeared and unreadable when I use the “Briss” tool to crop margins and read on my Sony PRS-505 reader. Perhaps other readers will similarly fail once Briss has made the PDFs ‘fit’ on screen.

2013-07-15
204ERROR

Line 3 sets up an on_exit() with format string " ~p died with:~p~n" — but note that the error report below line 5 does not contain “died with:” anywhere — where does it go?

2013-07-15It goes to the shell process. But this is killed before the error message can be written
206SUGGEST

“Write a function which creates a global process …” — I don’t think “global process” has been defined at this point.

2013-07-15should be registered process
212SUGGEST

kvs.erl really should use a map rather than the process dictionary. Everything I’ve read about the process dictionary says to not use it, no need to encourage it here.

2013-07-16Right now maps are still not released. So I'd prefer code that can be \nrun *today* - so I haven't changed it. This can be changed when maps are released
215SUGGEST

I’d like to see a mention very near the introduction of -cookie about the security implications of the cookie. I’d also like to suggest that use of Erlang across the Internet be discouraged without an authenticated connection as any intermediate could abuse the connection.

2013-07-16I've added a longer comment about this
233TYPO

“… and sends the a …” delete “the”.

2013-07-15
234SUGGEST

example1_driver.c declares byte buff[100] — and while nowhere near all 100 bytes are used in the code, this buffer isn’t large enough for the {packet, 2} mode used with the port.

2013-07-16
237TYPO

“… MAC OS-X Mountain lion …” -> “Mac OS X Mountain Lion”

2013-07-15
437TYPO

“performed and and the browser” — double `and’

2013-07-15
356TYPO

“Two Property based tools exist for testing Erlang programs QuickCheck with is a commercial program supplied by a Swedish company called Quviq and proper. which was inspired by QuickCheck.”

There should be `which’, not `with’ after Quickcheck. Also
the `dot’ in “…and proper. which…”

2013-07-15
299TYPO

“contains a lot parameters”. `of’ is missing

2013-07-15
431TYPO

“rebar itself uses a program called mech for testing purposes”

Not `rebar’ but `bitcask’. Not `mech’ but `meck’

2013-07-15
372TYPO

handle_call(Stop, From, Tab) returns {stop, normal, stopped, Tab} which stops the server.

There should be an atom `stop’, not the `Stop’ variable.

2013-07-15
435TYPO

//Host/cgi&amp;mod=Modname?Func=Funcname

The URL is bad formed. Should be
//Host/cgi?mod=Modname&amp;func=Funcname

2013-07-15
240TYPO

“… returns you CPU type, …” -> “your”

2013-07-15
251SUGGEST

“(An IO list is a list whose elements are
IO lists, binaries, or integers from 0 to 255.” — is this a mistake or holdover from pre-Unicode days? Or are IO Lists not Unicode-aware?

2013-07-16No - I/O lists are unchanged since unicode arrived.
257ERROR

“A awk style regular expression …” and “Here ShellRegExp is a awk style regular expression that is easier to write than the full form of a regular expression.” Awk regular expressions are the full form of regular expressions — the simplified form used here are shell expansions or glob-style expressions. (The ".erl" example cannot compile in awk, has no preceding character, class, or group to operate on.)

2013-07-16Yes - it's not awk.
263SUGGEST

The “Writing a Web Server” sidebar is in an awkward position — it might be less distracting on the next page.

2013-07-16It might be moved later
266ERROR

socket_examples.erl binds to a port without specifying an IP address; since this server gives eval() access without any access controls of its own it should bind and listen only on localhost.

2013-07-16This is not a bug it's an undocumented feature
267TYPO

“{ok, Listen} = gen_tcp:listen(…),” — this code is placed too far to the left, it gets cut off briss-mangled PDFs, and looks awkward on the printed versions.

2013-07-15
273TYPO

Sidebar, “{N1,N2,N3,N3}” — “N3” is duplicated.

2013-07-15
275TYPO

“… but the individual datagrams, if they arrive, will be undamaged.” Damage is only detected by crc32 — accidental one-bit errors will be caught with probability 1 - 1/2^32 — not bad — but multiple-bit errors are much less likely to be caught, and malicious modifications will never be caught.

2013-07-15
285TYPO

On this page, and several others, “JavaScript” has accidentally been written “Javascript”.

2013-07-15
286TYPO

“The first example, shows in detail …” delete comma.

2013-07-15
288ERROR

“The number 2233 has no particular significance, any unused port number over 1000 would do.” Unix systems reserve ports 1-1023 for the superuser. To be useable by an unprivileged user, the port must be between 1024 and 65535, inclusive.

2013-07-16fixed
301TYPO

“A web browser is, of course a massively complicated object.” delete comma.

2013-07-15
301TYPO

“… we can easily contain this complexity, and harness it …” I suggest deleting the comma.

2013-07-15
308SUGGEST

Sidebar, “… the user must ensure that reads and writes to the table are performed in a consistent manner.” How should a user ensure that reads and writes are performed consistently? There isn’t exactly an easy locking interface in Erlang. I suggest mentioning that this is usually accomplished via Mnesia or via a single owner process that manages all CRUD operations on behalf of others via messaging. Or whatever would actually be useful to ensure this consistency in a language noted for not providing the primitives. :)

2013-07-16There is an easy locking interface. Only one process (the owner of the ets table) can write the table all others can read.
308TYPO

“… we’ll analyze which trigrams. occur in the word.” Delete the period after “trigrams”.

2013-07-15
312SUGGEST

lib_trigrams.erl function open/0 should use filename:join/2 to create the trigramsS.tab file.

2013-07-15
314SUGGEST

lib_filenames_dets.erl function open/1 discards the _Reason given when it cannot open the file; discarding the reason makes it harder for sysadmins or users to correctly use programs — if it fails, the operator has no information to help them correct the problem. If the error message included the filename and the reason for the error, users could fix the problem without resorting to the debugging or error dumping methods discussed elsewhere.

2013-07-15
331SUGGEST

“… “impedance mismatch” … This means that inserting and deleting complex data structures into the database is very fast." Much more important, to my mind, than a fast database insert, is that the code is beautiful. Typical ORM code to manage the mismatch between objects and relational databases is usually not beautiful and quite often frustrating to debug when incorrect.

2013-07-16
336TYPO

“… Erlang distribution site In addition, …” Insert a period after “site”.

2013-07-15
343TYPO

“… depreciated, undefined, and unused functions.” should be “deprecated”.

2013-07-15
356TYPO

“Compile the module. dict.” Delete “dict.”

2013-07-15
370SUGGEST

I suggest swapping the order of these two sentences: “The macro ?MODULE expands to the module name my_bank. Mod is the name of the callback module.”

2013-07-15
384SUGGEST

“firstly” is used without “secondly” nearby. This may have happened elsewhere in the book as well, I don’t believe I wrote down every instance.

2013-07-15
389SUGGEST

The -config elog2 example has been re-run recently and includes a 2013 date; the example examining THELOG are still the original 2009 date. I think it’d be nice if THELOG copy-and-paste also included the corresponding error message created in the interactive shell.

2013-07-15
401TYPO

“… computation was defined (in computer_area/1) …” should be “(in compute_area/1)”.

2013-07-15
406TYPO

“sellaprim” has been used instead of “sellaprime” in the following: “sellaprim_supervisor.erl”, “sellaprim_app.erl”

2013-07-15
408SUGGEST

lib_primes.erl, several issues: (a) where is new_seed/0 defined? (b) many APIs generate horrible random numbers if seeded multiple times — why is it alright to seed this API multiple times? © is_prime/1, is_prime/2, and is_prime/3 are very confusing — variable names are too short to be meaningful, the names change from call to call, the order of the arguments change from call to call, and the comment that “ A is a random number less than N” actually looks like a random number less than K. (d) I’m getting confused by the code in is_prime/3, but it looks like it strongly over-biases towards generating very small values for A. This module feels over-complicated. Please give a try to re-write with more meaningful function and variable names, and definitely explain why calling new_seed/0 multiple times in one process is desirable. Thanks.

2013-07-16new_seed() is in lib_primes. This is a chapter about OTP and not about \nprime number generation - I really don't want to add a lot here which would distract from the OTP discussion. So I would. I corrected the \ncomment and changed N to K.
401SUGGEST

The ‘rectongle’ mistake is left unsolved in this section. It feels very unsatisfying to not show fixing the error and reloading the module on the fly. (Hot code reloading is probably why 1/3 of the readers are reading the book, to guess wildly. :)

2013-07-16I have to leave something for the reader to try for themself
410TYPO

“When a a prime …” delete an “a”.

2013-07-15
417TYPO

“… between machines (Actually IRC …” The capitalization of “Actually” is odd, but I think the better fix is terminating the sentence at “between machines.” and removing the parenthesis around the second sentence.

2013-07-15
418SUGGEST

“Conventionally in a file called mbox. We receive a message, open a file called mbox write the message to the file and we’re done.” The first sentence is a fragment, the second sentence doesn’t flow well. I suggested “We receive a message, open a file (conventionally named mbox), write the message to the file, and close the file.”

2013-07-15
419SUGGEST

“In protocols such as HTTP the input request must be parsed, this is a colossal waste of time since every single input character in the HTTP header must be examined by the parser …” This paragraph is misleading; surely binary_to_term also inspects every single character when it parses network input. (binary_to_term might copy the byte unchanged, but I cannot see how it could do anything other than read every input byte.) I suggest deleting from “In protocols …” to “inherently inefficient.”.

2013-07-15
420TYPO

“… simple statefull counter, …” should be “stateful”. (Granted, my easy dictionaries don’t have “stateful” either, but e.g. Wikipedia has a “Stateful Firewall” entry.)

2013-07-15
423SUGGEST

adapter_db1_test.erl test/0 tries to demonstrate an adaptor API but duplicates the code — it’d be more convincing if it had two portions, one that creates lists or dict-based database, and one that runs through the same API on whatever was handed to it…

2013-07-16
424SUGGEST

“This is not a very good error message.” I suggest “This is a poor error message.”

2013-07-15
425TYPO

“… other peoples code …” should be “people’s”. This may have happened elsewhere in the book, I don’t believe I took notes every time I saw it.

2013-07-16
428TYPO

“Click on the new-repro …” probably “new repo” was meant.

2013-07-15
430TYPO

“… Erlang mailing list, 2 or tweet about it with the hash tag #erlang” — the superscript ‘2’ is in an odd location in the text, and the period is missing after the hashtag.

2013-07-15
430SUGGEST

bertie/bertie.erl, the fetch/1 function should have a corresponding store/2 function, so that start/1 does not need to make the “put” calls itself. Also, “n” is a poor name for a long-term storage slot; I suggest “bertie_executions” instead.

2013-07-15
431SUGGEST

bertie/Makefile will only update the deps when the user explicitly deletes the entire ‘deps’ directory. Is this really the best way to update dependencies?

2013-07-16It's ok for the purposes of the book. This is about Erlang not Makefiles
431SUGGEST

“… unpack it and type make.” What does “unpack it” mean here?

2013-07-15
434TYPO

“… parallel session can be far higher than this.” should be “sessions”.

2013-07-15
434TYPO

“… routines init/2, handle/3 and terminate/2.” The code in cowboy/simple_web_server.erl as reproduced in the book shows init/3, not init/2. There are several references to init/2.

2013-07-15
434TYPO

“… what cowboy calls a “Request Object” The request …" Insert a period after “Object”.

2013-07-15
434TYPO

“handle calls cowboy_req:path(Req) (Line 2) to extract …” I suggest “(line 2)”.

2013-07-15
435ERROR

cowboy/simple_web_server.erl, read_file/1 contains two problems that would probably be reported as security flaws in a real program: (a) does not limit files served to a specific directory structure; .. directory traversal. (b) XSS injection point, “File” is returned to caller without any HTML directive escaping. (These both might seem nit-picking, but I believe text in books should be held to the same standard as programs intended to be deployed by other people.)

2013-07-16I've added this as an additional exercise at the end of the chapter.
435TYPO

“… and make a more useful example:” — I suggest replacing the colon with a period.

2013-07-15
435ERROR

cowboy/cgi_web_server.erl does not show any code for binding only to localhost; any service that grants eval()-level access over a socket should not be bound to all interfaces by default.

2013-07-16Added an exercise at the end of chapter
438TYPO

“… large integers we might run into problem.” should be “problems”.

2013-07-15
438TYPO

“… point numbers might loose precision …” should be “lose”.

2013-07-15
439TYPO

“… to create you own project.” should be “your”.

2013-07-15
439TYPO

“… examine the contends.” should be “contents”.

2013-07-15
439TYPO

“Make you own self-executing …” should be “your”.

2013-07-15
442TYPO

“… no mutable data structures(that’s not …” insert space before parenthesis.

2013-07-15
444SUGGEST

Sidebar, multicore CPUs: most smartphones sold today are dualcore or even quadcore. Even cheap and power-miser devices are going towards multicore.

2013-07-16Yes - changed the side bar to add comment about smartphones
445SUGGEST

Pages 445, 446; the ‘protected’ paragraph mentions “corrupted”, but one hopes a single process could not do this. What would be more likely would be non-atomic updates that are inconsistent when viewed part-way through completion. That’s not corrupted. The ‘private’ paragraph is actually half about DETS shared tables. I think this little section needs a dedicated edit pass. Thanks.

2013-07-16I'm not going to change this. A full description would be too long here. \n
447TYPO

“If you Google this term, …” “Google” is a trademark, and doubtless the Google lawyers will remind you that it should not be used as a verb in place of “Search”. :) (Though the whole sentence could be removed without loss.)

2013-07-15
447SUGGEST

“Remember the emphasis we made …” — I feel like “remember” when used in this fashion needs to raise a question. I suggest “Recall” instead.

2013-07-15
452ERROR

runtests starts the timing without explicitly warming up the cache: the first case might be run on a cold cache and thus look artificially very expensive compared to the second run. Running the erl -boot … step once, before the for loop, and discarding the results, would warm the cache before data collection begins.

2013-07-16This is a book about erlang - not about performance measurements. \nSometimes you have to leave things out since otherwise the book would become unbearably long
458TYPO

“This chapter, has shown how …” delete comma.

2013-07-15
458TYPO

“… standard libraries, and the major …” delete comma.

2013-07-15
459TYPO

Twice, “worse case” is used instead of “worst case”.

2013-07-15
462TYPO

This sentence is missing its quotes: “It’s the term frequency
times the inverse document frequency, I shall explain …”

2013-07-15
465SUGGEST

“The highest numbers is posting number 7260 with a similarity weight of 0.27.” I suggest “The highest weight is …” or “The heaviest weight is …”

2013-07-15
470TYPO

“So if a document, contains the word …” delete comma.

2013-07-15
292TYPO

R17 is expected in 2103. I can’t wait that long.

2013-07-15Patience, my friend.
23TYPO

Text “doing A and B will take only take fifteen seconds” should be either “doing A and B will take only fifteen seconds” or “doing A and B will only take fifteen seconds”.

2013-07-15Thanks
215TYPO

It looks like an extra line-break-and-indent:

pastie.org/private/p9u7fxl9lfup8omj89ufq

Per the first-edition of the book, the general form is:

pastie.org/private/pwupmirvhnohijjmfi52fq

2013-07-16
215ERROR

Registering the process (associating an atom with a process), causes keep_alive/2 to crash after about 175k - 200k iterations with the following error:

=ERROR REPORT 10-Jul-2013::21:04:44 ===
Error in process <0.6372.224> with exit value: {badarg,[{erlang,register,[f,<0.6373.224>]},{lib_misc,keep_alive,2}]}

See:

pastie.org/8130141

If I remove the registration, it works fine. (I let it run to about 1.3 million iterations w/o fail.)

2013-07-16This looks like an erlang bug - not a book bug
379TYPO

Link at bottom of page in reference 3 is not correct. Leads to an error:

Object Not Found
The requested URL /doc/pdf/design_principles.pdf was not found on this server.

2013-07-15
217TYPO

Exercise 5:
Write a function that starts and monitors several worker processes. If any of the worker processes dies, abnormally restart it.

“abnormally restart it” — was this intentional? What does it mean to “abnormally restart” a process?

2013-07-15
xviiiTYPO

In the acknowledgements for the second edition, there is a comma missing between the names of Kurt Landrus and Kenneth Lundin.

2014-08-06
14TYPO

code sample has halt() without the dot at the end

2014-08-06seems ok to me
79TYPO

what’s up with count_characters/3?
I’m guessing
count_characters(T, #{ H => 1 }, X));
should be
count_characters(T, X#{ H => 1 });

2014-08-06This is problematic. Keys in maps used outside the map are currently illegal \nbut I hope this situation will change in a future not too distant release of Erlang. \n \nAt this stage I don't want to change the text - even though it is incorrect.
306ERROR

In section 19.1, under “Insert a tuple or several tuples into a table” and “Look up a tuple in a table”, it stated that insert(Tablename, X) and lookup(Tablename, Key), but should it be insert(TableId, X) and lookup(TableId, Key)?

The the ets_test.erl example, it is also stated as TableId, not Tablename.

2014-08-06
44SUGGEST

I think the explanation of where to use the comma should be mentioned before showing the example where it is used (in the test function), otherwise it might cause some confusion..

2014-08-06I've used the convention 'first show the code' then explain. Often you can guess \nthe meaning of the code from the example, so you can skip over the explanation \nI don't want to change my convention - so I have made no change
68TYPO

“Or course, if they want an exception…” => “Of course, …”

2014-08-06
116TYPO

In example on page 116 there is “{version, ”4.8“}” and on page 117 among the text there is “The value {version,”4.5.5“} is the version of the compiler(..)”.
Should they both be 4.8 (or 4.5.5)?

2014-08-06they should both be 4.8
138ERROR

At bottom of the page:
spec plan_route(From:: point(), To:: point())> …
should be
spec plan_route(From::point(), To::point())> …

2014-08-06
160ERROR

While running script ‘hello’ which contains main(Args) interpreter produces a warning:
./hello_escript.erl:3: Warning: variable ‘Args’ is unused
better will be main(_Args).

2014-08-06
280TYPO

In wait_for_ref/2 function closing end of case statement has semicolon. Erlang compiler reports errors:

udp_test.erl:62: syntax error before: ‘after’
udp_test.erl:47: function wait_for_ref/2 undefined

So shouldn’t it be witohut semicolon like that:
(..)
end
after 1000 ->
(..)
?

2014-08-06
15SUGGEST

“The code for a process is contained in a module and to create a process we call the primitive spawn(…) which actually creates the process.”

Information about creating the process is mentioned twice in one sentence.

2014-08-06It's ok I think. If I replaced the second 'process' by 'it' there might be confusion. \nIs 'it' a module or process.
297SUGGEST

Some parts of codes showed in chapter 18 are out-dated with code stored on Github, for example at page 297 at the beginning of listing of websockets/chat2.erl we have:

start(Browser) ->
idle(Browser).

while on Github we have:

start(Browser) ->
case whereis(irc) of
undefined -> irc:start();
_ -> true
end,
idle(Browser).

2014-08-06The github code is being improved. The book code is frozen when the book \nis published. There is no automatic syncing of the two. The book is internally \nconsistent - but might disagree with code on github.
421TYPO

At the top of page:
“In lines 12 to 13 (..)”
should be:
“In lines 14 to 15 (..)”

2014-08-06
425ERROR

In listing of adapter_db1_tester.erl there should be store/3 imported from adapter_db1, not store/2

2014-08-06fixed
311SUGGEST

Among the text there is “for_each_trigram_in_the_english_language(F, A)” shouldn’t it be “for_each_trigram_in_the_english_language/2” ?

2014-08-06No I use the first form with variables when I refer to F and A later in the text
164ERROR

“see the online tutorial[4] for more details”
[4] …parser_tutorial-1.0.tgz - dead link

2014-08-06I'll try and get them back ... at this link
310ERROR

From jaerlang2-code.tgz, 354984si.ngl.gz is broken.

gunzip -t 354984si.ngl.gz

gzip: 354984si.ngl.gz: invalid compressed data—crc error

gzip: 354984si.ngl.gz: invalid compressed data—length error

2014-08-06This works for me \n \nCheck the file you got was correct. The MD5 sum is below \n \nmd5 354984si.ngl.gz \nMD5 (354984si.ngl.gz) = 103e17cb6610f31106f201f5af4d1dd7 \n \nIf this is wrong the file was corrupted somewhere. \n \n \n
206TYPO

In the end of the page, this code:

4> Pid ! hello.
hello
5>
=ERROR REPORT 14-May-2013::10:05:42 ===
Error in process <0.36.0> with exit value:
{badarg,[{erlang,list_to_atom,[hello],[]}]}

should be something like this:

4> Pid ! hello.
<0.36.0> died with:{badarg,[{erlang,list_to_atom,[hello],[]}]}
hello
5>
=ERROR REPORT 14-May-2013::10:05:42 ===
Error in process <0.36.0> with exit value:
{badarg,[{erlang,list_to_atom,[hello],[]}]}

The secondo line

<0.36.0> died with:{badarg,[{erlang,list_to_atom,[hello],[]}]}

is missing in the current version.

2014-08-06
209TYPO

“If the process dies before on_exit gets evaluated, then a link will be not be created.”

2014-08-06What was wrong here? . I see no error
70TYPO

In the second paragraph, “This is a consequence of the way that the list was constructed. If we want the list elements in the same order as they were in the original, all we have to do is reverse the lists in the final clause of the function by changing the second clause of odds_and_evens2 to the following:”, odds_and_evens2 should be odds_and_evens_acc.

2014-08-06
68TYPO

The very last sentence of section 4.7 refers to “the following tables list all the guard predicates…and all the guard functions”, but these tables appear on a previous page (66).

2014-08-06
82TYPO

ASCII decimal value 101 is ‘e’, and 104 is ‘h’. The book states that 101 is ‘h’.

2014-08-06yes h is 104
378TYPO

The link erlang.org/doc/pdf/design_principles.pdf is broken. I assume it’s similar to erlang.org/doc/design_principles/des_princ.html, except that it should be a PDF file.

2014-08-06I don't know where this has gone - I'll investigate it should be there \n \nThe book is frozen on publication - these links get changed later by people \nwho do not know that the links should not move
66ERROR

is_bitstring/1 is missing from Table 1, which purports to list all legal guard predicates. Current Erlang documentation has is_bitstring/1 and notes that it is guard-legal. (is_bitstring/1 is also used on PDF page 110, although not in a guard context).

www.erlang.org/doc/man/erlang.html#is_bitstring-1

I think this was an inadvertent omission: Table 1 is explicitly intended to be complete (and even includes is_pmod, although parameterized module support has been removed from the language).

Excellent book—one of the best programming books I’ve read, and moving me quickly towards my alpha launch!

2014-08-06
76TYPO

In chapter 5.2 rr() function suggested as shell command for record definition, but rd() should be used in last versions of Erlang.

2014-08-06I tested this rd failed rr worked.
268ERROR

lib_misc:string2value(Str) is referenced in the nano_server example, but it is not defined. Later, the author defines string2value/2 which requires some adaptation to work in the context of the nano_server.

2014-08-06strong2value/2 is also not defined - but both string2value/1 and string2value/2 are in lib_misc.erl which can be downloaded from the prag web site in the code \nthat follows the book
115TYPO

“This specifies the endianess of the machine. ”

I think “endianess” might be “endianness”.

2014-08-06
147TYPO

Page 147 bottom half: “creates an opaque types called rich_text()”. It should be “type” not “types”.

2014-08-06
9380TYPO

When updating a map is first introduced, the following example is used:

5> F3 = F1#{ c => xx }.
#{ a => xx, b => 2 , c => xx}

The response from the command is wrong though, it should return:
#{ a => 1, b => 2 , c => xx}

2014-08-06
111TYPO

In the “Bit-Level Storage” section, the sentence with “they have to masked out and shifted into registers” should be “they have to be masked out and shifted into registers.”

2014-08-06
81ERROR

Pattern Matching the fields of a map: In R17rc1 you must use := (not =>) in map patterns.

2014-08-06
83ERROR

BIFs that Operate on Maps: In R17rc1 maps:map_size is named maps:size and maps:difference is missing.

2014-08-06I've change map_size to size. difference should be added to the maps library so I'll leave this
52SUGGEST

Funs: You may want to add a description of funs with names here.

F = fun Fact(0) -> 1; Fact(N) -> N * Fact(N-1) end.

2014-08-06This would need a lot of explanation. I can only make small changes in this edition. This is something for a third edition :-)
197TYPO

I looked through it and noticed that loop is taking an argument X that it does nothing with and the spawn in start do not send any arguments which is why it’s throwing errors. The code is from the “A concurrent program template” on page 197.

-module(week6).
-compile(export_all).

start() ->
spawn(?MODULE, loop, []).

rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
{Pid, Response} ->
Response
end.

loop(X) ->
receive
Any ->
io:format(“Received:~p~n”,[Any]),
loop(X)
end.

2014-08-06
N/ASUGGEST

In a future edition of the book, it would be good to have a chapter dedicated to testing and the different test frameworks available. In particular, I would be interested to see examples using EUnit and Common Test with a discussion of when is it appropriate to use one or the other.

2014-08-06I think these topics should be in separate books - not in a new edition of this book
110TYPO

In 7.1 Binaries Section,the code snippet

1> <<5,10,20>>. <<5,10,20>>
2> <<“hello”>>. <<“hello”>>
3> <<65,66,67>> <<“ABC”>>

The third code snippet miss a period.It should be:
3> <<65,66,67>>. <<“ABC”>>
^

2014-08-06
79ERROR

The third in the list of map properties states that a key can be any //fully ground// term. However, as of 17rc1, no variables can be used in maps:

1> K = 1.
2> #{K => one}.

  • 1: illegal use of variable ‘K’ in map
2014-08-06I think this is a bug in erlang not the book. Maps should allow this, there is \nno good reason not to allow this. I won't change the text.
82ERROR

Because variables can’t be used in map keys in 17rc1 or rc2 (see errata for p. 79), count_characters/2 is triply broken. The head of its first clause depends on a fairly sophisticated pattern match (H is bound in the first argument, and used as a ground match key in the second), which fails as “illegal use of map”. Both the first and the second clause also use H in the clause body (to increment and to add, respectively), and fail for the same reason.

Additionally, the text claims that “the second clause use[s] map_extend to add a new key.” My best guess is that map_extend was meant to be the maps:put/3 BIF, which would have that effect (but which isn’t mentioned in the list of BIFs, which nonetheless contains maps:get/2. However, the second clause, as written, doesn’t call a BIF; instead, it uses the more idiomatic update syntax, X#{ H => 1 }.

The following version of count_characters/2 seems to work OK in 17rc2 (and does use a BIF in the equivalent of the second case clause).

count_characters([H|T], X) ->
count_characters(T, case maps:find(H, X) of
{ok, N} -> maps:update(H, N+1, X);
error -> maps:put(H, 1, X)
end);
count_characters([], X) ->
X.

I’m being picky because these (otherwise excellent) few pages are a good portion of the total documentation on maps (as of March 2014). I’m sure this will change after R17 is out of rc.

2014-08-06All your comments are completely correct. My hope is that Erlang will be \nchanged to correspond to the text in the book. \n \nI don't want to update the book text with your correct version, since I hope the \nimplementation will be fixed soon.
84ERROR

The JSON bridge stuff doesn’t seem to have made it into R17 after all, which means this whole section is off (for now).

2014-08-06One day JSON bridge stuff will be added to the libraries I hope. So leaving it in the book might encourage this :-)
223215TYPO

The node name is specified as ‘gandalf’ (-sname gandalf) which is then correctly displayed in the terminal output. However, in the second last paragraph, (“Important Note”), the node is referred to as ‘gandolf’ instead of ‘gandalf’.

2014-08-06
206ERROR

In 13.7 ([Concurrent] Error Handling Primitives), spawn_monitor/1 and /3 are shown returning {Pid, Ref}. The book states that “Pid is the process identifier of the newly created process, and Ref is a reference to the process.”

If I understand correctly, Ref is a reference to the monitor, not the process. (See www.erlang.org/doc/man/erlang.html#spawn_monitor-1).

This is more confusing than it would be otherwise because monitor references aren’t mentioned in 13.2 (definitions) or 13.6 (the section on monitors).

It might also be worth mentioning monitors in 8.22 (References) since the monitor system is a clear internal use of them.

2014-08-06
206TYPO

Tiny wart in 13.7:

spec spawn_link(Mod, Fnc, Args)> Pid

but

spec spawn_monitor(Mod, Func, Args)> Pid

The second parameter to MFA BIFs is consistently spelled Func (except for -spawn_link).

2014-08-06
208ERROR

Error #52624 (reported by Riccardo Marotti on B6.0 book page 206) is still alive in P1.0 on PDF page 208.

The output of the handler function passed to on_exit (“~p died with:…”) is missing from the shell output, which includes only the error report. This is confusing because setting up the handler function is the whole point of that section, and from the listed output it appears the the function didn’t fire.

2014-08-06
49ERROR

Missing period (.) in the last expression in this code example:

case f(…) of Pattern1 ->
Expressions1;
Pattern2 ->
Expressions2;

LastPattern ->
LastExpression % Missing a period after this expression
end

2014-08-06No - it could be a comma. It's a period if it's the last expression in a sequence \notherwise a comma. The expression itself has no period.
0TYPO

Reading the Kindle version- no page numbers. But it’s section 23.6:

“This is shown in the first line of the function_clase error message”

I believe that should be “function_clause”.

2014-08-06
5.3ERROR

Kindle version. Section 5.3.

Under “Maps in Other Languages”:
D1 = {status=> ‘old’, status=>‘feed cats’}

Missing the # before the opening { ?

2014-08-06
209TYPO

"
following two lines of code:
Pid = register(…)
on_exit(Pid, fun(X) -> ..),
"

The line in the middle should be “Pid = spawn(…)”.

2014-08-06the code was \nregister(Name, Pid = spawn(Fun)), \non_exit(Pid, fun(_Why) -> keep_alive(Name, Fun) end) \n \nPid gets assigned inside the call to register, so the code is correct
408SUGGEST

In this page of the book there is an explanation about monitor application (appmon), I think it should be explained the change made in v17 about appmon, that is removed and changed by observer. I don’t mean removing the appmon, but explaining this change. In page #338 the observer is used for table viewer, so that is why I think it would be more clear.

Thank you.
Best regards.

84ERROR

The maps module does not contain any BIFs for converting to and from JSON.. and according to this thread from February on the erlang-questisons mailing list ( http : //erlang.org/pipermail/erlang-questions/2014-February/076936.html ), it will not do so in the future, either.

82ERROR

The character count example not compile.

-module(count).
-export([count_characters/1]).

count_characters(Str) ->
count_characters(Str, #{}).

count_characters([H|T], #{ H := N }=X) ->
count_characters(T, X#{ H := N+1 });
count_characters([H|T], X) ->
count_characters(T, X#{ H => 1 });
count_characters([], X) ->
X.

The resulting output is:

Erlang/OTP 17 [erts-6.1] [source] [64-bit] [smp:8:8] [async-threads:10] [kernel-poll:false]

Eshell V6.1 (abort with ^G)
1> c(count).
count.erl:7: illegal use of variable ‘H’ in map
count.erl:8: illegal use of variable ‘H’ in map
count.erl:8: variable ‘N’ is unbound
count.erl:10: illegal use of variable ‘H’ in map
error
2>

160TYPO

The section that reads: “The two most common functions that we use to manipulate the load path are as follows:
-spec code:add_patha(Dir) => true | {error, bad_directory}
Add a new directory, Dir , to the start of the load path.
-spec code:add_pathz(Dir) => true | {error, bad_directory}
Add a new directory, Dir , to the end of the load path.
Usually it doesn’t matter which you use. The only thing to watch out for is if using add_patha and add_pathz produces different results.”

contains illegal erlang (=>) and the two functions return identical results in my version of erlang (17.1).

10290TYPO

At the bottom of the page in the last paragraph we have FuncOrExpessionSeq instead of FuncOrExpressionSeq.

38TYPO

Missing opening [ at the beginning of the response to 3>

184 TYPO

Probably a mismatch:

3> Pid ! {square, 12}.
Area of square is 144
{square, 144}

The return value of Pid ! {square, 12} should be {square, 12} instead of {square, 144}. That follows from the ! operator declaration and practice checking.

378ERROR

The URL for the design_principles.pdf is invalid (in footnote)

292ERROR

compile error for clock1.erl:

$ erlc clock1.erl
clock1.erl:18: illegal pattern
clock1.erl:27: illegal pattern

#18: {Browser, #{ clicked => <<“stop”>>} } ->
#27: {Browser, #{clicked => <<“start”>>} } ->

I changed “=>” to “:=” to correct the compile error.
#18: {Browser, #{ clicked := <<“stop”>>} } ->
#27: {Browser, #{clicked := <<“start”>>} } ->

On OSX Yosemite 10.10.2
Erlang/OTP 17 [erts-6.3.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

82ERROR

In the description of the maps:from_list function, the description of how duplicate keys in the list are handled is incorrect. “If the same key occurs more than once, then the value associated with first key in the list will be used…” In version 17.5, the new behavior is, “[i]f the same key appears more than once, the latter (rightmost) value is used and the previous values are ignored.”

468ERROR

Cross product is wrong. It should be called dot product. The code correctly calculates the dot product. See also HTTP://nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf on (printed) page 124.

467TYPO

In the second Paragraph of “Similarity Queries” is written:
“They we compute the cosine…”, which should be “Then we compute the cosine…”.

119TYPO

in example code shows version number to be 4.8 then describes the version number as 4.5.5

133TYPO

comma is missing between = and ! in table.
could lead to confusion of a possible operator of =! type

218TYPO

The example code shows using rpc:call as such:

1> rpc:call(gandalf@doris.myerl.example.com, kvs,store,[weather,cold]).

But this will give an error like:

  • 1: syntax error before: ‘.’

Should the node names containing dots be quoted?

1> rpc:call(‘gandalf@doris.myerl.example.com’, kvs,store,[weather,cold]).

403ERROR

On sellaprime.app codewhere is sellaprime_super I think it should have sellaprime_supervisor.

295TYPO

first line of receive block has too many } brackets

133ERROR

Calculation error:

- 36#wow is said to be equal to 42368.
- 36#wow is equal to 30363.

168ERROR

bottom note 4 : the link
h t t p://www.erlang.org/contrib/parser_tutorial-1.0.tgz
is broken : error 404

515SUGGEST

I knew that erlc is used to compile from the command line, but was looking for parameters, and could not find erlc in the Index.

==> erlc should be added in the Index

237SUGGEST

Bottom of the page : The C program has three files.

But on page 241, ports/Makefile.mac has a rule

example1_drv.so: example1_lid.c example1.c

and ports/unit_test.erl uses example1_lid. What is it ? The test crashes.

To make it work, I had to remove references to example1_lid, please visit

h*ttps://forums.pragprog.com/forums/256/topics/14309

315ERROR

The example failed in line 85 of lib_trigrams.erl :

Bin = zlib:gunzip(Bin0),

Maybe the zip utility used to compress 354984si.ngl.gz is not compatible.

I had to re-download the file from the Moby site. Please visit
h*ttps://forums.pragprog.com/forums/256/topics/14315

84ERROR

The whole section “The JSON Bridge” seems to have become irrelevant.
According to the discussion on the mailing list,
http:_erlang.org_pipermail_erlang-questions_2014-February_076936.html (replace ’’ with ‘/’), the JSON functions “maps:to_json(Map) -> Bin”, “maps:from_json(Bin) -> Map” and “maps:safe_from_json(Bin) -> Map” are no longer part of the Maps library.

137TYPO

In the section 8.25 Tuple Modules, the paragraph “…, in which case the function Mod1:f(Arg1, Arg2, …, Arg3, M) is called.” contains wrong argument Arg3 instead of ArgN.

11ERROR

The link in the third paragraph to install Erlang is broken. It returns a 404 error.

80ERROR

In the section “The Semantics of Maps” on erl line 6, the example of using := on a nonexistent key is missing the dot whitespace at the end.

153ERROR

The functions f1/1, f2/1 and f3/1 in dialyzer/types1.erl are using the wrong calculation if they are trying to compute the number of seconds. All three have “(H+M*60)*60+S” but it should be “(H*60+M)*60+S”

266SUGGEST

In the code for nano_get_url/1 in socket_examples.erl, many web servers are not dealing with HTTP 1.0 requests anymore. Several sites that I tried responded with 403 or 404 responses. Modifying the gen_tcp:send parameters to use HTTP 1.1 is more successful.

ok = gen_tcp:send(Socket, “GET / HTTP/1.1\\r\
Host: ” Host “\\r\
\\r\
”),

The code does wait for the connection to time out so some additional code would need to be added to close the connection after the response is received and not wait for the timeout.

270SUGGEST

in the loop/1 function called from start_nano_server/0 in socket_examples.erl, it calls lib_misc:string2value/1. It might be nice to explain the logic of this function and show its source.

325SUGGEST

In the vicinity of the definition for do_this_once/0 in test_mnesia.erl, it would be helpful to know that the record definition for “design” is mentioned later in the text so that the reader knows where it comes from.

326TYPO

The code snippet from test_mnesia.erl repeats the definition for demo/1. I believe you wanted to have the code for start/0 and reset_tables/0 there.

392TYPO

In the printout of the rb:help() function, the documentation for rb:start() shows up as a line typed into the interpreter instead of a line output by the help function.

407ERROR

In section 23.8 where you list the files in an app, you list elog4.config but in all your example erl sessions, you use elog3.config. I thought it was a little odd given that you had shown us elog4.config back on page 392 but then the following erl sessions all used elog3.config.

58TYPO

At the bottom of p. 58, there is a code example with the heading shop2.erl. The example specifies the following import annotation:

-import(lists, [map2, sum/1]).

I think that line should import the mylists module —not the lists module, i.e.:

-import(mylists, [map2, sum/1]).

My reasoning is that the section starts off on p. 57 by saying:


4.4 Simple List Processing

…we can get back to writing sum and map, which we’ll need for our improved version of total….
——

To me that implies that when we rewrite total(), we are going to use the versions of sum() and map() that we write, i.e. the version in the mylists module. However, the example just uses the versions of sum and map in the stdlib.

58TYPO

At the bottom of p. 58, there is a code example with the heading shop2.erl. The example specifies the following import annotation:

-import(lists, [map2, sum/1]).

I think that line should import the mylists module —not the lists module, i.e.:

-import(mylists, [map2, sum/1]).

My reasoning is that the section starts off on p. 57 by saying:


4.4 Simple List Processing

…we can get back to writing sum and map, which we’ll need for our improved version of total….
——

To me that implies that when we rewrite total(), we are going to use the versions of sum() and map() that we write, i.e. the version in the mylists module. However, the example just uses the versions of sum and map in the stdlib.

58SUGGEST

Well, it looks like my previous errata #81096 is not validated by the text on p. 59, which doubles down and directs the reader to examine the import annotation and to note that it imports “lists”. That seems to suggest that the author intended to import lists and not mylists on p. 58.

15SUGGEST

In Chapter 2, in the file server example, while careful reading does indicate the file:read_file() returns a tuple composed of the result and the bytes read, only the bytes read should be sent to the client. As there has been no discussion of tuples, a newbie (like me) wouldn’t really notice this significance of of sending back the tuple to the client. It was only when attempting to write the put_file, and actually trying to write the file to disc that I discovered the problem. It took a bit of persistence, but once I realized the return value was a tuple, and by looking ahead in the next chapter, I was able to find out how to get hold of only the file contents. Perhaps, the example should be changed to explicitly pull the bytes read from the tuple to provide a realistic example, as well as avoiding confusion.

103ERROR

On the bottom of p. 103, the book says,


The value of Size specifies the size of the segment. The default value depends on the type…..In pattern matching, this default value is valid only for the very last element.
———-

Here is an example that I think disproves the statement that in pattern matching the default value “is valid” only for “the very last element”:

1> Bin = <<97, 98, 99>>.
<<“abc”>>

2> <<X/integer, Rest/binary>> = Bin.
<<“abc”>>

3> X.
97

4> Rest.
<<“bc”>>

It seems to me that X is not “the very last element”, and yet the default size “is valid” for X. On the other hand, I may not understand what “is valid” means or what “the very last element” means.

103SUGGEST

On the bottom of p.103, I’ve come to the conclusion that the following statement is erroneous:

“In pattern matching, this default value is valid only for the very last element.”

That statement led to much needless confusion for me. In fact, the shell gives an error message that is more informative than this section in the book:

8> Bin = <<97, 98, 99>>.
<<“abc”>>

9> <<B/binary, X/integer>> = Bin.
“a binary field without size is only allowed at the end of a binary pattern”

In my opinion, that error message should be substituted into the book for the sentence I quoted above.

Also, I think this section needs at least two examples to help understand what the text is trying to explain about the default Size:

1) Constructing a binary with one segment being a binary:

1> Bin = << 17/integer, 3.2/float, <<97, 98, 99>>/binary >>.
<<17,64,9,153,153,153,153,153,154,97,98,99>>

2> size(Bin).
12

2) Showing the neat feature when you specify a segment with a binary type at the end of a pattern:

7> Bin = <<97, 98, 99>>.
<<“abc”>>

8> << X/integer, Rest/binary >> = Bin.
<<“abc”>>

9> X.
97

10> Rest.
<<“bc”>>

Besides those two minimal examples, I think it would be nice to see a simple example demonstrating how the TypeSpecifierList works (Endian-Sign-Type-Unit), including how Size and units interact to determine the total size of a segment—-before embarking on the more complex examples.

And I think at least briefly mentioning what happens when you specify a Size that is too small to contain an integer would help with clarity. That’s one of the first things I wondered about.

9481TYPO

2> #{ born => B } = Henry8.
returns: “* 1: illegal pattern”

It should be:
2> #{ born := B } = Henry8.
returns: “#{born => 1491,class => king,died => 1547}”

Note: I’m using Erlang/OTP 19 [erts-8.2] in OSX

Great book by the way :D

275SUGGEST

Paraphrasing:
—-
If the socket was opened in passive mode, then gen_tcp:recv(Socket, 0) will return “all available bytes”.
—-

A book about Erlang should try to explain the confusing aspects of a topic, and the phrase repeated from the docs “all available bytes” has absolutely zero meaning. The key thing your readers need to know is: specifically, how many bytes is “all available bytes”?

For instance, what does “all available” bytes mean when {packet, 2} was specified? In that case, I think “all available bytes” means: the number of bytes specified by the Length in the first 2 bytes of a message. I think Erlang reads the first 2 bytes to get the Length of the message, then Erlang internally loops over a recv() and reads the indeterminate size chunks that a message was split into when it was transported by a TCP connection, until Erlang reads Length bytes, upon which time gen_tcp:recv(Socket, 0) returns Length bytes.

Next, what does “all available” bytes mean when {packet, 0} was specified (or spelled another way {packet, raw} )? In that case, a message is not preceded by its length. So I think that gen_tcp:recv(Socket, 0) will return one chunk of a message, and the chunk will be of indeterminate length. As a result, in order to read the whole message you would need to loop over gen_tcp:recv(Socket,0) until you have read the entire message. But how do you know when you have come to the end of the message? I think the “marker” for the end of the message is: the other side closed the socket.

266TYPO

In the code example (marked with a circled 5):

lists_to_binary(reverse(SoFar))

Change “reverse” to “lists:reverse”.

276SUGGEST

Request for clarification.

The 4th paragraph says:
——
The client will block until the server has called recv.
—-
Wow! Important point! Presumably the client will block on send(). Why not make that explicit?

The text continues:
—-
Note that the OS does some buffering that allows the client to send a small amount of data before it blocks even if recv has not been called.

I read that 20 times and I couldn’t understand it, but I think typing it out just now helped me understand what it means. My mental model of send() was that it transferred data to the server (then the client went merrily on its way), and I never considered where the data was stored on the server, then when the server wanted to read the data it called recv(). Now that I think about it, my mental model of send() suffered the same problem as message passing: a client could flood the server with data.

I think what the quoted text implies is that send() doesn’t actually transfer data to the server. Instead, the data remains at the client until the server calls recv(), then the recv() pulls the data from the client to the server. The quoted text above is qualifying that implication by noting that somehow send() will push a small amount of to the server due to OS buffering before send() blocks.

In my experience buffering usually prevents data from being transferred as quickly as you would expect, so I don’t understand how Erlang’s send() seems to have the opposite problem—but at least now I think I understand what the quoted text is trying to say.

287TYPO

Exercise 2 at the bottom of the page says:


Enter the code for A Simple TCP Server, on page 269.

The code is actually on p. 270, and it’s called start_nano_server() in a module called socket_examples.erl. Personally, I would drop the name “nano” from all the function names in the chapter.

218ERROR

Thanks Scott Baron!! I got the same error:

  • 1: syntax error before: ‘.’

If I atom quote the fully qualified node name in rpc:call(), then the error goes away.

Because the instructions in the book are woefully inadequate, I thought I would post what worked for me. I used two Macs that were both connected to the same home wifi network, which is likely a more common setup than a LAN.

Mac#1 (the Server, iMac running OSX 10.7.5/Erlang 19.2:
—————————-
1. System Preferences > Security & Privacy > Firewall:
—Turn Off Firewall

2. System Preferences > Sharing:
—Check Remote Login checkbox.
—Allow access for: Only these Users: Select a user whose password you know
—The green light next to “Remote Login: On” should be lit.
—Underneath the green light it says: To log in to this computer remotely type:
“ssh FirstLast@new-host.home”.
You will use whatever it says on that line (without the quotes) for starting an ssh session.

Mac#2 (the Client), Macbook Pro running OSX 10.10.5/Erlang 19.2:
——————————-
1. Open a Terminal window.

2. Start an ssh session:
~$ ssh FirstLast@new-host.home

(The first time I opened an ssh session, I was presented with a message that said something like, “blah blah keys couldn’t be verified. Continue (yes/no)?” I typed: yes)

Password: <enter password for the User chosen in step #2 for Mac#1>
Last login: Mon Dec 1 11:30:22 1900 from MyMB.home

~$ cd erlang_programs/ (this is the directory on Mac#1 that contains kvs.erl and kvs.beam.
~/erlang_programs$ ls
kvs.beam\tkvs.erl

~/erlang_programs$ erl -name gandalf -setcookie abc
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.2 (abort with ^G)

(gandalf@new-host.home)1> kvs:start().
true
(gandalf@new-host.home)2>

4. Open another Terminal window.

5. It doesn’t matter what directory you are in:

$ erl -name bilbo -setcookie abc
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.2 (abort with ^G)

(bilbo@MyMBP.home)1>

6.
(bilbo@MyMBP.home)1> rpc:call(‘gandalf@new-host.home’, kvs, store, [weather, cold]).
true

Note that the fully qualified host name needs to be atom quoted—otherwise you will get the error: * 1: syntax error before: ‘.’ Also, note that the fully qualified host name that worked for me is the exact same thing appearing in the prompt for the ssh session in the first Terminal window.

7.
(bilbo@MyMBP.home)2> rpc:call(‘gandalf@new-host.home’, kvs, lookup, [weather]).
{ok,cold}
(bilbo@MyMBP.home)3>

8. You can end the ssh session like this:

(bilbo@MyMBP.home)3> q().
~/erlang_programs$ exit
logout
Connection to new-host.home closed.
~$

Mac#1 (the Server):
—————————-
1. System Preferences > Sharing:
—Uncheck Remote Login checkbox.

2. System Preferences > Security & Privacy > Firewall:
—Turn On Firewall

That didn’t work too well for me: the Remote Login light turned Orange—instead of going off. I had to restart the computer. On restart, the Remote Login checkbox was checked again, and when I unchecked it, the display immediately switched to “Remote Login: Off”, and the light was greyed out.

221TYPO

A little more than halfway down the page, the definition of:

spawn(Node, Mod, Func, ArgList) -> Pid

is discussed. The text says,


Note: This form of spawn is more robust than spawn(Node, Fun). spawn(Node, Fun) can can break when the distributed nodes are not running exactly the same version of a particular module.
—-

Because spawn(Node, Fun) does not depend on any module—much less a different version of a module on another Node—I don’t understand the “Note”. I think the note should say the opposite:


Note: spawn(Node, Fun) is more robust than this version of spawn because this version of spawn can break when the distributed nodes are not running exactly the same version of a particular module.
—-

325ERROR

I’ll have to one up Kim Shrier. In the middle of the page, the definition of do_this_once() refers to a record named design, whose definition is nowhere to be seen. If you try to compile the test_mnesia.erl module—so that you can run the command test_mnesia:do_this_once()—you will get the error:

1> c(db).
db.erl:12: record design undefined
error

(Yes, I refuse to give a module a name that is longer than two characters! And so should you if you don’t want to go insane while programming erlang!)

The record definition for the design record is listed on p. 334, and you need to include it under the definitions for the records shop and cost.

234TYPO

Section 15.1/First paragraph/last word:


…Erlang messages that come from the ports.
—-

I think “ports” should be changed to “port”.

263SUGGEST

the code provided to us (the lib_find module) is missing a parameter to a re:run function.

the line:
case re:run(FullName, Reg, [{capture,none}]) of

should be changed to:
case re:run(FullName, Reg, [unicode, {capture,none}]) of

i.e. ‘unicode’ needs to be added. Otherwise, some files present in the file system may cause the lib_find:files/5 to fail (e.g. files with Chinese characters in the name, some of which are present in the Erlang’s release itself).

313SUGGEST

The link to the Moby data set seems to no longer be available.

Perhaps it is hosted elsewhere now—the link should be updated to that new location (or, preferably, to a copy of the data set hosted just for this book).

81ERROR

This doesn’t work on Erlang 21.3 as I tried on
2> #{ born => B } = Henry8.

It must use := instead
2> #{ born := B } = Henry8.

27SUGGEST

The link for installing erlang returns a 404. A reference to a live link (or reviving that page) would be helpful

68SUGGEST

It would be more robust to use “_” in the beginning of variable names where they unused.

I the ```filter function to in the last clause it would be nice to use this one (“_P”).
The code example:
`````````
`fiter(_P, []) ->
[].
`

81ERROR

“The logically equivalent Erlang code is as following” must be
D1 = #{status=>old, task=>‘feed cats’},

Without “#” it will be an error (* 1: syntax error before: ‘=>’).

82SUGGEST

I would like to propose a solution to the problem of the code example of code_characters(Str) function .
This code clearly shows a bug of Erlang implementation. I hope that soon the solution will be merged to the Erlang/OTP public version and beginners will no longer stumble over a non-working code examples.

-module(counter).
-export([count_characters/1]).

count_characters(Str) ->
\tcount_characters(Str, #{}).

count_characters([H|T], X) when is_map(X),is_map_key(H, X) ->
\tN= map_get(H,X),
\tcount_characters(T, X#{ H := N+1 });
\t
count_characters([H|T], X) ->
\tcount_characters(T, X#{ H => 1 });\t
\t
count_characters([], X) ->
\tX.

11SUGGEST

Note that in the Introduction, the" New in This Edition" section on the page xv (15) says that “We now cover all
official language changes and describe Erlang version R17”. When the shell starts, the R16B version is printed.

66TYPO

Current version Erlang’s BIFs have not the following predicate:
is_constant(X)

Current version of Erlang (22.1) has the expanded list BIFs (with additional predicates):
is_bitstring/1
is_boolean/1
is_builtin/3

66SUGGEST

Current version Erlang’s BIFs (22.1) have not the following predicate:
is_constant(X)
is_pmod(X)

68TYPO

“The following tables list all the guard predicates (that is, guards that return booleans) and all the guard functions.”

It is very likely that this paragraph is in this place by accident (It is located at the end section). It is likely that it is overlooked here, since it should have been placed in front of the BIFs’ tables.

80TYPO

The expression “6> F4 = F1#{ c := 3}” must be with a period (.) (followed by whitespace).

90SUGGEST

There is no formatting of a body of a function at the first case:

f(…) ->

X = try … end,
Y = g(X),

I think it would be nice to have it:

f(…) ->

X = try … end,
Y = g(X),

99TYPO

In the examples of binaries in the last example there is a typo.

3> <<65,66,67>>

The correct expression is

3> <<65,66,67>>.

126SUGGEST

A link to the function purge_module is outdated or was incorrect.

This is correct one:
erlang.html#purge_module-1

150TYPO

I think that the type of an instance “that the return value of erlang:time()” should not end with round parentheses.
I think it is type: {non_neg_integer(), non_neg_integer(), non_neg_integer()}).

It is correct one: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.

150SUGGEST

Running dialyzer test2.erl now returns other recommendations (I have Erlang/OTP 22.1) .

Now dialyzer suggests:

test2.erl:4: Function f1/0 has no local return
test2.erl:5: The call erlang:list_to_tuple({’a’,‘b’,‘c’})
breaks the contract (List) -> tuple() when List :: [term()]

155SUGGEST

Message of dilyzer for final function is changed (Erlang/OTP 22.1).
Now it is:

types1_bug.erl:9: The call erlang:integer_to_list
\t\t\t(H::float()) break the contract
\t\t\t\t(Integer) -> string() when Integer :: integer()

144SUGGEST

Note that the list of predefined build-in type is changed a little bit and expended.

This is a table contains changed and new build-in types:

-type binary() \t :: <<:*8>>.
-type bitstring()\t :: <<:*1>>.
-type nil()\t\t :: [].
-type nonempty_list()\t:: nonempty_list(any()).
-type iodata() \t\t:: iolist() | binary()
-type map()\t\t :: #{any() => any()}.
-type function()\t :: fun().
-type map() \t\t :: #{any() => any()}.
-type function()\t :: fun().
-type module() \t\t:: atom().
-type mfa() \t\t :: {module(), atom(), arity()}.
-type arity() \t\t :: 0..255.
-type identifier()\t :: pid() | port() | reference()

More info can be found in the typespec.html of reference_manual of the Erlang documentation.

142SUGGEST

In Erlang reference manual typespec.html while we add variable name in -spec annotation it would be nice to add a space between a name and a separator:

spec plan_route(From :: point(), To :: point())> …

166SUGGEST

The link to the wikipedia page about the utility make is changed. Therefore, the reference to it in the footnote is already outdated.

This one is correct:
en.wikipedia.org/wiki/Make_(software)

168SUGGEST

The link to yecc (parser generator tool) is outdated.

This is a valid one: erlang.org/doc/apps/parsetools/parsetools.pdf

172SUGGEST

In OTP 17, which is described in a book, it used a web-server utility to analyze the contents of a dump file. In later versions, the Crashdump Viewer GUI program is used for this.

196SUGGEST

Note that erlang:now() is depricated. Instead of this function, you can use erlang:timestamp().

3> clock:start(5000, fun() -> io:format(“TICK ~p~n”,[erlang:timestamp()]) end).

239SUGGEST

I adapted the makefile in the book to run it on Windows.
I hope that the resulting solution will be useful.

  1. Makefile.win
    .SUFFIXES: .erl .beam .yrl

.erl.beam:
\terlc -W $<

MODS = example1 example1_lid unit_test

all: \t ${MODS:.beam} example1 example1_drv.dll
\t@erl -noshell -s unit_test start
\t
example1: example1.c erl_comm.c example1_driver.c
\tgcc -o example1 example1.c erl_comm.c example1_driver.c\t

example1_drv.dll: erl_comm.c example1_lid.c example1.c
\tgcc -fpic -shared -I “E:/Program Files/erl10.5/usr/include” erl_comm.c example1_lid.c example1.c -o example1_drv.dll

clean:
\trm example1_drv.dll *.beam

  1. make -f Makefile.win

In addition, I made improvements to the erlang code (I follow the recommendations of the documentation for the erl_ddll module).

Here is the code for the modified module example1_lid functions:
%…
start(SharedLib) ->
case erl_ddll:try_load(“.”, SharedLib,[]) of
\t{ok, loaded} -> ok;
\t{ok, already_loaded} -> ok;
\t_ -> exit({error, could_not_load_driver})
end,
register(example1_lid, spawn(fun() -> init(SharedLib) end)).

loop(Port) ->
receive
\t{call, Caller, Msg} ->
\t Port ! {self(), {command, encode(Msg)}},
\t receive
\t\t{Port, {data, Data}} ->
\t\t Caller ! {?MODULE, decode(Data)}
\t end,
\t loop(Port);
\tstop ->
\t Port ! {self(), close},
\t receive
\t\t{Port, closed} ->
\t\t\terl_ddll:try_unload(example1_lid,[]),
\t\t exit(normal)
\t end;
\t{’EXIT’, Port, Reason} ->
\t\terl_ddll:try_unload(example1_lid,[]),
\t exit({port_terminated, Reason})
end.

%…

For loading / unloading a dynamic library, I used functions erl_ddll:try_load / erl_ddll:try_unload .


To compile the C code to dynamic library correctly, I created the header file example1.h, in which I placed the function definitions int sum(int x, int y) and int twice(int x). I modified example1_lid.c file. Here is a list of includes in it:

#include <stdio.h>
#include <string.h>
#include “erl_driver.h”
#include “example1.h”

make -f Makefile.win

After all these improvements, Joe Armstrong’s code will work (all tests in the file unit_test.erl will be successful).

254SUGGEST

Unfortunately, the proposed code

1> B = socket_examples:nano_get_url(“erlang.org”),
L = scavenge_urls:bin2urls(B), scavenge_urls:urls2htmlFile(L, “gathered.html”).

could not receive data from the site “www.erlang.org”.

exception error: no match of right hand side value {error,nxdomain}
in function socket_examples:nano_get_url/1 (socket_examples.erl, line

or

<<"HTTP/1.0 503 Service Unavailable\\r\
Cache-Control: no-cache\\r\
Connection: close\\r\
Content-Type: text/html\\r\
\\r\

<body"…>>

I did my code test, which I would like to share.
(compile scavenge_urls.erl before enter )
1> List = [“”,“”].
2> scavenge_urls:urls2htmlFile(List, “gathered.html”).
3> {ok, B} = file:read_file(“gathered.html”).
4> L = scavenge_urls:bin2urls(B).

This code will be working.

259SUGGEST

In a function parameter description Fun(File, AccIn) -> AccOut author use reference to the RegExp parameter of lib_find:files(Dir, RegExp, Recursive, Fun, Acc0). It is not an atom regExp.

272TYPO

17.2 Active and Passive Sockets

First paragraph. Third line.

There is not left
There is no left bracket in the function definition of gen_tcp:connect function.

277TYPO

In the end of a function client(Request) the dot is not in place. I think it have to be in the end.

341TYPO

In the bottom, in the reference part one link is broken - to the eprof (erlang.org/doc/man/eprof.html ).
The are two links to the fprof (erlang.org/doc/man/fprof.html ).

Categories: