PDF Pg | Paper Pg | Type | Description | Fixed on | Comments |
30 | | ERROR | 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-14 | The 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
|
24 | | ERROR | 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
|
23 | | TYPO | In Clarity section (bottom of page): “sequentaility” should be spelled “sequentiality”.
| 2013-04-14 | I think this was the error noted earlier on page 7
|
24 | | TYPO | 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-14 | same error as reported on page 8 earlier
|
11 | | TYPO | 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 | |
420 | | TYPO | 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-14 | thank you - fixed
|
418 | | TYPO | Statefull
should be
Stateful
| 2013-04-14 | thanks
|
432 | | TYPO | 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-14 | corrected - thank you
|
| 58 | TYPO | afile_server.erl should also export loop/1
The current code gives a compiler warning and won’t run
| 2013-04-13 | fixed - same error as on page 11
|
15 | | ERROR | The export list for afile_server must include loop/1 since it is the target of spawn/3.
| 2013-04-13 | My bad - fixed
|
| 58 | ERROR | afile_server.erl should also export loop/1
The current code gives a compiler warning and won’t run
| 2013-04-13 | fixed
|
18 | | TYPO | 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-14 | fixed
|
79 | | TYPO | Missed “)” at the end of expression:
count_characters(T, maps:extend(#{H~1}, X);
| 2013-04-14 | thanks
|
16 | | TYPO | Second paragraph: “The is the standard way […]” replace “The” with “This”
| 2013-04-14 | thanks - fixed it
|
20 | | TYPO | 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-14 | fixed
|
12 | | TYPO | 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 | fixed
|
7 | | TYPO | In Clarity section (bottom of page): “sequentaility” should be spelled “sequentiality”.
| 2013-04-14 | thanks, fixed
|
8 | | TYPO | 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-14 | thanks
|
30 | | TYPO | 4th paragraph: “Since Erlang variables immutable […]” should read “Since Erlang variables are immutable […]”
| 2013-04-14 | fixed
|
35 | | ERROR | Unbalanced } in:
Person={person,{name,joe,armstrong}},{footsize,42}}.
Should read:
Person={person,{name,joe,armstrong},{footsize,42}}.
| 2013-04-14 | ooops - thanks you
|
38 | | TYPO | Middle of page: " The notation \\x{2281}" should read " The notation \\x{221e}" to be consistent with the example.
| 2013-04-14 | Quite right. Thanks
|
51 | | TYPO | To perform the same operation operation on every element of a list. — duplicated word ‘operation’
| 2013-04-14 | thanks - missed that one
|
283 | | TYPO | In the third paragraph, “… in Chapter25, Third Party Programs, on page 425 To simplify…” . A period is missing after “on page 425”
| 2013-04-16 | thanks
|
283 | | TYPO | In the beginning of the last paragraph, it says “In the rest of of this chapter,”. there are two “of”s.
| 2013-04-16 | thanks
|
284 | | TYPO | In the second paragraph, a period is missing in this part: “../joearms/ezwebframe The browser code….”.
| 2013-04-16 | Thanks
|
284 | | TYPO | At the beginning of the third paragraph, I think “Note: The code show here” should be “Note: The code shown here”.
| 2013-04-16 | Thanks
|
284 | | TYPO | In the fifth paragraph, “If Erlang wants to the browser ..” should be “If Erlang wants the browser…” ?
| 2013-04-16 | You're right, there's an extra "to" - thanks
|
284 | | TYPO | In the last paragraph, there are duplicated “we” in “this is so that we we can ..”.
| 2013-04-16 | yes - how come I didn't see this?
|
286 | | TYPO | The first sentence “This code is build up from..” should be “This code is built up from ..” ?
| 2013-04-16 | thanks
|
286 | | TYPO | 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-16 | yes - two errors - thanks
|
287 | | TYPO | 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-16 | Thanks - this syntax is not finalised so will probably change
\nbefore the final beta and book is published.
|
287 | | TYPO | In the last paragraph, “carriage return a message is send” should be “carriage return a message is sent”.
| 2013-04-16 | fixed - thanks
|
292 | | TYPO | At the beginning of second paragraph, it says: “This code hooks an an event..”. “an” is duplicated.
| 2013-04-16 | thanks
|
292 | | TYPO | In the third paragraph, “We have to respond to two message,” should be “We have to respond to two messages,”.
| 2013-04-16 | thanks
|
299 | | TYPO | 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-16 | You're right again! - thanks
|
300 | | TYPO | 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-16 | Should be "it is" not "is is"
\nThanks
\n
|
197 | | TYPO | In “If something goes wrong in the middle or a transaction we simple abort …”, “simple” should be “simply”
| 2013-04-28 | thanks
|
197 | | TYPO | In “It simplifies the system architecture, so we can thing about the application”, “thing” should be “think”
| 2013-04-28 | thanks
|
484 | | TYPO | A2.4 SEE Implementation “deatils” => A2.4 SEE Implementation details
| 2013-04-28 | Thanks
|
80 | | TYPO | In the last paragraph (about maps:without), the word any is duplicated (“… but with any any elements…”).
| 2013-04-28 | thank you
|
| 7 | TYPO | The word “Scaleability” has an extra “e”.
| 2013-04-28 | thanks
|
412 | | TYPO | “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-28 | thanks
|
415 | | TYPO | In third paragraph from the last, “..file transfer is support by..” should be “..file transfer is supported by..”
| 2013-04-28 | thanks
|
418 | | TYPO | In last line, “then create a instance..” should be “then create an instance..” ?
| 2013-04-28 | an instance is correct - thanks
|
423 | | TYPO | In fifth paragraph, “find is called when..” means “fetch is called when..” ?
| 2013-04-28 | Yes - my mistake - thanks
|
423 | | TYPO | In the last paragraph, “Extent the adapter..” should be “Extend the adapter…”
| 2013-04-28 | yes - thanks
|
138 | | SUGGEST | 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-30 | Good 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.
|
19 | | TYPO | second paragraph: tying should probably read trying
| 2013-04-28 | yes - thanks
|
35 | | TYPO | 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-28 | thanks
|
70 | | TYPO | In problem #4, “… in the Python datetime class can be implement using” : should be “implemented”.
| 2013-04-28 | thanks
|
4 | | TYPO | …(that’s whats “/1” means…
should be
…(that’s what “/1” means
| 2013-04-28 | thank you
|
5 | | TYPO | “Means start a parallel process…”
should be
“means start a parallel process…”
| 2013-04-28 | |
5 | | SUGGEST | “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-28 | Yes - and it emphasises that it is *erlang* processes (ie not OS processes)
|
5 | | SUGGEST | “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-28 | I agree
|
6 | | TYPO | “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 | |
0 | | TYPO | 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-28 | fixed
|
268 | | TYPO | 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-28 | thanks
|
21 | | TYPO | Part II intro: “Well cover all of sequential Erlang […]”: replace “Well” with “We’ll” or “We will”.
| 2013-04-28 | thanks
|
24 | | TYPO | 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-28 | You're right of course. What a silly error for me to make. Thanks
|
43 | | TYPO | Common Errors 1st paragraph: “Commands like c(gemomtery).” “gemomtery” -> “geometry”
| 2013-04-28 | thanks
|
6 | | TYPO | “…so that Susannah knows who the message came from”
The sentence is missing the full stop character (“.”).
| 2013-04-28 | How could I miss that?
|
6 | | TYPO | “Rather that extending the model, …”
should be
“Rather than extending the model, …”
| 2013-04-28 | thanks
|
7 | | TYPO | “A top end processor, has 64 cores…”
should be
“A top end processor has 64 cores…”
| 2013-04-28 | thanks
|
7 | | TYPO | “Erlang programs written for sequential machine…”
should be
“Erlang programs written for sequential machines…”
| 2013-04-28 | thanks
|
8 | | TYPO | “Now that you’ve seen these benefits, we’d try…”
should be
“Now that you’ve seen these benefits, we’ll try…”
| 2013-04-28 | thank you
|
8 | | SUGGEST | 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-28 | yes
|
8 | | TYPO | 3rd paragraph from bottom of the page: “The difference between a good and bad processes model…”
Use “process model” instead.
| 2013-04-28 | thanks
|
8 | | SUGGEST | 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-28 | No sure about this. Concurrent programs are not necessarily sets of independent processes - I don't want to end up confusing people
|
9 | | TYPO | Paragraph 3 from the bottom: “Erlang concurrency works the the same way…”
Drop one “the”.
| 2013-04-28 | thanks
|
9 | | SUGGEST | 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-28 | I agree - thanks
|
9 | | TYPO | 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-28 | how did I miss that? - thanks
|
10 | | TYPO | 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-28 | I added a "a" - not sure about this one. Very interesting - I think
\nmail can be singular or plural.
|
12 | | TYPO | 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-28 | I added the comma
|
13 | | SUGGEST | 2nd paragraph - make the note in parentheses a footnote.
| 2013-04-28 | Unfortunately footnotes can only contain URLs - this is the pragmatic press "house style" and has to do with formatting the book for epub readers
|
80 | | TYPO | The word `surprise’ doubled in phrase “… But surprise surprise, x has changed to…”
| 2013-04-28 | But this is not an error - "surprise surprise" is a common english expression not an inadvertent error
|
15 | | SUGGEST | 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-28 | That looks better, thanks
|
83 | | ERROR | “…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-28 | My bad - silly mistake - thanks
|
139 | | TYPO | “…Once we’ve happy…” Should be “we’re”
| 2013-04-28 | thanks
|
15 | | TYPO | 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-28 | Excellent - I swapped the order - thanks
|
16 | | SUGGEST | 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-28 | Ok - I had a long think abou this one :-)
|
141 | | TYPO | “…Addition type variables…”
Shouldn’t be there something like “…Additional…” or “…In addition, …”?
| 2013-04-28 | Yes "additional" - thanks
|
142 | | TYPO | “…FileName and Modes and on…” Should be “ on”
| 2013-04-28 | thanks
|
142 | | TYPO | Double `by’ in “…was being opened by by using…”
| 2013-04-28 | thanks
|
151 | | TYPO | `Runing’ should be `Running’
| 2013-04-28 | thanks
|
18 | | TYPO | Last paragraph: “This gives us the freedom to change to underlying protocols…” — change the second “to” to “the”
| 2013-04-28 | |
26 | | TYPO | 4th paragraph: “…(for details see see…).” — drop one “see”
| 2013-05-13 | thanks
|
28 | | TYPO | 3rd paragraph from bottom: “Here’s some examples:” — change “Here’s” to “Here are”
| 2013-05-13 | yes - thanks
|
30 | | TYPO | 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-13 | fixed - thanks
|
35 | | TYPO | 2nd paragraph: “…we’d represent the days using the the atoms…” — drop one of the two consequent “the”
| 2013-05-13 | thanks
|
199 | | TYPO | “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-13 | thanks
|
200 | | TYPO | “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-13 | fixed
|
36 | | SUGGEST | 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-14 | I've reworded this. See the next release. Thanks for the idea
|
37 | | TYPO | 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 | |
39 | | SUGGEST | Please consider moving the “Exercises” section to page 40 - it will look better with all the exercises on a single page.
| 2013-06-02 | The final typography will be fixed later -
|
39 | | TYPO | Last paragraph: “…and pattern matching, so we can step up the tempo…” — remove the comma and “so”
| 2013-05-13 | thanks
|
41 | | TYPO | First paragraph: “Modules and functions, are the basic units…” — remove the comma
| 2013-05-13 | done :-)
|
209 | | TYPO | “To illustrate thse steps” should be “To illustrate these steps”.
| 2013-05-13 | thanks
|
43 | | TYPO | 2nd paragraph: “…we used in the shell example, have become…” — remove the comma
| 2013-05-13 | yes thanks
|
47 | | TYPO | 4th paragraph from bottom: “Comma is a sort-range symbol, …” — should be “short-range symbol”
| 2013-05-13 | fixed
|
50 | | TYPO | First paragraph in section 4.3 — there is a full stop missing after “…in Erlang is called a fun”
| 2013-05-13 | Thanks
|
51 | | TYPO | 2nd bullet point: “Erlang, has for example, no for loop.” should read “Erlang has, for example, no for loop.”
| 2013-05-13 | Yes - thanks
|
204 | | ERROR | 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-13 | Thank you
|
222 | | TYPO | Last line : “this basic code structure in central to many applications” should be : “this basic code structure is central to many applications”
| 2013-05-13 | thanks
|
262 | | SUGGEST | 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-30 | I've added some comments and a new exercise at the end of the
\nchapter. Fixing this makes a nice exercise.
\n
|
78 | | TYPO | 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-13 | This part has been rewritten to reflect a last-minute change in syntax
|
81 | | TYPO | 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-13 | yes - thanks
|
431ff | | SUGGEST | 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-18 | This 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
|
61 | | TYPO | 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-13 | thanks
|
63 | | TYPO | First paragraph after the bullet list: “They are include
in this tables for completeness.” “include” -> “included”.
| 2013-05-13 | thanks
|
67 | | TYPO | Penultimate paragraph: “This might lead to a problem in Erlang because if is a expression”: “a expression” -> “an expression”
| 2013-05-13 | thanks
|
67 | | TYPO | 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-13 | thanks
|
69 | | TYPO | First paragraph: “The best thing thing to do is […]” delete duplicate “thing”.
| 2013-05-13 | thanks
|
70 | | TYPO | 3rd paragraph: “It also has supports records.” rephrase to “It also has a data type called records.” or “It also supports records.”
| 2013-05-13 | thanks
|
85 | | TYPO | Second paragraph: “In a sequential language with only one processes”: “processes” -> “process”.
| 2013-05-13 | thanks
|
85 | | TYPO | Second paragraph: “If we have large numbers of
processes it is not so important if one processes crashes”: second “processes” -> “process”
| 2013-05-13 | I reworded this a bit
|
91 | | TYPO | 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-13 | thanks
|
94 | | TYPO | 3rd paragraph from bottom: “One the other hand the user […]”: “One” -> “On”.
| 2013-05-13 | thanks
|
435 | | SUGGEST | (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-13 | I've changed the text - see next edition
|
123 | | TYPO | Bottom of page: “To see the result of pre-
procssing […]”: “pre-procssing” -> “pre-processing”
| 2013-05-13 | yes
|
138 | | TYPO | 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 | |
146 | | TYPO | Last paragraph: “If
factorial is called with a negative argument the program the program”: delete second “the program”.
| 2013-05-14 | thanks
|
198 | | TYPO | 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-18 | thanks
|
23 | | SUGGEST | 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-27 | Thanks - 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
|
395 | | TYPO | 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-18 | thanks
|
56 | | TYPO | 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-24 | thanks
|
58 | | TYPO | 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-24 | thanks
|
12 | | TYPO | Maps have talked about -> Maps have been talked about
| 2013-05-27 | My goodness somebody reads the change logs - you do have sharp eyes :-)
\n
\nThanks
\n
\n
|
27 | | TYPO | The link to the installation page is wrong
“Object not found”
| 2013-05-27 | Some 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
|
31 | | SUGGEST | “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-27 | Reformulated 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
|
14 | | SUGGEST | In the shell session at the top of this page, it would be good to show the use of halt(). to exit.
| 2013-05-27 | Yup - did this
\n
|
53 | | TYPO | 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-27 | Reformulated as
\n
\nWe refer to ...
|
58 | | TYPO | 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-30 | Fixed
|
59 | | SUGGEST | 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-30 | I'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.
|
229 | | TYPO | “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-30 | thanks
|
592 | | TYPO | “Note: The code show here, is a simplified version” ->
“Note: The code shown here, is a simplified version”
| 2013-05-30 | thanks
|
60 | | TYPO | 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-30 | thanks
|
61 | | TYPO | “perm is pretty neat.” Should be “perms is pretty neat.”
| 2013-05-30 | thank you
|
84 | | SUGGEST | 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-30 | Yes - it should have a sensible name :-)
\n
|
173 | | TYPO | First sentence: “Let’s forget about programming for while […]”: “for while” -> “for a while”.
| 2013-05-30 | yes - thanks
|
192 | | ERROR | In concurrent program template, the start() method should read:
start() ->
spawn(?MODULE, loop, []).
| 2013-05-30 | thanks
|
210 | | SUGGEST | 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-30 | The 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
|
107 | | TYPO | 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-30 | How could I get that wrong?
|
113 | | TYPO | “segement” -> “segment”
| 2013-05-30 | |
189 | | ERROR | 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-02 | Thanks - fixed now.
|
195 | | TYPO | “this time we use span(Fun)” should be spawn(Fun)
| 2013-06-01 | I re-wrote this bit
|
94 | | TYPO | 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-01 | thanks
|
95 | | TYPO | Replace “loose” with “lose” in “so we never loose them”.
| 2013-06-01 | fixed
|
101 | | TYPO | In the sentence “If the size of a segement is not specified a default value will be assumed.”, segment is misspelled.
| 2013-06-01 | thanks
|
xiii | | TYPO | “non” should be “none” in the last sentence.
| 2013-06-01 | thanks
|
430 | | SUGGEST | 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-01 | The 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
|
7 | | TYPO | 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 | |
17 | | TYPO | Missing period, capitalization, “… identifier of the the server) this identifier is added”. I suggest “… server). This …”
| 2013-06-02 | |
18 | | TYPO | “freedom to change to underlying protocols” reads oddly, I suggest “… to change the …”
| 2013-06-02 | |
20 | | TYPO | “(ie which processes known about each”, I suggest “i.e.” and “know about”.
| 2013-06-02 | |
24 | | TYPO | “In Line two the percent (%) …” I suggest “In line two the …”
| 2013-06-02 | |
29 | | SUGGEST | Consider including the examples “16 = X + Y.” and “X + Y = 16.” in the pattern matching introduction.
| 2013-06-02 | |
49 | | TYPO | “The call shop1:total([{milk,3}]) Matches the clause:” I suggest “… matches …”
| 2013-06-02 | |
50 | | TYPO | “… and the data type that represent a function in Erlang …” I suggest “… represents …”
| 2013-06-02 | |
70 | | SUGGEST | 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 | |
73 | | TYPO | “… maps, and in Lua they are called tables, and in Python dictionaries.” I suggest deleting the ‘and’ just before ‘in Lua’.
| 2013-06-02 | |
76 | | TYPO | “Maps were made available as from version R17 of Erlang.” I suggest removing “as”.
| 2013-06-02 | |
76 | | TYPO | “… (fully ground means that, that there are no unbound variables in the term).” I suggest “fully grounded” and deleting the comma.
| 2013-06-02 | |
76 | | TYPO | “… keys are not changed, is a space efficient …” I suggest deleting the comma.
| 2013-06-02 | |
78 | | TYPO | Is the space between “#” and “{” legal in the Henry8 shell interaction, line 2?
| 2013-06-02 | |
92 | | SUGGEST | 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 | |
79 | | SUGGEST | 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-02 | maps are still being discussed and implemented. There probably will
\nbe such a function in the future but I can't say what now.
|
81 | | ERROR | “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 | |
81 | | TYPO | “continuiously” -> “continuously”
| 2013-06-02 | |
82 | | SUGGEST | Is the type “map()” correct in the type “json_value()” definition? Or should it be replaced with “json_map()”?
| 2013-06-02 | |
85 | | SUGGEST | 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 | |
85 | | TYPO | “… after all, the entire computer …” — I suggest replacing the comma with a colon.
| 2013-06-02 | |
86 | | TYPO | Missing period at “This rule is called “Let it
crash”".
| 2013-06-02 | |
126 | | TYPO | 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 | |
228 | | TYPO | First line: three function -> three functions
| 2013-06-06 | |
94 | | TYPO | “Error messages are programmers gold-dust.” I suggest adding a ’ for “programmers’”
| 2013-06-06 | |
97 | | TYPO | “Binary are written and printed…” I suggest “Binaries …”
| 2013-06-06 | |
98 | | TYPO | “… functions from the module binary.erl …” — the “.erl” isn’t needed in this context; the sentence is missing its period.
| 2013-06-06 | |
101 | | SUGGEST | 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-15 | It is nice, but I don't really want to gloat here.
|
102 | | SUGGEST | “End is big | little | native” — please include a note that the default, Big, is also known as network byte order.
| 2013-06-06 | |
103 | | TYPO | I suggest deleting the comma in “The final example, shows how to unpack an IPv4 Datagram.”
| 2013-06-06 | |
108 | | SUGGEST | I suggest re-writing the sentence “The next section covers bitstrings these are used to store sequences of bits.”
| 2013-06-06 | |
113 | | TYPO | “… we can create “modules with state” this …" I suggest adding a semicolon after “modules with state”.
| 2013-06-06 | |
123 | | SUGGEST | “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-16 | I changed the text
|
128 | | TYPO | “… when we compile the code This is …” needs a period.
| 2013-06-06 | |
131 | | SUGGEST | 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-16 | They are In table 6 page 134 (page number in beta 2)
\n
|
131 | | SUGGEST | “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-16 | The process dictionary hasn't changed - I think this is ok
|
132 | | SUGGEST | “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-06 | To be precise would need a lot of explanation here.
\nToo advanced for this book
|
138 | | TYPO | “… were of type point() We also …” is missing a period.
| 2013-06-06 | |
143 | | TYPO | In the code for module(a), “Hight::integer()” should be “Height::integer()”
| 2013-06-06 | |
152 | | SUGGEST | 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 | |
236 | | TYPO | Section 15,1 describes sending massages to ports. Intriguing, but perhaps you meant messages :-)
| 2013-07-15 | |
| 161 | TYPO | Sidebar, “Note the using -compile(export_all)” should be “Note that …”
| 2013-07-15 | |
| 163 | ERROR | 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 | |
| 166 | TYPO | “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-15 | You're right. Thanks
|
| 175 | TYPO | “… saying why the first process dies.” should be “died”.
| 2013-07-15 | |
| 192 | SUGGEST | 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-15 | No. I think before use the OTP templates you should code in raw Erlang to get a feeling for what is going on.
|
| 195 | TYPO | “Handling Errors in concurrent programs …”, should be “errors”.
| 2013-07-15 | |
| 195 | TYPO | [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 | |
| 197 | SUGGEST | The bullet points in “Why Crash?” are a bit awkward; I suggest removing “we just crash” from the first two bullet points.
| 2013-07-15 | A bit of repetition here, for emphasis
|
| 200 | SUGGEST | [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 | |
| 204 | ERROR | 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-15 | It goes to the shell process. But this is killed before the error message can be written
|
| 206 | SUGGEST | “Write a function which creates a global process …” — I don’t think “global process” has been defined at this point.
| 2013-07-15 | should be registered process
|
| 212 | SUGGEST | 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-16 | Right 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
|
| 215 | SUGGEST | 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-16 | I've added a longer comment about this
|
| 233 | TYPO | “… and sends the a …” delete “the”.
| 2013-07-15 | |
| 234 | SUGGEST | 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 | |
| 237 | TYPO | “… MAC OS-X Mountain lion …” -> “Mac OS X Mountain Lion”
| 2013-07-15 | |
437 | | TYPO | “performed and and the browser” — double `and’
| 2013-07-15 | |
356 | | TYPO | “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 | |
299 | | TYPO | “contains a lot parameters”. `of’ is missing
| 2013-07-15 | |
431 | | TYPO | “rebar itself uses a program called mech for testing purposes”
Not `rebar’ but `bitcask’. Not `mech’ but `meck’
| 2013-07-15 | |
372 | | TYPO | 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 | |
435 | | TYPO | //Host/cgi&mod=Modname?Func=Funcname
The URL is bad formed. Should be
//Host/cgi?mod=Modname&func=Funcname
| 2013-07-15 | |
| 240 | TYPO | “… returns you CPU type, …” -> “your”
| 2013-07-15 | |
| 251 | SUGGEST | “(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-16 | No - I/O lists are unchanged since unicode arrived.
|
| 257 | ERROR | “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-16 | Yes - it's not awk.
|
| 263 | SUGGEST | The “Writing a Web Server” sidebar is in an awkward position — it might be less distracting on the next page.
| 2013-07-16 | It might be moved later
|
| 266 | ERROR | 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-16 | This is not a bug it's an undocumented feature
|
| 267 | TYPO | “{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 | |
| 273 | TYPO | Sidebar, “{N1,N2,N3,N3}” — “N3” is duplicated.
| 2013-07-15 | |
| 275 | TYPO | “… 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 | |
| 285 | TYPO | On this page, and several others, “JavaScript” has accidentally been written “Javascript”.
| 2013-07-15 | |
| 286 | TYPO | “The first example, shows in detail …” delete comma.
| 2013-07-15 | |
| 288 | ERROR | “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-16 | fixed
|
| 301 | TYPO | “A web browser is, of course a massively complicated object.” delete comma.
| 2013-07-15 | |
| 301 | TYPO | “… we can easily contain this complexity, and harness it …” I suggest deleting the comma.
| 2013-07-15 | |
| 308 | SUGGEST | 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-16 | There is an easy locking interface. Only one process (the owner of the ets table) can write the table all others can read.
|
| 308 | TYPO | “… we’ll analyze which trigrams. occur in the word.” Delete the period after “trigrams”.
| 2013-07-15 | |
| 312 | SUGGEST | lib_trigrams.erl function open/0 should use filename:join/2 to create the trigramsS.tab file.
| 2013-07-15 | |
| 314 | SUGGEST | 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 | |
| 331 | SUGGEST | “… “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 | |
| 336 | TYPO | “… Erlang distribution site In addition, …” Insert a period after “site”.
| 2013-07-15 | |
| 343 | TYPO | “… depreciated, undefined, and unused functions.” should be “deprecated”.
| 2013-07-15 | |
| 356 | TYPO | “Compile the module. dict.” Delete “dict.”
| 2013-07-15 | |
| 370 | SUGGEST | 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 | |
| 384 | SUGGEST | “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 | |
| 389 | SUGGEST | 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 | |
| 401 | TYPO | “… computation was defined (in computer_area/1) …” should be “(in compute_area/1)”.
| 2013-07-15 | |
| 406 | TYPO | “sellaprim” has been used instead of “sellaprime” in the following: “sellaprim_supervisor.erl”, “sellaprim_app.erl”
| 2013-07-15 | |
| 408 | SUGGEST | 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-16 | new_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.
|
| 401 | SUGGEST | 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-16 | I have to leave something for the reader to try for themself
|
| 410 | TYPO | “When a a prime …” delete an “a”.
| 2013-07-15 | |
| 417 | TYPO | “… 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 | |
| 418 | SUGGEST | “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 | |
| 419 | SUGGEST | “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 | |
| 420 | TYPO | “… 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 | |
| 423 | SUGGEST | 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 | |
| 424 | SUGGEST | “This is not a very good error message.” I suggest “This is a poor error message.”
| 2013-07-15 | |
| 425 | TYPO | “… 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 | |
| 428 | TYPO | “Click on the new-repro …” probably “new repo” was meant.
| 2013-07-15 | |
| 430 | TYPO | “… 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 | |
| 430 | SUGGEST | 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 | |
| 431 | SUGGEST | 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-16 | It's ok for the purposes of the book. This is about Erlang not Makefiles
|
| 431 | SUGGEST | “… unpack it and type make.” What does “unpack it” mean here?
| 2013-07-15 | |
| 434 | TYPO | “… parallel session can be far higher than this.” should be “sessions”.
| 2013-07-15 | |
| 434 | TYPO | “… 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 | |
| 434 | TYPO | “… what cowboy calls a “Request Object” The request …" Insert a period after “Object”.
| 2013-07-15 | |
| 434 | TYPO | “handle calls cowboy_req:path(Req) (Line 2) to extract …” I suggest “(line 2)”.
| 2013-07-15 | |
| 435 | ERROR | 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-16 | I've added this as an additional exercise at the end of the chapter.
|
| 435 | TYPO | “… and make a more useful example:” — I suggest replacing the colon with a period.
| 2013-07-15 | |
| 435 | ERROR | 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-16 | Added an exercise at the end of chapter
|
| 438 | TYPO | “… large integers we might run into problem.” should be “problems”.
| 2013-07-15 | |
| 438 | TYPO | “… point numbers might loose precision …” should be “lose”.
| 2013-07-15 | |
| 439 | TYPO | “… to create you own project.” should be “your”.
| 2013-07-15 | |
| 439 | TYPO | “… examine the contends.” should be “contents”.
| 2013-07-15 | |
| 439 | TYPO | “Make you own self-executing …” should be “your”.
| 2013-07-15 | |
| 442 | TYPO | “… no mutable data structures(that’s not …” insert space before parenthesis.
| 2013-07-15 | |
| 444 | SUGGEST | Sidebar, multicore CPUs: most smartphones sold today are dualcore or even quadcore. Even cheap and power-miser devices are going towards multicore.
| 2013-07-16 | Yes - changed the side bar to add comment about smartphones
|
| 445 | SUGGEST | 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-16 | I'm not going to change this. A full description would be too long here.
\n
|
| 447 | TYPO | “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 | |
| 447 | SUGGEST | “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 | |
| 452 | ERROR | 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-16 | This is a book about erlang - not about performance measurements.
\nSometimes you have to leave things out since otherwise the book would become unbearably long
|
| 458 | TYPO | “This chapter, has shown how …” delete comma.
| 2013-07-15 | |
| 458 | TYPO | “… standard libraries, and the major …” delete comma.
| 2013-07-15 | |
| 459 | TYPO | Twice, “worse case” is used instead of “worst case”.
| 2013-07-15 | |
| 462 | TYPO | This sentence is missing its quotes: “It’s the term frequency
times the inverse document frequency, I shall explain …”
| 2013-07-15 | |
| 465 | SUGGEST | “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 | |
| 470 | TYPO | “So if a document, contains the word …” delete comma.
| 2013-07-15 | |
292 | | TYPO | R17 is expected in 2103. I can’t wait that long.
| 2013-07-15 | Patience, my friend.
|
23 | | TYPO | 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-15 | Thanks
|
215 | | TYPO | 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 | |
215 | | ERROR | 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-16 | This looks like an erlang bug - not a book bug
|
379 | | TYPO | 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 | |
217 | | TYPO | 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 | |
xviii | | TYPO | In the acknowledgements for the second edition, there is a comma missing between the names of Kurt Landrus and Kenneth Lundin.
| 2014-08-06 | |
14 | | TYPO | code sample has halt() without the dot at the end
| 2014-08-06 | seems ok to me
|
79 | | TYPO | 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-06 | This 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.
|
306 | | ERROR | 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 | |
44 | | SUGGEST | 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-06 | I'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
|
68 | | TYPO | “Or course, if they want an exception…” => “Of course, …”
| 2014-08-06 | |
116 | | TYPO | 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-06 | they should both be 4.8
|
138 | | ERROR | At bottom of the page:
spec plan_route(From:: point(), To:: point())> …
should be
spec plan_route(From::point(), To::point())> …
| 2014-08-06 | |
160 | | ERROR | 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 | |
280 | | TYPO | 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 | |
15 | | SUGGEST | “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-06 | It's ok I think. If I replaced the second 'process' by 'it' there might be confusion.
\nIs 'it' a module or process.
|
297 | | SUGGEST | 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-06 | The 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.
|
421 | | TYPO | At the top of page:
“In lines 12 to 13 (..)”
should be:
“In lines 14 to 15 (..)”
| 2014-08-06 | |
425 | | ERROR | In listing of adapter_db1_tester.erl there should be store/3 imported from adapter_db1, not store/2
| 2014-08-06 | fixed
|
311 | | SUGGEST | 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-06 | No I use the first form with variables when I refer to F and A later in the text
|
164 | | ERROR | “see the online tutorial[4] for more details”
[4] …parser_tutorial-1.0.tgz - dead link
| 2014-08-06 | I'll try and get them back ... at this link
|
310 | | ERROR | 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-06 | This 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
|
206 | | TYPO | 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 | |
209 | | TYPO | “If the process dies before on_exit gets evaluated, then a link will be not be created.”
| 2014-08-06 | What was wrong here? . I see no error
|
70 | | TYPO | 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 | |
| 68 | TYPO | 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 | |
82 | | TYPO | ASCII decimal value 101 is ‘e’, and 104 is ‘h’. The book states that 101 is ‘h’.
| 2014-08-06 | yes h is 104
|
378 | | TYPO | 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-06 | I 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
|
66 | | ERROR | 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 | |
76 | | TYPO | 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-06 | I tested this rd failed rr worked.
|
| 268 | ERROR | 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-06 | strong2value/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
|
115 | | TYPO | “This specifies the endianess of the machine. ”
I think “endianess” might be “endianness”.
| 2014-08-06 | |
147 | | TYPO | Page 147 bottom half: “creates an opaque types called rich_text()”. It should be “type” not “types”.
| 2014-08-06 | |
93 | 80 | TYPO | 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 | |
111 | | TYPO | 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 | |
| 81 | ERROR | Pattern Matching the fields of a map: In R17rc1 you must use := (not =>) in map patterns.
| 2014-08-06 | |
83 | | ERROR | BIFs that Operate on Maps: In R17rc1 maps:map_size is named maps:size and maps:difference is missing.
| 2014-08-06 | I've change map_size to size. difference should be added to the maps library so I'll leave this
|
| 52 | SUGGEST | 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-06 | This would need a lot of explanation. I can only make small changes in this edition. This is something for a third edition :-)
|
197 | | TYPO | 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/A | | SUGGEST | 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-06 | I think these topics should be in separate books - not in a new edition of this book
|
110 | | TYPO | 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 | |
79 | | ERROR | 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-06 | I 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.
|
82 | | ERROR | 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-06 | All 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.
|
| 84 | ERROR | 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-06 | One day JSON bridge stuff will be added to the libraries I hope. So leaving it in the book might encourage this :-)
|
223 | 215 | TYPO | 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 | |
206 | | ERROR | 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 | |
206 | | TYPO | 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 | |
208 | | ERROR | 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 | |
49 | | ERROR | 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-06 | No - 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.
|
0 | | TYPO | 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.3 | | ERROR | Kindle version. Section 5.3.
Under “Maps in Other Languages”:
D1 = {status=> ‘old’, status=>‘feed cats’}
Missing the # before the opening { ?
| 2014-08-06 | |
| 209 | TYPO | "
following two lines of code:
Pid = register(…)
on_exit(Pid, fun(X) -> ..),
"
The line in the middle should be “Pid = spawn(…)”.
| 2014-08-06 | the 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
|
408 | | SUGGEST | 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.
| | |
84 | | ERROR | 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.
| | |
82 | | ERROR | 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>
| | |
160 | | TYPO | 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).
| | |
102 | 90 | TYPO | At the bottom of the page in the last paragraph we have FuncOrExpessionSeq instead of FuncOrExpressionSeq.
| | |
38 | | TYPO | 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.
| | |
| 378 | ERROR | The URL for the design_principles.pdf is invalid (in footnote)
| | |
| 292 | ERROR | 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]
| | |
82 | | ERROR | 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.”
| | |
| 468 | ERROR | 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.
| | |
| 467 | TYPO | In the second Paragraph of “Similarity Queries” is written:
“They we compute the cosine…”, which should be “Then we compute the cosine…”.
| | |
| 119 | TYPO | in example code shows version number to be 4.8 then describes the version number as 4.5.5
| | |
| 133 | TYPO | comma is missing between = and ! in table.
could lead to confusion of a possible operator of =! type
| | |
218 | | TYPO | 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]).
| | |
| 403 | ERROR | On sellaprime.app codewhere is sellaprime_super I think it should have sellaprime_supervisor.
| | |
295 | | TYPO | first line of receive block has too many } brackets
| | |
133 | | ERROR | Calculation error:
- 36#wow is said to be equal to 42368.
- 36#wow is equal to 30363.
| | |
168 | | ERROR | bottom note 4 : the link
h t t p://www.erlang.org/contrib/parser_tutorial-1.0.tgz
is broken : error 404
| | |
515 | | SUGGEST | 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
| | |
237 | | SUGGEST | 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
| | |
315 | | ERROR | 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
| | |
84 | | ERROR | 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.
| | |
| 137 | TYPO | 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.
| | |
11 | | ERROR | The link in the third paragraph to install Erlang is broken. It returns a 404 error.
| | |
80 | | ERROR | 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.
| | |
153 | | ERROR | 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”
| | |
266 | | SUGGEST | 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.
| | |
270 | | SUGGEST | 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.
| | |
325 | | SUGGEST | 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.
| | |
326 | | TYPO | 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.
| | |
392 | | TYPO | 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.
| | |
407 | | ERROR | 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.
| | |
| 58 | TYPO | 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.
| | |
| 58 | TYPO | 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.
| | |
| 58 | SUGGEST | 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.
| | |
| 15 | SUGGEST | 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.
| | |
| 103 | ERROR | 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.
| | |
| 103 | SUGGEST | 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.
| | |
94 | 81 | TYPO | 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
| | |
| 275 | SUGGEST | 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.
| | |
| 266 | TYPO | In the code example (marked with a circled 5):
lists_to_binary(reverse(SoFar))
Change “reverse” to “lists:reverse”.
| | |
| 276 | SUGGEST | 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.
| | |
| 287 | TYPO | 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.
| | |
| 218 | ERROR | 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.
| | |
| 221 | TYPO | 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.
—-
| | |
| 325 | ERROR | 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.
| | |
| 234 | TYPO | Section 15.1/First paragraph/last word:
…Erlang messages that come from the ports.
—-
I think “ports” should be changed to “port”.
| | |
| 263 | SUGGEST | 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).
| | |
313 | | SUGGEST | 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).
| | |
81 | | ERROR | This doesn’t work on Erlang 21.3 as I tried on
2> #{ born => B } = Henry8.
It must use := instead
2> #{ born := B } = Henry8.
| | |
27 | | SUGGEST | The link for installing erlang returns a 404. A reference to a live link (or reviving that page) would be helpful
| | |
68 | | SUGGEST | 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, []) ->
[].
`
| | |
81 | | ERROR | “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: ‘=>’).
| | |
82 | | SUGGEST | 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.
| | |
11 | | SUGGEST | 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.
| | |
66 | | TYPO | 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
| | |
66 | | SUGGEST | Current version Erlang’s BIFs (22.1) have not the following predicate:
is_constant(X)
is_pmod(X)
| | |
68 | | TYPO | “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.
| | |
80 | | TYPO | The expression “6> F4 = F1#{ c := 3}” must be with a period (.) (followed by whitespace).
| | |
90 | | SUGGEST | 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),
…
| | |
99 | | TYPO | 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>>.
| | |
126 | | SUGGEST | A link to the function purge_module is outdated or was incorrect.
This is correct one:
erlang.html#purge_module-1
| | |
150 | | TYPO | 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()}.
| | |
150 | | SUGGEST | 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()]
| | |
155 | | SUGGEST | 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()
| | |
144 | | SUGGEST | 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.
| | |
142 | | SUGGEST | 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())> …
| | |
166 | | SUGGEST | 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)
| | |
168 | | SUGGEST | The link to yecc (parser generator tool) is outdated.
This is a valid one: erlang.org/doc/apps/parsetools/parsetools.pdf
| | |
172 | | SUGGEST | 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.
| | |
196 | | SUGGEST | 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).
| | |
239 | | SUGGEST | I adapted the makefile in the book to run it on Windows.
I hope that the resulting solution will be useful.
- 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
- 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).
| | |
254 | | SUGGEST | 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.
| | |
259 | | SUGGEST | 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.
| | |
272 | | TYPO | 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.
| | |
277 | | TYPO | In the end of a function client(Request) the dot is not in place. I think it have to be in the end.
| | |
341 | | TYPO | 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 ).
| | |