By Developers, For Developers

Historical errata for Programming Elixir

PDF PgPaper PgTypeDescriptionFixed onComments
4ERROR

The last version in the installation guide installs the last erlang version (R16B) but the book is still referring to version R15B03.

2013-05-27The book is tracking the latest versions, and the next beta will say R16B (although it makes no appreciable difference to the content)
14TYPO

The first paragraph on page #14 refers to the second to last example on page #13, causing a mismatch between the last example read:

iex> a..b = 1..10
1..10

which is a success, and the text “But here the 1 (the second term in the list) cannot be…”

2013-05-27
23TYPO

In description of the “r” option for regular expressions, the words “matching as must as possible” should read “matching as much as possible”.

2013-05-27
23SUGGEST

Maybe add a note about the delimiters of the regular expression being (semi-)freely selectable. The first paragraph in the “Regular expressions” section defines the syntax as %r{regexp}, but all the examples use %r/regexp/ — and iex uses a third method:

iex> pattern = %r{[aeiou]}
%r“[aeiou]”

2013-05-27
27TYPO

Last paragraph: The words “any other value that false …” should read “any other value than false …”

2013-05-27
17TYPO

File name is intro/hello.exs but while running it example is missing “s”
$elixir hello.ex
also in
$iex
it has
iex > c(“hello.ex”)

2013-05-27
15TYPO

>>>
iex> a = 1
1
iex> [^a, 2, 3 ] = [ 1, 2, 3 ] # use existing value of a
[1,2]
iex> a = 2
2
iex> [ ^a, 2 ] = [ 1, 2 ]

(MatchError) no match of right hand side value: [1,2]

<<<<

Line two returns “[1,2,3]” not “[1,2]”

2013-05-27
39ERROR

In the “Your turn…” section, you have to rewrite the first exercise in the chapter with &1 notation.

sum.(1,2,3) can’t use &1 since it has three variables (sum = &1 + &2 + &3 is illegal).

pair_tuple_to_list({8,7}) doesn’t make sense to rewrite using &1 with the knowledge so far since it only has one variable. Turning multiple parameters into a list or tuple would be more useful.

2013-05-27
38TYPO

The text describes a function named each in the Enum module, while using Enum.map in the example.

2013-05-27
8TYPO

The “Think different(ly)” list starts out true statements like “Object-Orientation is not the only way to design code”, but in the middle turns into a list of false statements, like “Programming is work, not fun”.

2013-05-27
13TYPO

“The” is written twice on this paragraph: “The value on the right hand side corresponding the the term c ”.

2013-05-27
24TYPO

On the Pids and Ports paragraph “We’ll about this in Part 2” should be “We’ll talk about this in Part 2”.

2013-05-27
33TYPO

In section Your turn we have :
pair_tuple_to_list.( { 8, 7 } ] #=> [ 8, 7 ]

there is no parenthesis for close, the good one is :

pair_tuple_to_list.( { 8, 7 } ) #=> [ 8, 7 ]

2013-05-27
50TYPO

2103 should be 2013 in elixir version of example

2013-05-27
28TYPO

a=b # strict equality (so 1 1.0 is false)

should be

a=b # strict equality (so 1 = 1.0 is false)

2013-05-27
64TYPO

“chaacter codes” should be “character codes”

2013-05-27
34TYPO

> are evaluated as the result is substituted back in

I think it’s meant to be…

> are evaluated and the result is substituted back in

2013-05-27
28TYPO

“The types are the same, or are compatible (for example 3 > 2or 3.0 < 5) the comparison uses natural ordering”
should begin “If the types …”

2013-05-27
39TYPO

The example
iex> func.(9, 4)
shows a message

(BadArityError) bad arity error: #Function<erl_eval.6.82930912>
called with [3,4]

which is inconsistent, it should be [9,4] or the parameters should be (3,4)

2013-05-27
39TYPO

fn x -> (fn a, b -> a+b ends) + x end

should be

fn x -> (fn a, b -> a+b end) + x end

2013-05-27
6SUGGEST

I noticed that

iex> c IO

produced the same output as

iex> c(IO) but with less typing

is this by accident or design?

If it’s deliberate it double be noce to know

2013-05-27It's a function call, so the parentheses are optional.
55OK

On my system

iex> to_binary IO
“Elixir.IO”

I’m confused as to exactly what the a module name is. You say it’s
an atom - page 22 says atoms must be preceded by a colon

so

iex> is_atom IO

should return false. Io cannot be an atom since it’s not preceded
by a colon (as per page 22)

2013-05-27You're running 0.9. The next beta will show this. \n \n \nModule names are a syntactic sugar: Fred is converted to :Elixir.Fred
47TYPO

The module Debug, functionally is practically the same that Guard in page 46.

2013-05-27
50TYPO

bottom of page

…pretty must follows the form of your spec

likely to be

…pretty much follows the form of your spec

2013-05-27
105TYPO

“However, there are some functionals…” -> “some functions”

2013-05-27
29TYPO

“In a function language…” should probably read “In a functional language”.

End of section 3.4, second to last paragraph.

2013-05-27
59TYPO

“It you want…” should read “If you want…”

Section 6.6 “Modules”, second paragraph, first sentence.

2013-05-27
89TYPO

> Remove loading whitespace from str.

Loading -> leading

2013-05-27
96TYPO

> Then proccess that list to produce

Proccess -> process

2013-05-27
55SUGGEST

Hi,

I found it difficult to find the information on calling Erlang libraries from Elixir. Is there anyway you can cover this topic in greater depth or at least make it a higher-level section so that it’s easier to find?

Also, I realize that the intro states that the goal of this book was not to create a giant table of everything in the language like the pickaxe books does, but I think it would be helpful nonetheless to have a reference section at the end for syntax, built-in libraries, and useful Erlang libraries.

Thanks!

RJ

2013-06-13
70TYPO

I think “apis” should be capitalized as “APIs” in the text box.

2013-05-27
70TYPO

Missing the “e” from “the” in the sentence “You can also use th h command …”

2013-05-27
68SUGGEST

Maintain same convention when writing lists:
for example once you write [ 1, 2, 3 ] (with spaces before and after first and last element) and in other case it is [time, loc, temp, rain ] (with space before closing bracket and not after opening bracket).
It would be nice to maintain some clear convention in whole book.

2013-05-27
80TYPO

orders list is missing closing bracket, and has an extra comma at the end instead

2013-05-27
17TYPO

“The previous example shows how many of the code listings in this book are presented.”

This “how many” seems strange to me. Maybe it was intended to be “how code listings in this book are presented”

2013-05-27
20SUGGEST

String.capitalize is not available in the Fedora 18 elixir Version may you could use upcase instead or so…

To make it happen I had to compile & install the latest elixir Version 0.9.1.dev. But to compile that I had to compile the erlang Version 16 because otherwise I get an “OTP release R15B03 does not match required regex (R16).”
Of course this is not a major point cause everyone gets what you want to show the reader…

Greetings Jakob Oesterling

2013-05-29The new beta is for Elixir 0.9.x. Some of the content is incompatible with 0.8
55OK

“Elixir-IO” === IO
evaluates to false in iex.
I’m using Elixir 0.9.0, Erlang R16B (erts-5.10.1)

2013-05-29Beta 2.0 covers Elixir 0.9
55OK

:“IO.puts” 123

raises the following error

(SyntaxError) iex:3: syntax error before: 123
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:128: :elixir_parser.yecctoken_
end_location/1
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:113: :elixir_parser.yeccpars1/
7
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:56: :elixir_parser.yeccpars0/5

src/elixir_translator.erl:16: :elixir_translator.forms/4
/Volumes/Work/github/elixir/lib/iex/lib/iex/server.ex:77: IEx.Server.eval/4
/Volumes/Work/github/elixir/lib/iex/lib/iex/server.ex:36: IEx.Server.do_loop/1

2013-06-13The book has :"Elixir.IO".puts
73TYPO

“and rainfall an a number of weather stations”

-> you probably mean “and rainfall at a number of weather stations”?

2013-06-13
79SUGGEST

Inconsistent singular/plural:
The explanations for some functions say “returns a count”, “returns the size”, then others say “return a list”, “return true”, etc. Clearer would be if all were plural or all singular.

2013-06-13
105TYPO

“in the order you defined then“ -> ”in the order you defined them"

2013-06-13
127TYPO

“we’re coded all of the top conveyor belt“ -> ”we’ve coded all of the top conveyor belt"

2013-06-13
203TYPO

“All other Erlang code […]” ->Elixir code

2013-06-13
69SUGGEST

Explain why
lc x inlist 1..5, do: x * x
doesn’t works, but
lc x inlist :lists.seq(1,5), do: x * x
does

2013-05-29It's because 1..5 isn't a list,,,
205TYPO

“We can demonstrate this is two steps” -> “in two steps”

2013-06-13
206TYPO

“upquote is a silly name” -> “unquote is a silly name”

2013-06-13
208TYPO

“we could use unquote_slicing” -> “unquote_splicing”

2013-06-13
112TYPO

mix.esx should be mix.exs

2013-06-13
114TYPO

“…putting those tests into the file test/cli_test.ex” should be “cli_test.exs”.

2013-06-13
114TYPO

Not sure if it matters, but mine says

Code.require_file “test_helper.exs”, DIR

not

Code.require_file “test_helper.exs”, FILE

I’m running latest and greatest built from master branch.

2013-06-13Looks like they changed it. Thanks
215TYPO

The text “concept o protocols” should be “concept of protocols”.

2013-06-13
52SUGGEST

Can you bold the sentence “The |> operator takes the result of the expression on its left and inserts it as the first parameter of the function invocation to its right.” or move it to the first paragraph of the section so that it’s easier to find? It’s kind of buried in section 6.5 when, in fact, it is the most important sentence in the entire section! Thanks! :)

2013-06-13
201TYPO

> manipulate your programs code as if it were any other data.

programs -> program’s

2013-06-13
30TYPO

Missing “equals” in “Operators” strict equality example AND strict inequality example

a=b # strict equality (so 1 1.0 is false)

Should be (so 1 === 1.0 is false)

Also

a!==b # strict inequality (so 1 != 1.0 is true)

Should be (so 1 !== 1.0 is true)

2013-06-13
1OK

(Sorry can’t see the page number in my reader :()

project/issues-01/lib/issues/github_issues.ex

alias HTTPotion.Response

Can’t get it to work. I get:

module HTTPotion.Reponse is not loaded and could not be found

2013-06-14You're missing an 's' in Response. \n \n
8TYPO

5th paragraph down reads: ‘You can also load a file as if you’d typed each line into iex using import_file. If this case,…’ Should it be ‘In this case’?

2013-06-13
7OK

The IEx.Options module doesn’t seem to exist on OS X.

$ iex
Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (0.9.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> h(IEx.Options)
Could not load module IEx.Options: nofile
:ok

2013-06-13I hate to say it, but it works fine here.
7SUGGEST

Some examples use ‘exs’ as an extension and some ‘ex’.
The former can be seen in the green bar with text:“intro/hello.exs”.
The latter in the example code reading “$ elixir hello.ex” a few lines later.

2013-06-13I need to explain the difference earlier. Thanks.
52TYPO

DB.find_customers
|> Orders.for_customers
|> sales_tax(2103)
|> prepare_filing

The sales_tax function should have 2013 as its argument :)

2013-06-13Elixir is the language of the future
130ERROR

“Jsonex.decode” within the process function should be “decode_response” I think, that’s what the code says on pages 129 and 131 as well.

2013-06-13
145SUGGEST

The number of process here is rather small 200,000 try a few million
impress people.

Why not use 200_000 integer syntax. I tried a million processes
1_000_000 The underscore syntax is much nicer. Good opportunity to use it here

2013-06-13
7SUGGEST

IEx.Options doesn’t exist for my version of iex. I’m running Erlang R16B and IEx 0.9.0, which came as part of the 0.9.0 Elixir pre-built binary for Mac. So the whole “Customizing iex” section does not work for me.

Perhaps a note saying “not applicable to all versions of iex” would help.

2013-06-13
7SUGGEST

I compiled 0.9.0 and IEx.Options is undefined. I compiled 0.9.1 and it works, so it looks like IEx.Options is new and was introduced in 0.9.1.

2013-06-13
41TYPO

“However, this doesn’t.” Since that sentence refers to the following text snippet, should the period be a colon?

2013-06-13
51TYPO

In the line “tax = sales_tax(orders, ’2013)” there is a spurious single quote.

2013-06-13
26ERROR

In 4.2 System Types, if Elixir uses the Erlang built-in reference type, then those references are not globally unique. Their value can wrap up after a loooot of calls and also multiple Erlang VMs can end up sharing the same references. You can try launching a few (3+) Erlang shells and type “make_ref().” in them. You’ll see that some of them get repeated across VMs. I also tried this with Elixir and it has the same behaviour.

Cheers :)
Francis

2013-06-24
55TYPO

The sentence, “You require a module you want to use the macros defined in that module.” is missing a word. Not sure if you meant “…require a module WHEN you want to use the macros…” or not.

2013-06-13
123ERROR

sort_into_ascending_order should use ‘<’ here: fn i1, i2 -> i1[“created_at”] > i2[“created_at”] end

The unit test finds this error

2013-06-13
116OK

Could not get Issues.GithubIssues.fetch to run in cli.ex. I had to ‘import Issues.GithubIssues, only: [fetch: 2]’ and call ‘fetch’

2013-06-13Runs OK here. Did you start iex with "iex -S mix"?
83TYPO

missing paren in “VT (0x0b”

2013-06-13
93TYPO

Description of rstrip(str) starts “:Removes trailing…”. The leading “:” should be removed.

2013-06-13
49TYPO

Missing “)” at end of: “These built-in functions return values (not true or false.”

2013-06-13
48TYPO

“So it is a good idea to add a guard clause to stop this happening” should end with “stop this from happening”

Thanks for the great book!

2013-06-13
127OK

in test “column_widths” do

assert widths [ 5, 6, 7 ] should be assert widths [ 5, 5, 7 ]

2013-06-13I believe it is correct
20TYPO

“it the source file had contained any modules” should be “if the source file had contained any modules”

2013-06-13
29TYPO

“If you listen to function programming” should be “If you listen to functional programming”

2013-06-13
98TYPO

In “Your turn…”, “Define a decord…” should be “Define a record…”

2013-06-13
6TYPO

Near the bottom of page 6: “typing control-G followed q and return” - “followed q” should be “followed by q”.

2013-06-13
6SUGGEST

Near the top of page 6: “For help on the module, type h(IO).” - it seems the parentheses aren’t needed; ‘h IO’ works fine, as does ‘h IO.puts’. If you look at ‘h c/1’, the examples there don’t use parentheses - this should be consistent across all helper functions… just tried ‘h h’ and that does give examples of using h without parens.

2013-06-13The parens are indeed optional on all function calls.
8SUGGEST

A little way down page 8 (and elsewhere): “We can also compile and run it inside iex using the c helper.” … iex> c(“hello.exs”) - using c without parentheses reads better, and is easier to type. I’ve read the advice about when to use parentheses in the embryonic style guide, and I feel that the helper functions in the shell are a good example of where not to use them.

2013-06-13
15OK

Page 15, second para: “Let’s look at a few more examples.” - why is IEx allowing variables to be re-bound? That just seems wrong, and deserves explanation.

2013-06-13Because Elixir allows variables to be rebound :)
29SUGGEST

In the description of identifier syntax on Page 29 (first two paras of section 4.4) there’s no mention of at signs (@). The footnote on page 24, about atom identifiers, says they are allowed. Should they be mentioned here?

2013-06-13You're right—the footnote shouldn't use "identifier"
29TYPO

Page 29, 2/3 of the way down: “Source files names are written in lower case…” - ‘files’ should be ‘file’.

2013-06-13
29SUGGEST

The section on Truth, bottom of page 29, and the section on Ranges following (p30) look as if they should be in the earlier discussion of data types, rather than being in 4.4.

2013-06-13It's a close call, but I think that the truth discussion belongs here—it is a convention, \n \nYou're right about ranges.
142SUGGEST

The previous page shows a spawn example using “spawn” but this page shows “spawn_link”, since the explanation why use this comes a few pages later, I suggest to make a note about that to don’t confuse the nice reader.

2013-06-13
30ERROR

Under operators:

`a!==b # strict inequality (so 1 != 1.0 is true)`

That should be “`1 !== 1.0` is true”

2013-06-13
30SUGGEST

`xor` is also a valid boolean operator:

```
iex> true xor true
false
```

It’d be nice to see it included for completeness.

2013-06-13
15SUGGEST

Ranges are mentioned on page 15 (“You can even match on ranges”) and touched on briefly again on page 30 without any illustration. It’d be nice to get a little more detail early on about these structures.

2013-06-13
44SUGGEST

Why “Rakefile”? For clarity, a better example might be a file that we’ve actually created for the book (e.g., intro/hello.exs").

2013-06-13
143SUGGEST

The code does not seem to work on 0.9.1 (at least on my machine ;) ).
José Valim recommended to change this:

receive do
final_answer ->
“Result is #{final_answer}”
end

to

receive do
final_answer when is_integer(final_answer) ->
“Result is #{final_answer}”
end

This works.
(see Github issue 1176 on elixir-lang/elixir)

2013-06-13
145SUGGEST

Don’t know if it matters much, just noticed that the default max nr of processes seems to be higher: The Erlang docs (see erlang.org/doc/man/erl.html) say 262144, this matched my system.

2013-06-13
41TYPO

“tests is a is included in enum” should be “tests if a is included in enum”

2013-06-13
43TYPO

“(We” should be “We”

2013-06-13
31SUGGEST

It says here that `<>`, “concatenates two binaries (such as strings)”. Since the fact that strings are binaries isn’t covered until page 90, I’d like to see a little more treatment around this point earlier on.

2013-06-13
21TYPO

“I’m not saying that Elixir as a magic potion”

as -> is?

2013-06-13
27SUGGEST

“What if you instead want to force Elixir to use the existing value of the variable in the pattern? Prefix it with an ^ (a caret).”

For me this is a rather innocent explanation for an important concept. Even the examples for this are misleading. When you apply this concept with just lists, it led me to think it was only applied to lists. I had to put some effort in iex to grasp what you were trying to say. In think an example like the following would be much clearer:

a = 1
1
a = 2
2
^a = 1

(MatchError)

2013-06-13
26SUGGEST

“We don’t use references in this book.”

Would you mind explaining why? Are they a bad thing? Are they too complex for this level?

2013-06-13Because at this level, we don't need to. I really don't want to derail the flow with an explanation here.
40TYPO

“&1 will
be the first parameter to that function,, &2”

double commas

2013-06-13
48TYPO

“We’re seen that pattern matching allows Elixir”

We’ve seen?

2013-06-13
49TYPO

“There documentation is online on the same page as the type check functions.”

‘There is documentation’?

2013-06-13
30TYPO

Example in comparison operators section demonstrates the threequels flavor of equality, but the comments use the double equals variety.

Extracted from line 17 of PDF version (near comparison operator section):

a = b # strict equality (so 1 1.0 is false)
a !== b # strict inequality (so 1 != 1.0 is true)

Should be:

a = b # strict equality (so 1 = 1.0 is false)
a ! b # strict inequality (so 1 ! 1.0 is true)

2013-06-13
121OK

The explanation says that HTTPotion.start is not necessary as long as you add :httpotion in the application list in mix.exs.

For me HTTPotion.start in GithubIssues.fetch/2 was necessary, or ibrowse would not be usable. This was the case both for elixir 0.9.0 and 0.9.1.

2013-06-14This is strange, because I've tried everything I can think of and I'm not seeing this problem. \n \n
114TYPO

At the top top of page, in the @doc comment: “…the number of
entries to format” should end with a period.

2013-06-13
117TYPO

When I try run the code it does not compile because on line 42 of
cli.ex the parameter `count` is unused. Changing `count` to `_` fixes the
problem —- when I rerun the `mix run` command the app compiles and prints
the usage message.

2013-06-13I can't reproduce this. Is there possibly a typo in your code?
117TYPO

The period at the end of the first sentence in “Finding a Library”,
which is after a URL, is printed on the beginning of the next line instead
of immediately after the URL. The line should not wrap just before a period.

2013-06-24We'll fix that during layout
120SUGGEST

The `when` clause of the `case` statement is used without
explanation, and I don’t think it’s explained in the description of the
`case` statement in the section on control flow.

2013-06-13
123TYPO

In section 11.7 you create the function `decode_response` but on p.123 in “Transformation: Sort Data” the `process` function calls Jsonex.decode directly instead of calling `decode_response`.

2013-06-13
127TYPO

The end of the title of section 11.10 ends with “(#sec.cmd-line}”

2013-06-13
120OK

after escriptizing, ibrowser in HTTPotion complains:

(ArgumentError) argument error
:ets.lookup(:ibrowse_lb, {’api.github.com’,443})
src/ibrowse.erl:317: :ibrowse.send_req/6
/Users/alai/sandbox/issues/deps/httpotion/lib/httpotion.ex:82: HTTPotion.request/5
/Users/alai/sandbox/issues/lib/issues/github_issues.ex:8: Issues.GithubIssues.fetch/2
/Users/alai/sandbox/issues/lib/issues/cli.ex:49: Issues.CLI.process/1
/private/tmp/elixir-mL7K/elixir-0.9.1/lib/elixir/lib/kernel/cli.ex:39: Kernel.CLI.run/2
escript.erl:741: :escript.run/2
escript.erl:277: :escript.start/1

To fix this, add these to the beginning of the fetch method in Issues.GithubIssues:

:ssl.start()
:ibrowse.start()

2013-06-14Is your version of HTTPotion old? Does it have \n \n \n def application do \n [applications: [:ibrowse, :ssl]] \n end \n \n \nin its mix.exs?
145OK

Same as #51774 there seem to be some difference with messages when application exits. In 0.9.1 at least, running link1.exs as described will print “MESSAGE RECEIVED: {:EXIT,#PID<0.36.0>,:normal}” instead of the expected “Nothing happened as far as I am concerned”.

2013-06-14This is actually a bug in Elixir: https://github.com/elixir-lang/elixir/issues/1050
49TYPO

hdlList) should be hd(List), I think

2013-06-13
146OK

Apparently v0.9.1 of Elixir behaves differently: EXIT messages get sent to the sender even when calling spawn() (instead of spawn_link()). I saw this with a previous example, too.

With both spawn() and spawn_link(), it seems like the sleep() never gets run because the EXIT is sent immediately. Likewise, in the earlier example the EXIT arrived BEFORE the message sent to the parent actor by the child.

2013-06-14This is a bug in Elixir: https://github.com/elixir-lang/elixir/issues/1050
157ERROR

—name seems to only work as describe with 0.9.1. When I run `iex —name wibble` with the 0.9.0 binary release, `Node.self` still returns :“nonode@nohost” and the prompt is the default prompt.

2013-06-13
157OK

When defining `fun`, running Elixir 0.9.1, I had to use parens. Without them, I saw this:

=ERROR REPORT==== 4-Jun-2013::11:20:43 ===
Error in process <0.45.0> on node 'wibble@widget.corp.about-inc.com' with exit value: {{'Elixir.File.Error','__exception__',enoent,<<14 bytes>>,<<1 byte>>},[{'Elixir.Kernel',raise,2,[{file,"/private/tmp/foo/elixir-0.9.1/lib/elixir/lib/kernel.ex"},{line,3046}]},{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,569}]},{erl_eval,expr_list...

but with fun defined thusly, it ran fine:

fun = fn -> IO.puts(Enum.join(File.ls!, ",")) end
2013-06-13Strange, it runs here. But I've added the parens anyway—it's clearer.
148TYPO

“identify of the monitor” should be “identity of the monitor”

2013-06-13
54SUGGEST

It is largely clear what is going on, but import is first defined on page 54 but it is used on page 52. For the sake of flow, since import is not really used up until that point, it might be better to use `(1..10) |> Enum.map(&1*&1) |> Enum.filter(&1 < 40)` on page 52.

2013-06-13
57TYPO

‘so return `.ex` if given “`dave/test.exs`”’. Should that read ‘so return `.exs`…’ ?

2013-06-13
20OK

iex(1)> c ‘hello.exs’
Compilation error on file 104

(FunctionClauseError) no function clause matching in :elixir_compiler.file_to_path/2
src/elixir_compiler.erl:47: :elixir_compiler.file_to_path(104, “.”)
/private/tmp/elixir-ybNf/elixir-0.9.1/lib/elixir/lib/kernel/parallel_compiler.ex:56: Kernel.ParallelCompiler.“spawn_compilers/7-fun-0”/3

Can’t seem to compile the example code.

2013-06-13Use double quotes for strings \n \niex> c "hello.exs"
152SUGGEST

In the code for the scheduler, you’re using a variable called “factorial” while demonstrating Fibonacci numbers :)

Suggestions for a better name: “fib_number”, or if the emphasis is that the scheduler doesn’t know anything about the calculation: “processed_number”, “calculated_number”, or something like it?

2013-06-13
154TYPO

“Run your code on a direcory” -> “Run your code on a directory”

2013-06-13
66SUGGEST

Might be helpful to note that iex will print a character list as a list of ints instead of as a printable string if any individual value is nonprintable.

2013-06-13
38TYPO

DB.save record, [ {:use_transaction, true}, {:logging, “HIGH”} ]
can we written more cleanly as

Should be: can “be” written …

2013-06-13
66TYPO

The word character is written as “charcter” in the first sentence of the third “Your turn” problem (Beginning with “An Elixir single quoted string…”).

2013-06-13
4030TYPO

Operators section -> comparison operators, second example. The comment is missing the second =, so reads != instead of !==

= example is =

a!==b # strict inequality (so 1 != 1.0 is true)

= example should be =

a !b # strict inequality (so 1 ! 1.0 is true)

2013-06-13
132OK

Fetching and building the ex_doc dependency leads to errors on ubuntu 13.04.

Fix is to edit deps/ex_doc/sundown/Makefile and remove the “-Wl” on line 44, then run mix deps.compile to fix up.

2013-06-13I've reported this to the owner of the project.
94TYPO

s/xebra/zebra

2013-06-13
106TYPO

In first code snippet of 10.5 at line 5, `IO,puts` should be `IO.puts`.

2013-06-13
0SUGGEST

Can you allow kindle locations for errata as well as page numbers?

2013-06-14Not easily—I'm not sure how we could precalculate them. \n \nThe whole page-number thing is legacy, as will go away as soon as we work out something better
231SUGGEST

Excellent idea to shove this exception material out to an appendix! Can I tempt you into going further and dropping it altogether, maybe just leaving a link to something else online? I suggest it is muddying the waters a bit, and it would be more productive to add some more discussion on the ok/fail pattern.

2013-06-13I think it is needed—there is still the need for exception handling in Elixir code.
75SUGGEST

a general comment - you introduce |> around p51 but still use the << foo(bar, fun) >> form for the middle section of the book when you could in many (all?) cases use << bar |> foo(fun) >>

just wondering if it’s deliberate; arguably, |> is a big thing and it would be good to see it used more.

you seem to use it more consistently towards the end of the book.

2013-06-13Mostly that's a conscious choice. I use |> when the code represents a chain of transformations. But for a single function call, I think it is debatable \n \n[1,2,3] |> Enum.map &1*2 \n \nvs \n \nEnum.map [1,2,3], &1*2 \n \nMaybe it's just my old jaded eyes, but I find the latter easier to read.
222TYPO

polumorphic

2013-06-13
220SUGGEST

Pedantry: count and member? can be defined in terms of reduce, so you probably could make do with just reduce by itself… (Of course, efficiency varies…)

2013-06-13
212ERROR

deep within the source of the interpreter ? should be (elixir) compiler, no?

2013-06-13
211ERROR

here and various later pages: technically, you’re hiding various kernel definitions and using your own

also, might be worth underlining that this hiding only applies in current scope, not globally.

2013-06-13
201SUGGEST

Not sure about your discussion of homoiconic in this context.

Eg Haskell could be considered homoiconic under the criteria you give, eg the GHC compiler allows rewrite rules which can be used to manipulate code for certain effects, and these work by adding new transformations on code at compile time.

Elixir’s macro mechanism seems to be a compile-time thing, from what I’ve seen in your book, i.e defines certain forms which get expanded before further compilation.

Lisp’s homoiconicity is clearly something different, e.g. allows dynamic changes to macro handling IIRC. Does Elixir allow such, um, “flexibility”?

Since the concept of homoiconicity is only mentioned briefly and not developed much, it might be wiser to just leave it out?

2013-06-13
201SUGGEST

“So never use a macro when you could use a function.” - can you put this in bold? - this is more important than explaining homoiconicity IMHO

2013-06-13
152SUGGEST

Sorting - it’s a lot safer and friendly for properties like stability (of sort results) to use <=, and I suggest it’s better for beginners to see and use the <= test by default. It does save some grief!

Compare: Erlang’s docs for sort/2 say: “Fun(A, B) should return true if A compares less than or equal to B in the ordering”. Typically sort code will swap a pair of elements only if the function returns false, so will not swap ‘equal’ elements hence will preserve their relative order in the original collection.

Example: [(1,‘a’), (1,‘b’), (2,‘c’)] sorted by (<) vs (<=) on the first elem in the tuple?

2013-06-13
152SUGGEST

how about this order for the ready clauses under receive?

{:ready, pid} when length(queue) == 0

{:ready, pid}

length is never going to be negative (we hope), and the queue being empty is the definite stopping point we want to catch, hence better style perhaps to catch it explicitly.

this leaves the looping case a bit simpler…

also, the sort is probably better done outside of the loop - it’s a better separation of concerns etc.

2013-06-13
152SUGGEST

how about writing run as

1 .. num_processes
|>
Enum.map(….)
|>
schedule_processes(to_calculate, [])

?

2013-06-13
151SUGGEST

^pid - is this implicitly adding an old_var = new_var constraint?

is there something subtle going on with repeated bindings of “pid”? (without the ^ sign, it looks like the occurrence in the pattern is binding the matched result rather than forcing a match on the argument in the enclosing lambda…) if so, might be worth some more comment

2013-06-13
216TYPO

becuase

quite a few typos around in later pages: collectiom, appraoch, “display it s a”, termporarily, “simply macro”, “back into the compilation tree[?]”, parmeters, “you applications”

2013-06-13
142SUGGEST

tail recursion box - might help to show a version of fib which is tail recursive, just for comparison

2013-06-13
123SUGGEST

would you consider << Enum.map(HashDict.new(&1)) >> in the main code instead of adding a new (and quite simple) function?

Yes, naming could make it easier for beginners, but otoh it can help to see that it is just a map and for the mapped function to be shown more directly, ie not hidden inside another definition.

Note that you call Enum.take(n) later - is map “harder” than take? (-:

2013-06-13I changed he function to use |>, as I think it should have done originally. But I kept the separate function—I like the separation of concerns here.
124SUGGEST

Re. the “worries me a little” - See my comment for p152. I used to get burnt too, until I started to use <= unless I had a good reason not to!

2013-06-13
107TYPO

{:ok, data}a and the …

extra ‘a’ before and

2013-06-13
104SUGGEST

Probably more correct to say “nested pattern matching” rather than recursive pattern matching.

One reason is that the elixir patterns are finite, i.e. looking at most only a few nodes deep in a value…

2013-06-13
79TYPO

“true is there is”

2013-06-13
71TYPO

who’s product

2013-06-13
52SUGGEST

“The value of |> is the value of its right hand side”

Not really, eg compare “0 + x”.

Why not just say << x |> f(y,z) === f(x,y,z) >> etc

And so the value is “f(x,y,z)” rather than “f(y,z)”

2013-06-13
51TYPO

guard clauses are your friend[s] ?

2013-06-13
28SUGGEST

“short-circuit syntax”

you mention syntactic sugar elsewhere - better to use this, especially to avoid confusion with short-circuit evaluation?

2013-06-13
21SUGGEST

“new copy of it” - worth adding something like “new copy of it, though often sharing as much of the old structure as it can (and so isn’t so wasteful on memory)” etc?

some people could take “new copy” too literally …

2013-06-13Not yet, grasshopper, not yet
14ERROR

“could be unified” - technically no - it is one-way matching whereas unification is two-way.

suggest “made the same” instead of unify? you introduce the right term in the next line so I don’t think you lose anything, and you avoid introducing another technical term…

Example
a, 1 = 2, b
would be unification if b was set to 1 in the process

2013-06-13
217TYPO

“before and implementation for Any” -> “before an implementation for Any”

2013-06-13
217TYPO

“defimp stanzas” -> “defimpl stanzas”

2013-06-13
223TYPO

“modules sing them” -> “modules using them”

2013-06-13
223TYPO

“nothing more that“ -> ”nothing more than"

2013-06-13
223TYPO

“let the compiler validate that that” -> only one “that”

2013-06-13
149ERROR

Please see github.com/elixir-lang/elixir/issues/1176

2013-06-24
8TYPO

it the source file had contained any modules, their …

should be: if the source file had contained any modules, their …

2013-06-24
21OK

In section 3.3:
is divvied up
should be:
is divided up

2013-06-24Divvied is what I meant: http://www.merriam-webster.com/dictionary/divvied
34ERROR

a, b = 1, 2

is not a valid expression. It should be:

[a, b] = [1, 2]

or

{a, b} = {1, 2}

2013-06-24
35TYPO

or a simple error message is the file could not be opened.

should be:

or a simple error message if the file could not be opened.

2013-06-24
216TYPO

In the sentence “Elixir has the concept o protocols,” “o” should be “of.”

2013-06-24
216TYPO

In the sentence “And becuase self is a PID[…],” “becuase” should be “because.”

2013-06-24
166OK

… —this chapter will look at servers, the next at supervisors, and finally we implement applications.

should read:

… —this chapter will look at servers, then next at supervisors, and finally we implement applications.

2013-06-24I think it's OK as it stands.
151SUGGEST

{:shutdown} -> exit(0) —-> { :shutdown } -> exit(0)
^ ^ ^ ^
Consistent spacing with the rest of the code.

2013-06-24
148TYPO

In “Your Turn”, the first point:

Use spawn_link …. and then exit immeditately. (should read: immediately)

2013-06-24
150SUGGEST

In the Your Turn section:

• Change the ^pid in pmap to _pid. This means that the receive block will take response in the order the processes send them. Now run the code again. Do you see any difference in the output? (I don’t). Are you scared by this?

I think the “I don’t” followed by ‘Are your scared by this’ is misleading.

I think you could convey a clearer message by urging the reader to increase the size to map (50 elements will give me a weird order), which I think would be slightly simpler than passing a different function or sleeping.

2013-06-24
64SUGGEST

In the “keeping track of values” section: it’s clear you want to work towards explaining reduce, but sum isn’t a function that needs reduce - you can of course write << sum([head|tail]) = head + sum(tail) >>, in the style of “len” a few pages before. Some readers may wonder why the change of style, so a few words of explanation might go down well.

Alternatively, “_number_digits” from p97 is a good example to use with reduce - it really does need the running total.

2013-06-24
88SUGGEST

can simplify by omitting sign arg from _number_digits and doing the mult by –1 in the relevant case for number.

without this arg, it’s easier to use reduce as well - which underlines that it’s a left-to-right loop over the digit chars

(mistakenly reported for p97, apologies)

2013-06-24
68SUGGEST

“Lists of lists” - isn’t this section more about nested patterns?

also, this kind of thing really should use Enum.filter? (Wouldn’t you use #select in Ruby?)

2013-06-24
69SUGGEST

weather2 etc, the guard condition can be replaced by using target_loc twice in the pattern - the match will fail if the values differ (and will fall back to the final clause)

too obscure though? or a useful elixir idiom?

2013-06-24
79TYPO

foldl and foldr are currently in List module, not enum

2013-06-24
102SUGGEST

fizzbuzz example is much clearer as

(1..n) |> Enum.map(foo)

where foo handles the logic for a single number.

this way, you don’t have to mix up this logic with that for generating a range of numbers, stopping, reversing etc.

of course, this doesn’t help to demonstrate “cond”…

2013-06-24
251TYPO

String.h should be String.t?

2013-06-24
254TYPO

“that my creating a …”

2013-06-24
47TYPO

Poor sentence structure in second “Your turn…” activity for Anonymous Functions.
“Write a function that takes a single integer (n) calls the previous function passing it…”
Should be “(n) and calls” or “(n) then calls” or something similar.

2013-07-10
78TYPO

In description of the split function:

In n is negative, counts …

should be:

If n is negative, counts …

2013-07-10
73SUGGEST

The Enum Module
The functions in the Enum module work with all iterable collections. …

You should briefly explain what iterable (or enumerable ?) collections are. Like : An iterable collection is anything that implements the Enumerable protocol (see Enumerable in Elixir docs). This concept of protocol will be discussed later in the book. In short, protocols are like interfaces in other programming languages​​.

2013-07-10I think I'll keep it as it is. I hope most folks have an intuitive idea of what's going on, and I'm not sure introducing protocols here helps.
80TYPO

keylist is a list of tuples. Returns …

should be:

kwlist is a list of tuples. Returns …

In descriptions of keyword lists functions, you should replace all occurrences of keylist by kwlist

2013-07-10
86TYPO

and indent the trailing delimiter the the same margin

should be:

and indent the trailing delimiter the same margin

2013-07-10
70ERROR

In all the code for weather3.ex you do not use a guard but use pattern matching.

Code looks like:

>defmodule WeatherHistory do
>def for_location([], target_loc), do: []
>def for_location([ head = [, target_loc,, _ ] | tail], target_loc) [ head | for_location(tail, >target_loc) ]
>end
>def for_location([ _ | tail], target_loc), do: for_location(tail, target_loc) end
>The key change here is this line:
>def for_location([ head = [, target_loc,, _ ] | tail], target_loc) Compare that with the previous >version.
>def for_location([ [ time, target_loc, temp, rain ] | tail], target_loc)

However, when you summarize you do use a guard and a new variable:

>In the new version, we can just use the head, making it a lot clearer.
>def for_location([ head = [, target_loc,, _ ] | tail], target_loc) when loc == target_loc do
> [ head | for_location(tail, target_loc) ]
>end

don’t know where the ‘loc’ variable is coming from in this new def for for_location. It, also, seems unnecessary as you can use the pattern matching as is and if the target_loc in the head part is not the same as what’s passed in it will not match.

2013-08-01
7SUGGEST

Re: Customizing iex. ANSI escape sequences for colors are not supported by default on Windows. Windows users should be encouraged to disable the color feature with “IEx.Options.set(:colors, [enabled: false])”.

2013-07-10
223ERROR

There seems to be a type mismatch in the return line
“#Process: ” <> list_to_binary pid_to_list(pid) <> ‘!!’.

You probably want either
“#Process: ” <> (list_to_binary pid_to_list(pid)) <> “!!”. <— concat strings
or
“#Process ” <> list_to_binary [pid_to_list(pid) | ‘!!’] <— join lists, then convert

2013-07-10
60TYPO

In code sample of ‘how list are displayed iex’ the shell prompt has > rather than >.

2013-07-10
21SUGGEST

In section 3.3 you introduce the [h|t] notation and start talking about the head and tail of a list but the actual explanation of what is meant by head and tail is deferred to section 4.4 (Lists) on p. 27.
Maybe a brief explanation of what is meant by head & tail would be better suited in section 3.3 where the terms are first used or possibly have a reference to section 4.4?

2013-07-10
19SUGGEST

In chapter 3 on immutability it might be an idea to mention that functions in functional programming languages usually have no side effects on the data passed to them.
This might make it easier for someone reading up on other functional programming languages after reading this book when the term side effect comes up in context of immutability.

2013-07-10I don't think this is what is meant when people talk about side effects and functions. I _think_ they are talking about idempotence here.
1SUGGEST

Maybe include a brief section along the lines of ‘Why should I care about Elixir?’ in chapter 1 for people who already use or know functional programming languages.
A brief comparison or overview table with well established languages such as OCaml or Haskell might be nice with a disclaimer ‘If you don’t know these languages don’t look at it or your head might explode from gobbledygook’.
Parallel computation and nice syntax immediately spring to mind here.

2013-07-10Let me think about that. Right now, I'm guessing folks who know another functional language will be able to draw their own parallels. Let's see what others say.
108ERROR

Running control/case2.ex

defrecord Person, name: “”, age: 0

dave = Person.new name: “Dave”, age: 27

case dave do

Person[age: age] = record when is_number(age) && age > 21 ->
IO.puts “You are cleared to enter the Foo Bar, #{record.name}”

_ ->
IO.puts “Sorry, no admission”

end

Result with `elixir -e case2.ex`

  • (CompileError) /Users/tonini/Projects/ideas/elixir/def.exs:7: module Person is not loaded but was defined. This happens because you are trying to use a module in the same context it is defined. Try defining the module outside the context that requires it.
    Person.module_info(:compile)
    src/elixir_aliases.erl:75: :elixir_aliases.ensure_loaded/4
    /private/tmp/elixir-z91O/lib/elixir/lib/kernel.ex:3213: Kernel.“MACRO-access”/3
    /Users/tonini/Projects/ideas/elixir/def.exs:7: Kernel.access/2
2013-07-10
113TYPO

project and to share between projects. Have a look at

The beginning of this sentence is missing.

2013-07-10
239ERROR

%r{red}h should read %c{red}h

2013-07-10
69TYPO

Code for “weather2.ex” doesn’t compile.
Missing “do” in second def for “for_location”.
Also “loc” is undefined. Should be “target_loc”?

2013-07-10
160TYPO

CURRENT
We’re been using OTP all along

SUGGESTED (the “v” is what’s changed):
We’ve been using OTP all along

2013-07-10
69TYPO

def for_location([ [time, target_loc, temp, rain ] | tail], target_loc)
[ [time, loc, temp, rain] | for_location(tail, target_loc) ]
end

Should be

def for_location([ [time, target_loc, temp, rain ] | tail], target_loc)
[ [time, target_ loc, temp, rain] | for_location(tail, target_loc) ]
end

2013-07-10
41TYPO

“You have to be careful when using the &1 notation—when Elixir sees it, in converts the immediately enclosing expression into a function.”

in’ should be ‘it’

2013-07-10
57TYPO

“a 3 chaacter-wide field” -> character

2013-07-10
107TYPO

“full power of nexted pattern matches” -> nested

2013-07-10
144SUGGEST

When modifying the code between spawn3 and spawn4, it’d be nice if we had the same sort of left-margin indicators that happens between spawn2 and spawn3 on the “after” line.

2013-07-10
145SUGGEST

Would it be better to use defp for the _fact functions instead of doing the underscore prefix?

2013-07-10
145SUGGEST

Any particular reason this one is a .exs file and not a .ex file? They both appear to run.

2013-07-10Inconsistency on my part :)
85TYPO

Double “if” in Enum#fetch! description:

“raising an exception if if n is”

2013-07-10
88TYPO

“when” should be “where” in Enum#split description:

“Returns a tuple when the first element is the first n elements from collection…”

2013-07-10
88TYPO

“In” should be “If” in Enum#split description:

“In n is negative, counts down from the end of the collection.”

2013-07-10
88TYPO

Inconsistent name “fun” instead of “fn” for function argument in Enum#uniq definition:

“uniq(collection, fun // &1)”

2013-07-10
91ERROR

In chapter 8.3 in the “Your turn…” page, the last exercise states:

calculate(“123 + 27”) # => 150

The argument for the calculate function has double quotes instead of single quotes. I guess this is a mistake since the chapter is talking solely about single quotes (and the exercise is only possible with single quotes).

I’m loving the book thus far! Thanks!

2013-07-10
256TYPO

In Some Examples there’s this line:

( integer, atom -> { :pair, atom, integer }

This would appear to be missing a parentheses.

2013-07-10
52TYPO

Wrong:

> is the same as prepare_filing(sales_tax(list, 2012)).

Correct:

> is the same as prepare_filing(sales_tax(list, 2013)).

2013-07-10
259SUGGEST

It’d be great if it was explained here how to get rid of the elixir-specific unknown functions and types (so that, for example, I can more effectively use Dict.t in my code without generating a warning). It just requires adding the necessary ebin with the full path using —add_to_plt at the moment.

2013-08-01
192SUGGEST

In the section for OTP: Servers it gives a high level overview of the basic callbacks provided by GenServer. It’d be good to see a similar exposition of some of the options in supervisors (e.g., more meat on what “one_for_one” means). At a minimum, it would be good to see links to more of the “online resources” mentioned.

2013-07-10The previous paragraph has the link... I really don't want to get into a deeper discussion here, because that's a book in its own right. For now, I just want to give a taste.
175SUGGEST

I’d love to see some discussion or examples, even if it is just the simple case of Sequence.Server, of using ExUnit with gen_server.

2013-08-01To be honest, there's nothing really to discuss. You can just call the functions directly to test them.
29TYPO

The first paragraph here under “Another way of looking at the equals sign” has an opening parenthesize but no closing one

2013-07-10
203TYPO

3rd Sentence to Part III, More Advanced Elixir:

“THis al- lows you to add layers of abstraction to your code, which in turn makes your code easier to work with.” -> Should be ‘This’ instead.

2013-08-01
255ERROR

This isn’t really an error per se since in 0.9.3 this was legitimate, but as of 0.10.0 you can no longer do the “Single step” method for defining types (seen in the “Types and Records”) section. It wasn’t documented in the changelog, but it now generates the error “typespecs are not supported inlined with defrecord.”

2013-08-01
119ERROR

$ mix run ‘Issues.CLI.run([“-h”])’
runs into
[WARNING] mix run EXPR is deprecated, please use mix run -e EXPR instead
at least for Elixir 0.10.0

2013-08-01
41ERROR

under “boolean operators”, states: “These operators expect true, false, or nil as their first argument”. Installed 0.10.0 today and find this to be wrong; nil is not valid. elixir-lang.org/getting_started/1.html says only true and false

2013-08-01
263ERROR

You can no longer (as of 0.10.0) declare types in a single step inside of records. record_type is the only way to go. See Elixir issue #1404

2013-08-01
264SUGGEST

This may be a bit beyond scope, but it might be nice to give an example of how this is a little different with defrecord here (simply declaring it in the same module doesn’t appear to work in the way that would be obvious).

2014-04-19
35ERROR

References to IO.readline/1 should be changed to IO.read/2 as the former is deprecated in Elixir v0.10.0. There’s another reference to IO.readline on (PDF) page 111, as well as in the downloadable source code:

$ grep -ilrs ‘IO.readline’ .
./control/case.ex
./first_steps/handle_open.exs
$

2013-08-01
266TYPO

A2.5 Using Dialzer
should be:
A2.5 Using Dialyzer

2013-08-01
36SUGGEST

Section: Working with larger code examples

handle_open = function do
{:ok, file} -> “First line: #{IO.readline(file)}”
{_, error} -> “Error: #{:file.format_error(error)}”
end

=

You may want to use IO.read(file, :line) function since IO.readline(file) is deprecated as reported below.

C:\\Jana\\Erlang\\Elixir\\sandbox>iex
Interactive Elixir (0.10.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c(“handle_open.exs”)
[WARNING] IO.readline(device) is deprecated, please use IO.read(device, :line) instead
/Volumes/Work/github/elixir/lib/elixir/lib/io.ex:80: IO.readline/1
c:/Jana/Erlang/Elixir/sandbox/handle_open.exs:2: :elixir_compiler_0.“FILE/2-fun-0”/1
c:/Jana/Erlang/Elixir/sandbox/handle_open.exs:7: (file)
src/elixir_compiler.erl:65: :elixir_compiler.“eval_forms/4-fun-0”/7
src/elixir_compiler.erl:64: :elixir_compiler.eval_forms/4
src/elixir_compiler.erl:32: :elixir_compiler.quoted/2
src/elixir_compiler.erl:48: :elixir_compiler.file_to_path/2
[]
iex(2)>

2013-08-01
2TYPO

Chapter 8: The secon module, Stream, let’s you iterate over a collection lazily.

Should be “lets you iterate…” (allows, not let us)

2013-08-01
8.2TYPO

Chapter 8.2 The first map function taks the original list and…

taks -> takes

2013-08-01
190SUGGEST

I think it’s worth mentioning that the start_link function in Sequence.Server is special - the supervisor code that’s shown will attempt to call start_link and, if it’s not there, you get a very inscrutable error. In my case, I had only read the code about adding the start_link function to Sequence.Server, not actually added it, so it took me a bit to figure out what happened. A trip to the Elixir docs for worker cleared it up, but it’s probably worth mentioning that it’s part of the contract that start_link is implemented in the module being supervised.

2013-08-01
129SUGGEST

Since this is the first time we’ve seen the ‘use’ function from Kernel, it would be helpful if it was explained.

2013-08-01I don't want to distract from the flow here...
134ERROR

When doing mix deps / deps.get, two things happened differently than in the book:

1) I was prompted to install a “local copy” of rebar
2) HTTPotion is at 0.2.0 now even though the listing on expm said 0.1.0. mix deps.get ended up fetching the source for me regardless but complained that the specified version, 0.1.0, was unavailable.

I realize that the book can’t be kept perfectly in-sync with the versioning of this library but I think it’d be helpful to have some info listed about what might happen/go wrong if the version has changed.

2013-08-01
138SUGGEST

I’m learning this as I go, but it seems like SomeModule.some_function(&1) is a way of referring to a function by it’s arity? It shows up here in the convert_to_list_of_hashdicts function body but it’s not quite clear what it does, please add some elaboration on that (or even a note that say elaboration will be later in the book, if that’s the case).

2013-08-01It's the anonymous function generator, mentioned in the Functions chapter.
202TYPO

The contents show of sequence.app doesn’t match what 0.10 produces. Namely , the generated file delimits module names with dots, while the book shows dashes.

2013-08-01
170TYPO

iex(node_one@light-boy)> Node.list
[:“node_one@light-boy”]

the prompt should be still in node_two
iex(node_two@light-boy)> Node.list
[:“node_one@light-boy”]

2013-08-01
73TYPO

“Sometimes called hashes or associative arrays, Elixir somes with two implementations.”

“somes” should be “comes”.

2013-08-01
220TYPO

“were two ways on injecting values”, on->of

2013-08-01
223ERROR

“You can also evaluate a string with Code.eval”
Code.eval is now Code.eval_string. The example code also references it.

2013-08-01
126TYPO

Paragraph 2, line 3, twice the in : category the the Erlang distribution.

2013-08-01
145TYPO

Paragraph 3 : Elixir doesn’t have these issues, thanks to the architecture of the Erlang VM on which in runs. —> it runs

2013-08-01
153TYPO

Paragraph 5 : We asked it to run 10 processes, and it came back in 3.175mS. —> 3.175 [space] ms.

2013-08-01
153TYPO

Same typo at paragraph 11 : Ten thousand processes created and executed in 77mS. (unless millisecond is now mS rather than ms)

2013-08-01
168TYPO

Paragraph under Window #2, line 2 : was not made. And the node that it tried to connect to logs and error —> an error

2013-08-01
216TYPO

Last paragraph : Before we can our version of if, —> Before we can ? our version of if,

2013-08-01
217TYPO

Second to last line : you write “sum=#{1+2}”, Elixir evaluates 1+3 —> 1 + 2 ???

2013-08-01
218TYPO

Paragraph 6 says : If we instead wanted to insert just the elements of the list, we could use unquote_s[licing.

But the next two examples use unquote_splicing —> p instead of [ ?

2013-08-01
233TYPO

In paragraph “Built-in Protocols: Inspect”, the first line starts with THis instead of This

2013-08-01
21OK

Under the “Garbage Colection” section, on the third line of the third paragraph, divided is spelled as “divvied”.

2013-08-01I actually meant _divvied_ :)
76SUGGEST

A discussion of if/else comes in Chapter 11, but if/else are used to solve some of the “Your turn” exercises from Chapter 7 (like writing MyList.all? and MyList.filter). There may not be a way to cleanly do this, but it might be nice to make some mention of control flow before Chapter 7. I was writing some very ugly guard clauses (which may admittedly be your intention).

2013-08-01
238TYPO

Toward the bottom: "We’ve actually seen this already when we looked at the comments in the ‘TableFormatter‘ module on page 136. There, we used spec to document the types of function parameters and return values." The referenced section has no mention of what spec is- in fact @spec is only first mentioned in the book on this page.

2013-08-01
244TYPO

“You’ll find that the tracing now longer works.” “now” should be “no”

2013-08-01
243ERROR

In code listing: def add_list(list), do: Enum.reduce list, 0, &1&2 does not compile - it seems to require parens around the do:, e.g. like so def add_list(list), do: (Enum.reduce list, 0, &1&2)

2013-08-01
253TYPO

Some markup is bleeding through - at the very end of the page { :language=“session” } is in the generated text

2013-08-01
40TYPO

This:

The & operator converts the expression the follows into a function.

should be this:

The & operator converts the expression that follows into a function.

i.e. substitute the 3rd “the” for a “that”.

2013-08-22
101TYPO

Under “Defining Records: defrecord”, on first line of first paragraph, “define an record” should be “define a record”.

2013-08-22
64OK

iex> (1..10) |> Enum.map(&(&1*&1)) |> Enum.filter(&(&1 < 40)) have error in iex

iex> (1..10) |> Enum.map(&1*&1) |> Enum.filter(&1 < 40) works

2013-08-22This version of the book covers Elixir 0.10.1
42TYPO

In the “The Old Notation” sidebar, the & have been escaped as & in the code listings

2014-04-19
191TYPO

Third paragraph, “FWM” should be “FSM”

2013-08-22
192TYPO

First paragraph of 16.1, “You write a module module” - just need one “module”

2013-08-22
194TYPO

“The three even functions delegate the event handling to the gen_fsm library.” should be “The three event functions” (with a ‘t’)

2013-08-22
52OK

Problem with “The & Notation”. `add_one = &(&1 + 1)` does not evaluate on my elixir’s repl.


Erlang R16B
Elixir 0.10.0
OS X Mountain Lion


Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (0.10.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> add_one = &(&1 + 1)

(SyntaxError) iex:1: invalid token: &(&1 + 1)
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:128: :elixir_parser.yecctoken_end_location/1
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:113: :elixir_parser.yeccpars1/7
/usr/local/Cellar/erlang-r16/R16B/lib/erlang/lib/parsetools-2.0.9/include/yeccpre.hrl:56: :elixir_parser.yeccpars0/5
src/elixir_translator.erl:17: :elixir_translator.forms/4
src/elixir_translator.erl:29: :elixir_translator.forms!/4
src/elixir.erl:116: :elixir.eval/4
/private/tmp/elixir-40W3/elixir-0.10.0/lib/iex/lib/iex/server.ex:16: IEx.Server.start/1

iex(1)>

2013-08-22Your version of the book require 0.10.1
193TYPO

“we’ll put our state machine into it’s own module” =>“we’ll put our state machine into its own module”

2013-08-22
189SUGGEST

This is the end of chapter on gen_server, and the last sentence is “This is what the next chapter is about.” meaning supervisors. The next chapter was the chapter on supervisors, but not now when there is a chapter on gen_fsm in between.

2013-08-22
194TYPO

“The second if the various events we can feed it” => “The second is the various events we can feed it”

2013-08-22
5241TYPO

“[…] replacing it with an direct reference […]” -> “[…] replacing it with a direct reference […]”

2013-08-22
132ERROR

mix run EXPR syntax is deprecated, thus it will treat EXPR as a file to run, so
$ mix run ‘Issues.CLI.run([“-h”])’ won’t work,
should be:
$ mix run -e ‘Issues.CLI.run([“-h”])’

2013-08-22
139TYPO

“we call the Jsonex decode_response function.” should be “we call the Jsonex decode function.” decode_response function is defined by us, while Jsonex library function is decode.

2013-08-22
6048TYPO

“[…] using one or more when keywords, When doing pattern matching, Elixir first […]”

The comma before “When” should be a period.

2013-08-22
49TYPO

“5. http__elixir-lang.org/getting_started/2.html (section 2.8.2)”

Actual section on the site is 2.6.2.

2013-08-22
191TYPO

Second paragraph, “stimulii” -> “stimuli”

2013-08-22
196TYPO

First block of text:
“event occurs before this timne expires,”, timne -> time

2013-08-22
66TYPO

reduce([ head |tail ], value, fun) → reduce(tail, func.(head, value), fun)
should be
reduce([ head |tail ], value, fun) → reduce(tail, fun.(head, value), fun)
^

2013-08-22
124ERROR

Just a heads up. OptionParser.parse now (in 0.10.2) returns a tuple with three elements so the example in this page will be incorrect.

2013-08-22
69TYPO

“We can use a guard clause for this.”

The following example (lists/weather2.exs) does not have a guard clause (the “when” keyword).

2013-08-22
268TYPO

“with its (require) message field”, require -> required

2013-08-22
269TYPO

first sentence, “fie.d.” -> “field”

2013-08-22
278ERROR

The dialyzer stuff doesn’t seem to work or do anything. We first find the path to our elixir library, but then never use it, and then use the string “erts” which isn’t mentioned or explained, and then when run on our files, it complains that all functions are unknown. There must be some detail missing here.

2013-08-22
275TYPO

second to last paragraph is “We’re already seen the syntax”. Should be “We’ve already seen…”

2013-08-22
145TYPO

Code snippet missing code comments

2013-08-22
237TYPO

Paragraph 2, “manage to known” instead of “manage to know”

2013-08-22
238TYPO

2nd last paragraph, “Inspect,inspect(self)” instead of “Inspect.inspect(self)”

2013-08-22
19TYPO

Change from:
passing it the value 99 is an argument
to:
passing it the value 99 as an argument

2013-08-22
25TYPO

Should examples use ‘aeiou’ instead of ‘aieou’? No big deal.

But where the book example shows:

iex> Regex.scan %r/[aieou]/, “caterpillar”
[“a”, “e”, “i”, “a”]

I get:

iex> Regex.scan %r/[aieou]/, “caterpillar”
[[“a”], [“e”], [“i”], [“a”]]

Using Elixir 0.10.2-dev, Erlang R16B01 (erts-5.10.2), FreeBSD 9.1.

2013-08-22
17OK

“And these are not your father’s boring old processes or threads”
-> How about “your parent’s” or even “your mother’s”? :)

It’s a pop culture reference—http://en.wikipedia.org/wiki/Oldsmobile

2013-09-06
39SUGGEST

not sure if this is really an error, but:

"The types we’ve seen so far are common in other programming languages. Now we’re getting into types that are more exotic. Because of this, we’re going to go into more detail here.

Elixir containers hold values of any type (including other containers)."

The sentence about containers confused me, because the explanation what a container actually is is missing. Also, containers aren’t mentioned anywhere in the following paragraphs. Is there something missing here?

2013-09-06I should have said "Elixir _containers_ ...."
4836ERROR

When I tried the more verbose “function do … end” syntax, Elixir 0.10.1 tells me “function do … end is deprecated, please use fn … end instead”

2013-09-06
98TYPO

the doc for starts_with?() is in between the doc for the two versions of strip()

2013-09-06
109TYPO

“But so far we haven’t seen a single if statement,”

have seen if statements earlier in book

2013-09-06
117TYPO

Write a function ok! takes an arbitary parameter.

need to add “that”:

Write a function ok! that takes an arbitary parameter.

2013-09-06
123TYPO

We’ll tell it that -h and —help AND possible switches,

should be

We’ll tell it that -h and —help ARE possible switches,

2013-09-06
130ERROR

My installation (Mac OS) prompted as to whether I wanted to install ibrowse rather than just doing it as the book says.

2013-09-06
129SUGGEST

After running mix deps.get I got:

Unchecked dependencies for environment dev:

  • httpotion [git: “git://github.com/myfreeweb/httpotion.git”]
    the dependency does not match the requirement 0.1.0, got 0.2.0
    • (Mix) Can’t continue due to errors on dependencies

changing the version to 0.2.0 fixed this — I guess this is really an error on the expm page?

2013-09-06
178TYPO

next will look two different servers

should be?:

next will look AT two different servers

2013-09-06
131ERROR

creating a new project with mix, elixir v. 0.10.1, I don’t have the line

Code.require_file “test_helper.exs”, DIR

in my issues_test.exs

2013-09-06
36ERROR

In iex, this syntax from the text is accepted:

iex(2)> handle_open = fn
…(2)> {:ok, file} -> “Read data: #{IO.read(file, :line)}”
…(2)> {_, error} -> “Error: #{:file.format_error(error)}”
…(2)> end
#Function<6.80484245 in :erl_eval.expr/5>

but this syntax from the text is rejected:

iex(4)> handle_open = function do
…(4)> {:ok, file} -> “Read data: #{IO.read(file, :line)}”
…(4)> {_, error} -> “Error: #{:file.format_error(error)}”
…(4)> end
(SyntaxError) iex:5: unhandled operator ->
src/elixir_translator.erl:614: :elixir_translator.translate_arg/2
lists.erl:1339: :lists.mapfoldl/3
lists.erl:1340: :lists.mapfoldl/3
src/elixir_translator.erl:621: :elixir_translator.translate_args/2
src/elixir_literal.erl:24: :elixir_literal.translate/2
src/elixir_translator.erl:614: :elixir_translator.translate_arg/2
lists.erl:1339: :lists.mapfoldl/3

The example source downloaded from PragProg is similarly rejected:

$ cat handle_open.exs
handle_open = function do
{:ok, file} -> “First line: #{IO.read(file, :line)}”
{_, error} -> “Error: #{:file.format_error(error)}”
end
IO.puts handle_open.(File.open(“Rakefile”)) # call with a file that exists
IO.puts handle_open.(File.open(“nonexistent”)) # and then with one that doesn’t

$ elixir handle_open.exs
(CompileError) handle_open.exs:1: function function/1 undefined
src/elixir_translator.erl:47: :elixir_translator.translate_each/2
lists.erl:1339: :lists.mapfoldl/3
/usr/home/jimf/work/git/elixir/lib/elixir/lib/code.ex:291: Code.require_file/2
/usr/home/jimf/work/git/elixir/lib/elixir/lib/kernel/cli.ex:303: Kernel.CLI.process_command/2
/usr/home/jimf/work/git/elixir/lib/elixir/lib/enum.ex:618: Enum.“map/2-lc$^0/1-0”/2

Using Elixir 0.10.2-dev, Erlang R16B01 (erts-5.10.2), FreeBSD 9.1.

2013-09-06
225TYPO

tuples of code is is building…
is is -> it is

2013-09-06
6350ERROR

When I try the two functions that should result in the compilation error, I’m actually getting a different compilation error. Here’s my default_params.exs file

defmodule Example do
def func(p1, p2 // 2, p3 // 3, p4) do
IO.puts inspect [p1, p2, p3, p4]
end

def func(p1, p2) do
IO.puts inspect [p1, p2]
end
end

compiling that in iex gives

(CompileError) /Users/Ian/Documents/workspace/prag_prog/programming_elixir/default_params.exs:6: def func/2 conflicts with defaults from def func/4

This is Elixir 10.1.

2013-09-06
44TYPO

Book text:

iex> Times.double(“cat”)

(ArithmeticError) bad argument in arithmetic expression…

An exception (ArithmeticError) gets raised, and we see a stack backtrace. The
first line tells us what went wrong (we tried to perform arithmetic on a string,
and the next line tells us where. But look at what it writes for the name of
our function: Times.double/1.


The stack backtrace and function (“look at what it writes”) are not actually shown in the iex example in the book.

2013-09-06
51SUGGEST

The example solution to Exercise: ModulesAndFunctions-6 includes private functions. At this point in the book private functions haven’t been mentioned yet. I have posted a solution on the forum that doesn’t use private functions.

2013-09-06
60TYPO

(missing space after “cat”)
So the string ‘’cat’‘is the three codepoints 99, 96, and 116.
… should become …
So the string ‘’cat’‘ is the three codepoints 99, 96, and 116.

2013-09-06
97ERROR

The description of printable?(str) is different from elixir-lang.org/docs/master/String.html#printable?/1.

The example that returns false does contain printable characters, but it also contains non-printable characters.

The description should probably read “Returns true if str contains only printable characters.”

2013-09-06
97TYPO

Indentation for rstrip(str) is off compared to reverse(str) above and rstrip(str, character) below.

2013-09-06
48TYPO

Change comma:

keywords, When doing pattern matching

to period:

keywords. When doing pattern matching

2013-09-06
244TYPO

places that breaks are allows ->
places WHERE breaks are allowED

2013-09-06
245TYPO

The output of the improved function is missing. It just says

IO.inspect big_bitmap
IO.inspect big_bitmap, raw: true

but the output is not there.

2013-09-06
102OK

Page numbering goes from 101 to a chapter-beginning page to 104.

2013-09-06That's because we keep the same pages numbers that would be in the paper book, and new chapters in a paper book always start on recto pages. We remove the blank verso page in the PDF
109TYPO

“If the condition is truthy, the if expression evaluates the code associated with the do: key, otherwise it evaluates the else: code. If either key is absent, no action is taken.”

Technically, if either key is absent, action is still taken sometimes. (Example: not including `else` will still take the `do` action if the expression is truthy.)

2013-09-06
109ERROR

Book:
iex> if 1 == 1, do: “true part”, else: “false part”
true part

iex:
ex(1)>
if 1==1, do: “true part”, else: “false part”
“true part”

Note: “true part” is a double-quoted string and iex will print it out as such (yet the book doesn’t have the double-quotes).

2013-09-06
36SUGGEST

When I run the example with function do instead of fn .. end I get an error on the command line stating that function do … end is deprecated. Should probably discourage the functoin do … end method.

2013-09-06
72TYPO

“The Enum and Stream modules works …” should be “… work …”

2013-09-06
0SUGGEST

Will there be a chapter on using databases with Elixir in the final version of the book? Ideally I’d like to see examples of using mnesia, MySQL and SQLite.

2014-06-12I don't think so—I'd probably see this in another book.
225TYPO

Chapter 19.2: the last sentence in the penultimate paragraph starting with “The double quote says…” is missing a double quote at the end of the sentence.

2013-09-06
0TYPO

This is actually for the cheat sheet (for v0.10.0)

Block “Guard Clause”: “lengt(list)” is missing its “h”

2013-10-01
101TYPO

Otherwise the terminating delimiter is the next nonescaped occurrence of the opening delimited.

“delimiter” (the last word)
Also, consider using “non-escaped” or “unescaped”.

2013-09-29
17SUGGEST

The first paragraph of this page uses the acronym RHS without first explain what RHS stands for. Although the whole idea is understandable (because the ‘right hand side’ expression is used on the error message on the previous page), it would be good to make things clear for the reader.

“The first expression in this example succeeds because a is initially matched with the first 1 in the RHS. The value in a is then used in the second term to match the second 1 in the RHS.”

2013-09-29
124TYPO

`OptionParser.parse` returns a tuple with three elements — parsed options, its arguments and things it couldn’t parse. In your `parse_args` example the result of the `case` statement will always be `:help` as there’s no match.

2013-09-29
42ERROR

The 2nd exercise proposed on “Functions-5” doesn’t work on Elixir 0.10.2 even on the original form:

Enum.each [1,2,3,4], fn x -> IO.puts x end

Enum.each [1,2,3,4], fn x -> IO.puts x end

(FunctionClauseError) no function clause matching in IO.puts/2
/private/tmp/elixir-6TQo/elixir-0.10.2/lib/elixir/lib/io.ex:120: IO.puts(#PID<0.36.0>, 1)
/private/tmp/elixir-6TQo/elixir-0.10.2/lib/elixir/lib/enum.ex:351: Enum.“each/2-lists^foreach/1-0”/2
/private/tmp/elixir-6TQo/elixir-0.10.2/lib/elixir/lib/enum.ex:351: Enum.each/2
erl_eval.erl:569: :erl_eval.do_apply/6
src/elixir.erl:138: :elixir.eval_forms/3

2013-09-29Changed to use IO.inspect
167OK

You said: “Note that the name that’s returned is an atom—it’s in quotes because it contains an at-sign.”

That’s not exactly correct, I believe. I think it’s done for the safety reasons — you may have a period there in the name (as in “one@wibble.local”), which in Elixir notation would mean calling a function “local” on Erlang module with the name “one@wibble”. On its own, `:one@wibble` is a very valid atom definition. Try it in iex.

2013-09-30Well, it's displayed in quotes because it contains an @ sign... \n \nI think the statement is true. \n \n \n
44TYPO

Note #1 says “Elixir compiles a source file called name.ex into a binary file called Elixir-Name.beam. BEAM is both a binary file format and the name of the Erlang interpreter implementation that reads it.”. In my environment the actual name of the binary faile is “Elixir.Name.beam”, with a dot and not a dash.

2013-09-29
137ERROR

When adding HTTPoption to mix, the screen shot (and the text on expm.co/httpotion ) show version 0.1.0. The following code block shows “:httpotion, ”0.2.0". Current version is 0.2.2 though, so both of those result in an error:

Unchecked dependencies for environment dev:

  • httpotion [git: “git://github.com/myfreeweb/httpotion.git”]
    the dependency does not match the requirement 0.1.0, got 0.2.2
    • (Mix) Can’t continue due to errors on dependencies

Set code block to “:httpotion,”~> 0.2.0“,” and mention that expm.co/httpotion is out of date

2013-09-30
lotsTYPO

The book frequently references “Github”, but it should be “GitHub”

2013-09-29
251ERROR

do: IO.puts(a+b+c) no longer works. You need to change it to do: IO.puts(to_string(a + b + c)) for elixir 10.0.2.

2013-09-30
255TYPO

string = %{now is the time} should be string = %s{now is the time}?

2013-09-30
124ERROR

case parse do
{ [ help: true ], _ } -> :help
{ _, [ user, project, count ]} -> { user, project, binary_to_integer(count) }
{ _, [ user, project ]} -> { user, project, @default_count }
_ -> :help
end

Tests fails with:

(ExUnit.ExpectationError)
expected: :help
to be equal to (==): {“user”, “project”, 4}

If add extra "" to pattern {, [ user, project, count ], _ } , tests passes.

2013-09-29
146ERROR

The example code here doesn’t have any documentation in it. From the surrounding text it looks like there should be some @doc comments with doctests inside the comments.

2013-09-30
50OK

Chapter 6
Item: 6.4

mm/default_params.exs

Generate error:
Compilation error on file mm/default_params.exs

(CompileError) mm/default_params.exs:5: def func/2 conflicts with defaults from def func/4
src/elixir_def.erl:355: :elixir_def.“check_previous_defaults/7-lc$^0/1-0”/7
src/elixir_def.erl:135: :elixir_def.store_definition/9
src/elixir_compiler.erl:65: :elixir_compiler.“eval_forms/4-fun-0”/7
src/elixir_compiler.erl:64: :elixir_compiler.eval_forms/4
src/elixir_module.erl:143: :elixir_module.eval_form/5
src/elixir_module.erl:68: :elixir_module.compile/5
src/elixir_compiler.erl:65: :elixir_compiler.“eval_forms/4-fun-0”/7

Possible solution:
Invert functions definition order. But, it make default value on p2 pointless.

defmodule Example do
def func(p1, p2) do
IO.puts inspect [p1, p2]
end
def func(p1, p2 // 2, p3 // 3, p4) do
IO.puts inspect [p1, p2, p3, p4]
end
end

Example.func(“a”, “b”) # => [“a”, “b”]
Example.func(“a”, “b”, “c”) # => [“a”, “b”, 3, “c”]
Example.func(“a”, “b”, “c”, “d”) # => [“a”, “b”, “c”, “d”]

2013-09-29I left the second definition in the source by mistake.
168ERROR

for the function that prints Node.self, I needed to use inspect:
`func = fn -> IO.puts inspect Node.self end`

2013-09-30
199ERROR

In the example code on line 26, there is a call to CallData.new, but no record type of CallData was ever defined.

2013-09-30
23OK

Add “Ranges” in the list that shows the Elixir’s value types.

2013-09-29I debated this but it's really a derived type.
212TYPO

HTTPotion is misspelled HTTPoption twice in the second to last paragraph

2013-09-30
129TYPO

“HTTPoption” should be spelt “HTTPotion”.. your’s says ‘option’ instead of ‘potion’

Context:
Go back to the expm page that shows HTTPoption. About half way down, you’ll find a section headed “mix.exs”.

2013-09-29
124ERROR

In the isses/cli.ex listing, the tuples are each missing a third item. So, for example, they should read:

{ [ help: true ], , } -> :help
{ , [ user, project, count ] } -> {user, project, count}
#etc…

This is with Elixir v0.10.2.

2013-09-29
57ERROR

iex(3)> :“Elixir.IO”.puts 123

(FunctionClauseError) no function clause matching in IO.puts/2
/private/tmp/default-awJ0/elixir-0.10.2/lib/elixir/lib/io.ex:120: IO.puts(#PID<0.36.0>, 123)
erl_eval.erl:569: :erl_eval.do_apply/6
src/elixir.erl:138: :elixir.eval_forms/3

I get that error when i call this code snippet, the error maybe could be in 123 that is an integer instead of a string.

2013-09-30
7OK

Compile and run paragraph, you got:
“Once you tire of writing …”
must be
“Once you are tired of …”

2013-09-29It's OK as it stands, I believe.
74ERROR

In section 7.9 List Libraries in Action, the List.concat example produce an error because is deprecated, please use Enum.concat.

2013-09-29
52TYPO

I think that you missed the year in the function `sales_tax`:

filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers)))

Maybe the right answer is this:

filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers), 2013))

2013-09-29
63SUGGEST

On first read of the mm/default_params.exs listing, I was confused by the second definition of func. Only after reading the following paragraph did I realize that it was an example of something that would cause a compiler error.

Running `elixir default_params.exs` causes the CompilerError instead of printing output to demonstrate the default parameter version of func

Given that you repeat the compilation error example again, maybe you could remove the second func definition from the first example.

2013-11-04
9482ERROR

hands = deck |> shuffle |> chunk(13)

I don’t see a chunk method in the Elixir 10.3 documentation. And running the code gives me:

(UndefinedFunctionError) undefined function: IEx.Helpers.chunk/2

There are some chunk methods in Erlang, but they don’t seem to do what this code is doing.

2013-11-04Typo—it should be `chunks`
2TYPO

There is a warning across many even-numbered pages: “This book contains code that’s too wide. Look in the build log for details and fix.”

2013-11-04
107TYPO

“Was a list an appropriate structure to how each row of data?” “How” should be “hold”.

2013-11-04
124TYPO

The long code line that produces the warnings on even-numbered pages is on page 124.

2013-11-04
200SUGGEST

Newer versions of “mix new” (I’m running 0.10.4-dev) generate a lib/supervisor.ex skeleton. Might want to mention that.

2013-11-04
201TYPO

First bullet item, first sub-bullet is missing an apostrophe: “…the current module’s name.”

2013-11-04
201SUGGEST

Newer versions of “mix new” (I’m running 0.10.4-dev) generate a mix.exs file that contains a value in the :application function that auto-starts the supervisor when you run “iex -S mix”. This surprised me when I followed along.

2013-11-06
201SUGGEST

When trying my supervisor, I was bit by something that isn’t explicitly noted in the book: both the supervisor and server :start_link methods must return the {:ok, pid} result of the OTP :start_link methods they call. I’d added an IO.puts after the call to :gen_server.start_link in my server. That works just fine when you’re running the server by itself, but when I added the supervisor and called its :start_link function I kept getting :failed_to_start_child error messages.

2013-11-06
23ERROR

An inconsistency:
Ranges are not listed under built-in value types, yet there is a “Ranges” section under “4.1 Value types” on PDF p26.

2013-11-06
64OK

Chapter 7.4

Last example:
iex> MyList.map [1,2,3,4], &(&1 + 1)
needs to be
iex> MyList.map [1,2,3,4], (&1 + 1)

and:
MyList.map [1,2,3,4], &(&1 > 2)
needs to be:
MyList.map [1,2,3,4], (&1 > 2)

2013-11-04I believe it is correct. Are you running the most recent Elixir?
67OK

Same error as before in 7.4
Anonymous functions not declared correctly when you use Elixir 0.10.0
&(&1 + &2) needs to be (&1 + &2)

2013-11-04I believe it is correct as is.
173TYPO

receiver to the sever as an argument

should be:

receiver to the server as an argument

2013-11-04
50TYPO

The second implementation of func (func/2) should be removed from the first code listing on the page

2013-11-04
10998TYPO

In the description of rjust there’s an extra s in Returns.

2013-11-04
168OK

Using short names for notes doesn’t appear to work on OS X Mavericks.

== With snames

Window #1
→ iex —sname node_one
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.10.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(node_one@TheDoctor)1> Node.self
:“node_one@TheDoctor”

Window #2
→ iex —sname node_two
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.10.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(node_two@TheDoctor)1> Node.list
[]
iex(node_two@TheDoctor)3> Node.connect :“node_one@TheDoctor”
false

== Now with names
Window #1
→ iex —name node_one
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.10.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(node_one@TheDoctor.local)1> Node.self
:“node_one@TheDoctor.local”

Window #2

→ iex —name node_two
Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.10.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(node_two@TheDoctor.local)1> Node.self
:“node_two@TheDoctor.local”
iex(node_two@TheDoctor.local)2> Node.connect :“node_one@TheDoctor.local”
true
lex(node_two@TheDoctor.local)3> Node.list
[:“node_one@TheDoctor.local”]

iex(node_one@TheDoctor.local)2> Node.list
[:“node_two@TheDoctor.local”]

2013-11-06I can't reproduce this issue on my Mavericks box.
272TYPO

First sentence: “…where type IS any of the basic…”

2013-11-06
83TYPO

Heading: “A Stream is Composable Enumerator”
should be “A Stream is a Composable Enumerator
” ?

2013-11-12
124TYPO

This version of the code (project/0/issues/lib/issues/cli.ex) has already fixed the bug that is supposed to be fixed in the next section (binary_to_integer).

2013-11-12
130TYPO

If you have a clean machine, running `mix deps.get` actually asks to install rebar as well:

$ mix deps.get

  • Getting httpotion (git://github.com/myfreeweb/httpotion.git)
    Cloning into ‘deps/httpotion’…
    remote: Counting objects: 256, done.
    remote: Compressing objects: 100% (131/131), done.
    remote: Total 256 (delta 119), reused 228 (delta 95)
    Receiving objects: 100% (256/256), 33.41 KiB | 0 bytes/s, done.
    Resolving deltas: 100% (119/119), done.
    Checking connectivity… done
  • Getting ibrowse (git://github.com/cmullaparthi/ibrowse.git)
    Cloning into ‘/Users/david/Projects/playground/elixir/issues/deps/ibrowse’…
    remote: Counting objects: 869, done.
    remote: Compressing objects: 100% (445/445), done.
    remote: Total 869 (delta 532), reused 685 (delta 367)
    Receiving objects: 100% (869/869), 323.81 KiB | 262.00 KiB/s, done.
    Resolving deltas: 100% (532/532), done.
    Checking connectivity… done
  • Compiling ibrowse
    Could not find rebar, which is needed to build ibrowse
    I can install a local copy which is just used by mix
    Shall I install this local copy? [Yn]
  • creating /Users/david/.mix/rebar
    ==> ibrowse (compile)
    Compiled src/ibrowse_app.erl
    Compiled src/ibrowse.erl
    Compiled src/ibrowse_http_client.erl
    Compiled src/ibrowse_lb.erl
    Compiled src/ibrowse_sup.erl
    Compiled src/ibrowse_socks5.erl
    Compiled src/ibrowse_lib.erl
  • Compiling httpotion
    Compiled lib/httpotion.ex
    Generated httpotion.app
2013-11-13
130OK

I think it would make sense with some kind of explanation of the fact that the newly installed files (dependencies) are ignored by git. Is this the way it’s always done?

$ git status

  1. On branch master
  2. Changes not staged for commit:
  3. modified: mix.exs
    #
  4. Untracked files:
  5. mix.lock
    no changes added to commit
2013-11-13If I did that, I'd also have to talk about all the other files that get added throughout the book. \n \nThis behaviour is the way git has always worked, You have to `git add` new files. \n
116TYPO

Exercise: ControlFlow 2 - third paragraph
“lnaguages” should be “languages”

2013-11-12
187TYPO

list the follows this one -> list THAT follows this one

2013-11-12
124TYPO

{ , [ user, project, count ], } -> { user, project, binary_to_integer(count) }
…should be…
{ , [ user, project, count ], } -> { user, project, count }
…to get test failure message in later text

2013-11-12
197TYPO

OK, my initial erratum for this was wrong. line 20 should be:

call_info.update_suspicious_segments(&(&1+1)),@timeout}

instead of
call_info.update_suspicious_segments(&1+1),@timeout}

2013-11-12
263OK

The footnote at the bottom of 263 has bled over to the top of 264.

2013-12-12We don't worry about layout in beta books. It gets fixed when the book enters production
139TYPO

penultimate line: rach -> each

2013-12-12
140TYPO

Half way down page:
Given a list or rows -> Given a list of rows

2013-12-12
15TYPO

About half way down the page: “Lets try a pattern containing some values and some variable.” should be “Let’s”

2013-12-12
3SUGGEST

in sidebar Source file naming, the last sentence says “The PMap example used .exs …”, but we don’t know which name it has used ——> the green bar with the path name is missing (a search for Parallel has found this example in code/spawn/pmap.exs)

2013-12-12
6SUGGEST

h IO ——> please check the output, it has changed

2013-12-12
23SUGGEST

second paragraph Elixir’s built-in types are: ——> this is a trivia, but now that you have added Ranges in the bullet Value types, why not adapt the bullet Collection types (currently Lists - Tuples - Binaries) to the content of paragraph 4.3 which is Tuples, Lists, Keyword lists, Binaries ? [Other detail : 4.1 Integer is now shown as Arbitrary-sized integers in the bullet Value types].

2014-02-07
28OK

section Keyword Lists, paragraph 3 Elixir converts it into a list of 2-value tuples ——> it seems that it is no longer the case :

Interactive Elixir (0.11.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [ name: “Dave”, city: “Dallas”, likes: “Programming” ]
[name: “Dave”, city: “Dallas”, likes: “Programming”]

unless the output of iex does not reflect the internal representation.

I have noticed the contrary, explicit tuples converted to shortcut :

iex(4)> tax_rates = [ {:NC, 0.075}, {:TX, 0.08} ]
[NC: 0.075, TX: 0.08]
iex(5)> h_tax = HashDict.new(tax_rates)
#HashDict<[NC: 0.075, TX: 0.08]>
iex(6)> IO.puts “ht=#{inspect(h_tax)}”
ht=#HashDict<[NC: 0.075, TX: 0.08]>

2013-12-12Try using \n \ninspect kwlist, raw: true
29OK

in 4.4 Names, Source Files, Conventions, Operators, and So On ——> after the 5th paragraph (Comments start with a hash (#) and run to the end of the line.), it would be worth mentioning that a block comment à la Ruby (=begin/=end) can be achieved using the %S() sigil.

Example : I don’t want to delete debugging code when no longer necessary, so I comment it out :

%S(
IO.puts inspect(Enum.map(values, fn(x) -> {x, String.length x} end))
z = Enum.zip(headers, values)
IO.puts “#{inspect(z)}”
z
)
Enum.zip(headers, values)
end

2013-12-12Except it is dangerous—for example, try using %S to comment out the last lines of a function :)
40SUGGEST

section The & Notation, first paragraph : ………… provides
a short cut. ——> shortcut, without space ?

2013-12-12
44SUGGEST

Second paragraph : What happens if we make our function fail by passing it string ——> passing it a string ?

Third paragraph ——> not the same output :
iex(5)> Times.double(“cat”)

(ArithmeticError) bad argument in arithmetic expression
times.exs:3: Times.double/1

2013-12-12
58TYPO

last line : Execute an command ——> a command ?

2013-12-12
69ERROR

middle of the page, execution of example “weather.exs” : ——> there are only three locations for 27 :

iex(23)> for_location_27(test_data)
[[1366225622, 27, 15, 0.45], [1366229222, 27, 17, 0.468],
[1366232822, 27, 21, 0.05]]

instead of

[[1366225622,27,15,4.50000000000000011102e-01],[1366229222,27,17,
4.68000000000000027089e-01],[1366232822,27,21,5.00000000000000027756e-02]]
[[1366225622,27,15,0.45],[1366229222,27,17,0.468],[1366232822,27,21,0.05]]

2013-12-12
70TYPO

fourth paragraph from end of page, starting “In the new version, we use placeholders”, line 4 : to loc ——> to target_loc

2013-12-12
72TYPO

second paragraph, line 1 : For example, the code that follows uses a lc to list of pairs ——> list pairs (of numbers) ?

line 2 : … multiple of 10. it uses —> It uses (Capital letter at the start of a new sentence)

2013-12-12
90ERROR

paragraph before section 9.2 : One of the interesting things about sigils is that you can define your own. We
talk about this in Part 3 on page 89. ——> invalid link, points to the previous page, not in Part 3 (there is a section 22.1 Writing Your Own Sigils on page 259)

2013-12-12
114OK

I found it difficult to understand what’s going on in defmodule Users of control/case1.exs. I suppose that case makes a pattern match between the case expression and the LHS of “when” expressions, and when there is a match it binds the whole Person to RHS record. To make it more explicit I did the following :

defrecord Person … (same)
defmodule Users do
persons = [
Person.new(name: “Dave”, state: “TX”, likes: “programming”),
Person.new(name: “Tom ”, state: “IL”, likes: “fishing”),
Person.new(name: “Jim ”, state: “TX”, likes: “cooking”),
Person.new(name: “José”, state: “CA”, likes: “designing”)
]

filter_TX = fn(person) ->
case person do

Person[state: “TX”] = record ->
IO.puts Person.as_string record

_ ->
IO.puts “#{person.name} not in Texas”

end
end

Enum.map(persons, filter_TX)
end

Output :

iex(122)> c “mycase1.exs”
mycase1.exs:1: redefining module Person
Dave lives in TX and likes programming
Tom not in Texas
Jim lives in TX and likes cooking
José not in Texas

I still don’t understand “The full power of nested pattern matches can be used:” (bottom of page 113)

2013-12-12
122TYPO

middle of the page, .gitignore
Lists the files and directories generated as by products ——> by-products (checked with my old Harrap’s English-French dictionary as well as with the Oxford dictionary that comes with the Mac)

and

lib/
… third line …
In it, it has placed a skeleton supervisor, which we won’t we using ——> be using ?

2013-12-12
126TYPO

Line 6 (or third line of first paragraph after the test) :
than converting it to an integer. That’s easily fixed. The built in function ——> built-in

2013-12-12
126OK

Again … new file not detected

In order to keep the book code intact, I’m working in my own project directory. After deleting cli.ex and dragging it from code/project/1/issues/lib/issues/cli.ex, ——> the test fails instead of pass.

$ rm -R ebin/
$ mix test … ==> OK

2013-12-12Mix uses timestamps to determine what needs rebuilding. I suspect dragging an existing file retains its timestamp.
127SUGGEST

Second paragraph above 12.6 Task: Use External Libraries :

issues % mix run -e ‘Issues.CLI.run([“elixir-lang”, “elixir”])’

This is the place where to find the command to run the application. Each time I’m looking for it, I can’t find it because it is written in the same case as the error message, without line space after, and I have to search back and forth, then from the start of the chapter.

——> Please write it in the same colored bold face as

$ mix run -e ‘Issues.CLI.run([“-h”])’

above.

2013-12-12
134SUGGEST

middle of the page : So now our CLI module contains: ——> we have surreptitiously switched from project/2 to project/3, so you could add a green bar with the path name :

project/3/issues/lib/issues/cli.ex

and, to be coherent with the source code, show the definition as :

def process({user, project, _count}) do

with an underscored _count. count will only be used on the next page when we add |> Enum.take(count)

2013-12-12
135TYPO

section 12.8 Transformation: Take First N Items, first paragraph, line 2 : Rather that write a function ——> I’m not anglophone, but I would say : Rather than

2013-12-12
135SUGGEST

12.8 Transformation: Take First N Items, executing the application :

$ iex -S mix
…..

(CompileError) lib/issues/cli.ex:53: function count/0 undefined

because I had not seen that _count had been (surreptitiously) changed into count.

——> you could add an arrow to show the changed line before

def process({user, project, count}) do

because count is now needed by Enum.take(count).

2013-12-12
138SUGGEST

The whole section 12.9 Transformation: Format the Table uses project/4, but the last green bar of the section (just before 12.10) uses project/5/issues/lib/issues/cli.ex.
1) ——> project/4 is OK, because cli.ex already contains import Issues.TableFormatter
2) ——> A reminder of the command to execute the project would be good, because the entry point is no longer run as on page 127, but main :

$ mix run -e ‘Issues.CLI.main([“elixir-lang”, “elixir”])’

2013-12-12
66TYPO

In section Generalizing Our Sum Function, second paragraph, line 3 ——> missing closing parenthesis after helpers

2013-12-12
89TYPO

First line of section Sigils :
Like Ruby, Elixir has an alternative syntax for some literals. We’re already ——> what does We’re mean ? Isn’t it We have ?

2013-12-12
233ERROR

In the latest Elixir builds the syntax used in the case statement:

_ in [false, nil] -> unquote(else_clause)

no longer works, instead it should be:

x when x in [false, nil] -> unquote(else_clause)

2013-12-12Sigh. And I really liked the old syntax.
141TYPO

About in the middle of the page, the @doc above def separator(column_widths) do :

@doc “”"
Generate the line that goes below the column headings. It is a string of
hyphens, with + signs where the verticak bar ——> vertical

2013-12-12
156SUGGEST

second to last paragraph, first line :
Our receive block contains a new feature. We’ve already see ——> seen ?

2013-12-12
157SUGGEST

second paragraph, first line :
The run function starts the whole thing off. It uses a built in ——> built-in ?

2013-12-12
161SUGGEST

fourth paragrap : It depends on the semantics of your processes. If the intent is that a cat
pmap.failure ——> what does “cat pmap.failure” mean ?

2013-12-12
161SUGGEST

second line after Your turn… :
given time. You might want to use it to force some scenarios in the following :

——> after a colon I expect a description/enumeration of that “following”. The following paragraph :

“The key with these exercises is to get used to the different reports that you’ll see when you’re developing code.”

disturbs me. I first thought that something was missing after the colon. If the “following” are the three exercises, I would place this sentence either after the three exercises, or between parentheses with a lower case t and without line space.

2013-12-12
99TYPO

“Use list notation to specify more that one attribute for a field:”, it should say “than one”.

2013-12-12
125OK

The assertion doesn’t fail. Copy & pasted the exact code in the book.

2013-12-12Try copying from 0/issues, not 1/issues
125TYPO

In the assertion failure message you see:
expected: {“user”,“OrganizingAProject”,“99”}
but in the actual code the assertion is:
{ “user”, “project”, 99 }

2013-12-12
215TYPO

Near the bottom of the page, we see:

OPT assumes this module

when I believe it should be:

OTP assumes this module

2013-12-12
89TYPO

The end of the last non-code paragraph reads:

(We’ve already see the %r options.)

I believe that “see” should be “seen”

2013-12-12
96ERROR

Stream.repeatedly(function(:random.uniform/0))

should be

Stream.repeatedly(&:random.uniform/0) |> Enum.take(3)

2013-12-12
181SUGGEST

In the last section “Create the basic sequence server”, first paragraph :
Now ………. Add the sequence/
directory under lib.

——> why add a sequence directory ? It is already done :

$ mix new sequence
………

  • creating lib/sequence
2013-12-12
186OK

Link at the bottom of the page : the page displayed by this link is significantly different from the one displayed by h_p://www.erlang.org/doc/man/sys.html (starting at h_p://www.erlang.org —> DOCUMENTATION —> Erlang/OTP documentation —> Modules (in the left sidebar) —> sys).

——> Erlang’s doc seems a bit messy, especially if I download “R16B02 HTML Documentation File” from the download page. How did you get there ?

2013-12-12googling 'erlang sys'
187SUGGEST

In “15.3 GenServer Callbacks”,
in “init(start_arguments)”, second paragraph, line 3 :

is received in a span of _timeout_mS

——> According to h__p://en.wikipedia.org/wiki/Millisecond : Its symbol is ms.

2013-12-12
189TYPO

In “15.5 Tidying Up The Interface”, line 6 :

chapters when we look at supervisors, the name start_link a convention. ——> start_link IS a convention ?

2013-12-12
198TYPO

Second half of the page, paragraph before section “Playing With Our FSM in idx” :

The key this here is the second element of the tuple ——> The key here ? (this sounds superfluous)

2013-12-12
206TYPO

Second paragraph under the diagram, line 6 :

design for the top-level supervisor. Rather that give …

——> same as #53208 on page 135 : Rather than ?

2013-12-12
209SUGGEST

Third line from bottom of the page :

iex(1)> Sequence.Supervisor.start_link 123

——> this command is not necessary since Sequence#start (in file otp-supervisor/1/sequence/lib/sequence.ex) has been fixed on page 204.

More than that, the given number is ignored :

$ iex -S mix
Erlang R16B02 (erts-5.10.3) [source-b44b726] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.11.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Sequence.Supervisor.start_link 888
{:ok, #PID<0.61.0>}
iex(2)> Sequence.Server.next_number
123

2013-12-12
220ERROR

Fourth paragraph from the bottom of the page :

iex> c(“updated_sequence.ex”)

results in

Compilation error on file updated_sequence.ex

(MatchError) no match of right hand side value: {:error, :enoent}
…..

——> the file should be updated_server.ex instead of updated_sequence.ex :

iex(8)> c “updated_server.ex”
updated_server.ex:1: redefining module Sequence.Server
[Sequence.Server]

2013-12-12
114OK

One more word on “case”. I discover on page 226 :

case condition do
_ in [false, nil] -> …..

Very interesting. I have searched all occurrences of “case” in the book to check that I didn’t miss something, and read h__p://elixir-lang.org/getting_started/2.html. I find the Elixir online doc rather laconic. I like to read a comprehensive book on a subject (without the Pickaxe, I wouldn’t have been able to program in Ruby ;-) ).

——> I would appreciate a few more examples of case use/utilization. While playing with the exercises, I often started with a case, and replaced it soon with an if/then/else, because case seemed to be almost as powerless as the C switch.

Well, the trick is perhaps to use underscores :

iex(31)> list = [1,2,3,4,5]
[1, 2, 3, 4, 5]
iex(32)> last = List.last(list)
5
iex(33)> case list do
…(33)> _ when length(list) 4 -> "444444" ...(33)> _ when last 5 -> “ends with 5”
…(33)> _ -> “other”
…(33)> end
“ends with 5”

2013-12-12You probably want to look at `cond`
227SUGGEST

Line 7 counted from end of page :

My.macro 1.0 #=> 1.00000000000000000000e+00

is now (Elixir 0.11.1 and 2) displayed as 1.0

2013-12-12
229SUGGEST

In The quote function, some outputs have changed :

iex(1)> quote do: 1.0
1.0

and :

iex(10)> quote do: (a = 1; a + a)
{:block, [],
[{:=, [], [{:a, [], Elixir}, 1]},
{:+, [context: Elixir, import: Kernel],
[{:a, [], Elixir}, {:a, [], Elixir}]}]}
iex(11)> quote do: [ do: 1 + 2, else: 3 + 4]
[do: {:+, [context: Elixir, import: Kernel], [1, 2]},
else: {:+, [context: Elixir, import: Kernel], [3, 4]}]

2013-12-12
226TYPO

“The second form, using single quotes, represents strings as a list of integer codepoints. So the string ”cat’" is the three codepoints 99, 96, and 116.

This is a headache for iex. When it sees a list like ‘[99,96,116]‘ it doesn’t know if it is supposed to be the string “cat” or a list of three numbers.”

96 should be 97, as it is in the code section immediately following these paragraphs.

2013-12-12
236SUGGEST

Last line : for Kernel.quote for a full description. ——> isn’t rather Kernel.SpecialForms.quote ?

2013-12-12
238SUGGEST

Bottom of page, just before "19.9 Digging Deeper ——> new operators :

"iex(18)> Macro.unary_ops
[:!, :@, :^, :not, :+, :-, :~, :&]

2013-12-12
239SUGGEST

in “19.10 Digging Ridiculously Deep”, second paragraph ——> changed output :

iex(19)> quote do: 1 + 2
{:+, [context: Elixir, import: Kernel], [1, 2]}

2013-12-12
239TYPO

Second to last line :

implementation of this is in the file /lib/ex_unit/lib/assertions.ex.

——> found in :

elixir / lib / ex_unit / lib / ex_unit / assertions.ex

2013-12-12
139TYPO

We’re instructed to run our freshly minted command line executable with these arguments:

./issues elixir-lang dynamo 3

However there is not (any longer?) a dynamo repository for user elixir-lang, the dynamo repository is hosted by the dynamo user.

2013-12-12
228OK

First paragraph after the code example :

This shows us that atoms, numbers, lists (including keyword lists), binaries,
and tuples with two elements are represented internally as themselves. All
other Elixir code is represented by a three element tuple.

——> I would move (page 227)

My.macro do: 1 #=> [do: 1]

outside “# These values represent themselves” and say that a code block is represented by a keyword and a tuple :

defmodule My do
defmacro macro(param) do
IO.puts “param is a keyword list ? #{Keyword.keyword?(param)}”
IO.inspect param
end
end

defmodule Test do
require My
My.macro do: 1 #=> [do: 1]
My.macro do: 2 + 3 * 4
My.macro 2 + 3 * 4
end

$ elixir dumper2.exs
param is a keyword list ? true
[do: 1]
param is a keyword list ? true
[do: {:+, [line: 11], [2, {:*, [line: 11], [3, 4]}]}]
param is a keyword list ? false
{:+, [line: 12], [2, {:*, [line: 12], [3, 4]}]}

——> If I pass a do-block to a macro (exercise on page 240) :

assert (explain do: 2 + 3 * 4) == “multiply 3 and 4, then add 2”

it is received as a keyword list :

defmacro explain(p_expr) do
IO.puts “in defmacro explain #{inspect p_expr}”

outputs :

in defmacro explain [do: {:+, [line: 54], [2, {:*, [line: 54], [3, 4]}]}]

2013-12-12do: 1 is do: 1—it is represented as itself.
211ERROR

$ iex -S mix
Compiled lib/sequence.ex
Compiled lib/sequence/server.ex
Compiled lib/sequence/stash.ex
Compiled lib/sequence/subsupervisor.ex Compiled lib/sequence/supervisor.ex Generated sequence.app
iex(1)> Sequence.Supervisor.start_link 123 {:ok,#PID<0.71.0>} <== Not needed
iex> Sequence.Server.next_number

I believe “iex(1)> Sequence.Supervisor.start_link 123 {:ok,#PID<0.71.0>}” is superflous, since it is already called in the Sequence.Application.

2014-01-15
66TYPO

In section Generalizing Our Sum Function, second paragraph, line 3 : now it reads

helpersiex. And we also need …

——> still missing closing parenthesis after helpers, instead of iex

2014-01-15
188184OK

Hello Dave, I think the following seems wrong (using Elixir 0.11.2):

Even though we’ve recompiled the code, the old version is still running. The VM doesn’t hotswap code until you explicitly access it by module name. So, to try our new functionality, we’ll simply create a new server. When it starts, it will pick up the latest version of the code.

With the simple server from the Stack exercise:
```
defmodule Stack.Server do
use GenServer.Behaviour

def init(initial_state) do
{:ok, initial_state}
end

def handle_call(:pop, _from, [head|tail] = state) do
{:reply, head, tail}
end

def handle_call(:pop, _from, [] = state) do
{:reply, nil, state}
end
end
```

If I comment/uncomment the `handle_call(:pop, _from, [] = state)` clause, and
recompile code with `r Stack.Sever`, the code seems to be hot swapped
immediately on the running process (I can tell since it changes it’s crashing
behaviour when popping from an empty list).

You can contact me back at stefano.pigozzi@gmail.com

Kind regards
Stefano

2014-01-15That's because you explicitly mention the module
36OK

The handle_open.exs does not run as expected because even if you download the example code, there is no ‘Rakefile’ in the same directory as the program.

In fact, when I saw the message

iex(1)> c “handle_open.exs”
Error: no such file or directory
Error: no such file or directory

That output led me down the mistaken path of thinking the compilation had failed and I was getting a weird message out of Elixir, but it was simple giving me the correct output.

2013-12-30You'll simple need to supply a file name on your system.
243SUGGEST

Last paragraph : Once I display the page h__ps://github.com/elixir-lang/elixir, I have to click successively on :

lib
ex_unit
lib
ex_unit
assertions.ex

to reach assertions.ex.

——> The second to last sentence should read

implementation of this is in the file lib/ex_unit/lib/ex_unit/assertions.ex. (instead of
implementation of this is in the file elixir/lib/ex_unit/lib/assertions.ex.)

That is one more ex_unit.

2014-01-15
248TYPO

Top of page, first line of first exercise :

A basic Caesar cypher consists of shifting the letters is a message ——> IN a message ?

2014-01-15
251SUGGEST

Second section “Built-in Protocols: Inspect”, first paragraph, line 2 :

can return a representation that is a value Elixir literal ——> valid instead of value ?

2014-01-15
250SUGGEST

Before last paragraph :

IO.puts Enum.join fifty, “:”
This returns 0:1:1:0:0:1:0.

Compiling here gives an error :

c “bitmap.exs”
….
1
0
bitmap.exs:15: redefining module Enumerable.Bitmap
Compilation error on file …./Programming Elixir/code/protocols/bitmap.exs

(ArgumentError) argument error
/private/tmp/elixir-gDYd/elixir-0.12.0/lib/elixir/lib/enum.ex:860: Enum.“join/2-fun-0”/3
/private/tmp/elixir-gDYd/elixir-0.12.0/lib/elixir/lib/enum.ex:1131: Enum.“reduce/3-fun-0”/3
bitmap.exs:25: Enumerable.Bitmap._reduce/3
/private/tmp/elixir-gDYd/elixir-0.12.0/lib/elixir/lib/enum.ex:1130: Enum.reduce/3
bitmap.exs:37: (file)

Line 25 is :

_reduce(bitmap, { bit - 1, fun.(bitmap[bit], acc) }, fun)

——> If I replace it by :

{_code, actual_acc} = acc
_reduce(bitmap, { bit - 1, fun.(bitmap[bit], actual_acc) }, fun)

it works.

2014-01-15
253OK

Near the third of the page :

and we get the output:

——> needs a small adjustment of the alignment :

#Bitmap[12345678901234567890=01010101101010100101010011000110011101011000111110000101011010010]
{Bitmap, 12345678901234567890}

2014-01-15Depends on the width of your terminal window.
257TYPO

Third paragraph : When we complied the module ——> When we compiled ?

2014-01-15
258SUGGEST

Second line, I have

< returns 6 - - - - instead of < returns :ok

2014-01-15
258SUGGEST

Near the bottom of the page :

This outputs:

——> line numbers have changed :

{:puts_sum_three,
[line: 15],
[{:a, [line: 15], nil}, {:b, [line: 15], nil}, {:c, [line: 15], nil}]}
{:add_list,
[line: 16],
[{:list, [line: 16], nil}]}

2014-01-15
260SUGGEST

2/3 of page, after “Looking good:”, executing tracer3.ex gives :

< returns 6 - - - - instead of < returns :ok

2014-01-15
93SUGGEST

In section Sigils, third paragraph :

The letter determines with sigil’s type ——> I would say
The letter determines the sigil’s type

2014-01-15
264SUGGEST

Second to last paragraph : The predefined sigil functions are sigil_B, sigil_b, …

——> I cannot find sigil_b in the Kernel documentation. A search for “sigil” in the page finds 40 matches for C, R, S, W, c, r, s, w.

The strange thing is that a Google search (on 2013/12/19) finds it in the same page, as if it exists in a hidden part of the page :

Elixir v0.12.0 Documentation
elixir-lang.org/docs/stable/ ‎Traduire cette page
Elixir v0.10.1 ….. self/0 Kernel; set_elem/3 Kernel; sigil_B/2 Kernel; sigil_C/2 Kernel;
sigil_R/2 Kernel; sigil_W/2 Kernel; sigil_b/2 Kernel; sigil_c/2 Kernel; sigil_r/2 …

2014-01-15
264SUGGEST

End of last line : As of Elixir 0.9.2, sigil options ——> maybe change the version number

2014-01-15
267SUGGEST

Last sentence :

…………… Let’s create out
two projects now:

——> isn’t it our two projects ?

2014-01-15
268SUGGEST

First line ——> I have the impression that the beginning of the sentence is missing.
+
+
+
Line 2 : simple project. If You ——> you
+
+
+
After line 11 : * creating lib/line_sigil.ex

there are also :

  • creating lib/line_sigil
  • creating lib/line_sigil/supervisor.ex
    +
    +
    +
    And in mix compile there is an additional line with supervisor.ex.
2014-01-15
269SUGGEST

Executing odds/eval/apps/evaluator/lib/evaluator.ex :

$ cd ……code/odds/eval/apps/evaluator
$ mix compile
lib/evaluator.ex:11: function evaluate_with_binding/2 is unused
Compilation error on file lib/evaluator.ex

(CompileError) lib/evaluator.ex:7: function evaluate_with_binding/0 undefined

——> To make it work, in “def eval” I had to replace the third parameter of Enum.reduce :

  1. function(evaluate_with_binding/2))
    &evaluate_with_binding/2)

$ mix compile
[“code> a = 1”, “value> 1”, “code> b=2”, “value> 2”, “code> a+b”, “value> 3”]
Compiled lib/evaluator.ex
Generated evaluator.app

2014-01-15
268SUGGEST

Second paragraph ——> to be complete, I would add a “cd eval” command before “$ cd apps” :

$ mix new —umbrella eval
$ cd eval/ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$ cd apps/

2014-01-15
271SUGGEST

If I execute the book’s code :

$ pwd
…/Programming Elixir/code/odds/eval
$ mix test
……
test/evaluator_test.exs:4: unused import LineSigil

(CompileError) apps/evaluator/test/evaluator_test.exs:7: function sigil_l/2 undefined

——> this is because odds/eval/apps/line_sigil/lib/line_sigil.ex contains

def l(lines, _opts) do - - - - instead of
def sigil_l(lines, _opts) do
+
+
+
If I strictly follow the book, I end up with an error :

$ mix test

=INFO REPORT 23-Dec-2013::08:43:17 ===
application: line_sigil
exited: {bad_return,
{{’Elixir.LineSigil’,start,[normal,[]]},
{’EXIT’,
{undef,
[{’Elixir.LineSigil’,start,[normal,[]],[]},
{application_master,start_it_old,4,
[{file,“application_master.erl”},
{line,269}]}]}}}}
type: temporary

(Mix) Could not start application line_sigil: {:bad_return, {{LineSigil, :start, [:normal, []]}, {:EXIT, {:undef, [{LineSigil, :start, [:normal, []], []}, {:application_master, :start_it_old, 4, [file: ‘application_master.erl’, line: 269]}]}}}}

——> This comes from the automatically generated file apps/line_sigil/mix.exs which contains :

# Configuration for the OTP application
def application do
[mod: { LineSigil, [] }]
end

which must be changed to

def application do
[ ]
end

2014-01-15
275SUGGEST

Middle of the page ——> minor output changes :

iex(2)> Boom.start 1
About to divide by zero
Uh, oh! Arithmetic error: bad argument in arithmetic expression
DONE!

(ArithmeticError) too late, we’re doomed
exception.ex:25: Boom.raise_error/1
exception.ex:5: Boom.start/1

iex(3)> Boom.start 3
About to try creating a directory with no permission
Disaster! could not make directory /not_allowed: permission denied
DONE!
:ok

2014-01-15
277SUGGEST

Executing the example :

iex(5)> c “defexception.ex”
Compilation error on file .../Programming Elixir/code/exceptions/defexception.ex

(SyntaxError) defexception.ex:4: syntax error before: do

——> correction :

can_retry: false do

instead of

can_retry: false
do
+
+
+
iex(5)> c “defexception.ex”
Compilation error on file .../Programming Elixir/code/exceptions/defexception.ex

(SyntaxError) defexception.ex:11: unexpected comma. Parentheses are required to solve ambiguity in nested calls. Syntax error before: ‘,’

——> correction :

def talk_to_kinect, do: (raise KinectProtocolError, message: “usb unplugged”, can_retry: true)

instead of

def talk_to_kinect, do: raise KinectProtocolError, message: “usb unplugged”, can_retry: true

iex(5)> c “defexception.ex”
[B, KinectProtocolError]

2014-01-15
282SUGGEST

First line of section “Handling Truthy Values” :

The type as_boolean(T) says that type actual value matched will be of type T

——> sounds strange, maybe “says that the actual value” ?

2014-01-15
284TYPO

Paragraph after Line 9 :

For functions with multiple heads (or those that have default values ——> missing closing parenthesis

2014-01-15
285SUGGEST

I encountered two problems :

1) $ mix compile
Compilation error on file lib/simple/simple.ex

(CompileError) lib/simple/simple.ex:1: cannot define module Simple because it is currently being defined

If I put the file simple.ex into the directory simple/lib/simple/, there is a module name conflict with simple/lib/simple.ex created by “mix new simple” and containing :

defmodule Simple do

def start(_type, _args) do

——> there are two solutions :

a) replace Simple by SimpleXyz in the file simple/lib/simple/simple.ex :

b) ignore the hierarchy created by “mix new simple” and replace lib/simple/simple.ex
+
+
+
2) $ dialyzer _build/shared/lib/issues/ebin

dialyzer: Unknown option: _build/shared/lib/issues/ebin

——> replaced issues by simple :

$ dialyzer _build/shared/lib/simple/ebin

——> see also page 286, two times, 1/4 and 3/4 of page
——> see also page 287, two times, top and 2/3 of page
——> see also page 288, two times, top and middle of page :

dialyzer _build/shared/lib/issues/ebin/Elixir.NoSpecs.beam - - - - instead of
dialyzer _build/shared/lib/simple/ebin/Elixir.NoSpecs.beam
+
+
+
——> in both cases 1) a) and b), the output is different in this and following pages :

$ dialyzer _build/shared/lib/simple/ebin
Checking whether the PLT /Users/bekrootv/.dialyzer_plt is up-to-date… yes
Proceeding with analysis…
simple.ex:5: Invalid type specification for function ‘Elixir.Simple’:count_atoms/1. The success typing is (_) -> ‘nil’
supervisor.ex:1: Callback info about the supervisor behaviour is not available
Unknown functions:
supervisor:start_link/2
done in 0m0.74s
done (warnings were emitted)

2014-01-15
285TYPO

2/3 of the page, paragraph starting with “Oops. This looks serious, but it’s not.”, last sentence :

You add always add more apps ——> You can ?

2014-01-15
288TYPO

Fourth paragraph starting with “Here it noticed that the length_plus_n function”, line 2 :

……………..This means that length_plus_one ——> should be length_plus_n
+
+
+
Last paragraph, line 2 :

and without. Often, adding a @spec will further contrain ——> constrain ?
+
+
+
line 3 :

a function. We saw this with our count_of_atoms ——> count_atoms

2014-01-15
87TYPO

In section Stream.resource, first paragraph, line 5 :

the close the file at the end. ——> then close the file ?

2014-01-15
40ERROR

When typing the following on iex:

iex> times = &Kernel.*/2
&Kernel.*/2

This is the result:
iex(23)> times = &Kernel.*/2
#Function<12.80484245 in :erl_eval.expr/5>

Which is different from the explanation on page 41, that it’s optimizing the call to Kernel.*/2. It might be doing the optimization under the covers, but the output isn’t the same. The sample on page 41, talking about &(&1 + &2) has the same issue.

Info about the Elixir/Erlang version I’m running:
Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
Interactive Elixir (0.12.0) - press Ctrl+C to exit (type h() ENTER for help)

Cheers

2014-01-15
40ERROR

I sent another erratum previously, I think I found why the message is different, before commit 1096cd00 on 22/11/2013, Kernel.*/2 and Kernel.+/2 where defined as named functions, but this commit changed them into macros. Trying to use the short hand & with other methods, like IO.puts/1, work as described in the book, i.e:

iex(6)> fun = &IO.puts/1
&IO.puts/1

Minor detail, but it’s worth mentioning.

Cheers

2014-01-15
133SUGGEST

In #53267: About import and dependencies (page 166 of B10.0.11.2) I asked how to import one’s own modules residing in another directory, and what is the search mechanism for import.

Previously, having

defp deps do
[ {:extensions, path: “../extensions”} ]
end

in mix.exs was sufficient, and updates in my extensions were automatically compiled. But after adding a new module with a function to format the microseconds given by :timer.tc, I had again an error saying the module cannot be found. Somewhere in a Google search I found to try mix deps.compile and it worked, but this is the first time (since I upgraded to 0.12) I had to do this.

I have found a good answer to my question by Chris Keele in groups.google.com/forum/?fromgroups#!topic/elixir-lang-talk/ECmKaRTrUNw

2014-01-15
267TYPO

There are two problems with the footnote starting “This means that you don’t have to worry about…”. First, in the last sentence of the footnote, the second word “You” should not be capitalized. Second, the footnote spills over onto the next page.

2014-01-15
131OK

$ mix run -e ‘Issues.CLI.run([“-h”])’
Expected: usage: issues [ count | 4 ]

But, got this error: `) was unexpected at this time.

2014-01-15Can't reproduce. Is the error from the shell or your code?
55TYPO

As far as I know, the import directive takes two arguments, the first one is the module and the second (optional) one is the only/except argument.

Although that directive has only two parameters, the book is mentioning a thir one in:

“The optional third parameter lets you control which functions or macros are imported.”

I think the correct would be:

“The optional second parameter lets you control which functions or macros are imported.”

2014-01-15
188SUGGEST

The Nodes-4 exercise can be slightly ambiguous in how it is defined. I read it as creating a ring, where a single tick goes around the ring, from client to client. However, in discussing with another reader, he interpreted as each client is just ticking the next one every 2 seconds (so there are many ticks all going at the “same” time). Further, what should the behavior be if there is only a single client? (not that critical of a detail, but you could define it :)

2014-01-15
60TYPO

In the call-out “How Lists Are Displayed by iex”, the quotes are wrong around the word cat. They are at least mis-matched in the PDF, and I would recommend getting rid of any double-quotes and simply displaying single-quotes, in spite of proper editing style.

2014-01-15
70TYPO

In the weather3.exs example, missing the changed-line marker.

2014-01-15
72TYPO

“the code that follows uses a lc to list of pairs of numbers” should perhaps use “an lc” and remove the extra “of” between list and pairs.

2014-01-15
134126TYPO

“It you store your project on GitHub” should be “If you
store your project on GitHub”

2014-01-15
217TYPO

“Although it looked like we were just using a library, mix automatically
loaded the HTTPoption application. When we then started it, HTTPoption”

Used HTTPoption instead of HTTPotion

2014-01-15
266TYPO

impenatrable -> impenetrable

2014-01-15
87TYPO

You wrote “an initial state of {f1,f1} becomes”, but did you mean “an initial state of {f1,f2} becomes”?

2014-01-15
16ERROR

When the book moves to elixir version 0.12.2 the <- notation is deprecated therefore the example on “chapter 1. Take the red pill pg 2” needs to use the new send function as follows..

defmodule Parallel do

def pmap(collection, fun) do
me = self

collection
|>
Enum.map(fn (elem) ->
spawn_link fn -> send(me, { self, fun.(elem) }) end
end)
|>
Enum.map(fn (pid) ->
receive do { ^pid, result } -> result end
end)
end
end

2014-01-15
78ERROR

Beginning of ‘Functions & Pattern Matching’ there is a ‘missing cross reference target’ error. [epub version)

2014-02-07
25OK

The first line in the Regular Expressions section mentions “Elixir has regular expression literals, written as %r{regexp} or %r{regexp}opts”. But the default syntax actually is %r/regexp/opts. It’s little confusing.

2014-02-06Actually there is no default—you can write with any delimiter. Using %r/ / is nor a good idea, because it isn't nestable, so / in the regexp itself have to be escaped. Using %r{ } doesn't require this.
207TYPO

Last paragraph first word is “Out” should read “Our”.

“Our top-level module defines a start function, and that function invokes our
supervisor. And, as we now know, that supervisor in turn starts the actual
application code.”

2014-02-07
200TYPO

The second of the various events we can feed it.
should be
The second is the various events we can feed it.

2014-02-07
200TYPO

“Here’s we’re calling the Erlang code directly,”
should be
“Here we’re calling the Erlang code directly,”

2014-02-07
206TYPO

As of 0.12.3 (and perhaps earlier) the generated `init` function uses “children” instead of “child_processes”.

2014-02-07
207TYPO

As of 0.12.3 (and perhaps earlier) the generated `sequence.ex` has `use Application.Behaviour` as its second line.

2014-02-07
37TYPO

In exercise Functions-3 there is one " too many in the result.

2014-02-07
41OK

Second line on that page you say IO.puts/2 but doesn’t that need to be IO.puts/1

2014-02-07The actual function is IO.puts/2, but the device parameter is optional.
50TYPO

In “Default Parameters”, in the current version of Elixir (0.12.4-dev), if you compile the code appears another warning:

“using // for default arguments is deprecated, please use \\\\ instead”

2014-02-07
65SUGGEST

Private functions (“defp”). I found it strange that, after reading about modules and functions in Chapter 6, it is in a later chapter on the lists, “Keeping Track of Values During Recursion”, when shown how to define private functions.

I think it would be advisable to give such information before, when talking about the “Modules and Named Functions”.

2014-03-12
93TYPO

Second paragraph of Sigils: “…starts with a percent sign…” should be “starts with a tilde”

2014-03-12
50TYPO

The first example in “Default Parameters” is still using the deprecated notation “//”, instead of “\\\\”.

2014-03-12
41TYPO

Very minor:

“We’re already seen this:” seems like it should be “We’ve already seen this:”

2014-03-12
41TYPO

In page 40:
iex> speak = &(IO.puts(&1))
&IO.puts/1
but text on top of page 41:
So Elixir optimized away the anonymous function, replacing it with a direct reference to the function, IO.puts/2.

Should maybe be IO.puts/1 on page 41, or am I confused?

Thanks/Lars

2014-03-12
7TYPO

“You can put any Elixir code into .iex.”
Should be “.iex.exs” as in the sentence before: “I then created a file called .iex.exs in my home directory, containing the following.”

2014-03-12
41TYPO

So Elixir optimized away the anonymous function, replacing it with a direct reference to the function, IO.puts/2.

Think this should be … IO.puts/1.

2014-03-12
147OK

for me, ‘mix deps.get’ followed by ‘mix docs’ complained about the docs task not existing. I needed to run ‘mix deps.compile’ in between these commands, then it worked.

2014-03-12I tried it here, and it compiled ex_doc automatically.
165TYPO

Paragraph near the top, starting with “(The Reference record”, currently ends with “It is also returned, along with the pid, by the spawn_link call.”. It should read “It is also returned, along with the pid, by the spawn_monitor call”.

2014-03-12
113TYPO

Cha 11 Control Flow, bottom immediately before the example is “Either branch may be absent. taken.” The ‘taken.’ looks like a mixup.

2014-04-19
42TYPO

In the box “the old notation” the code example isn’t rendered correctly, it show html tags instead of chars (& instead of & for example)

2014-04-19
16TYPO

“gentlemen scientists” is double plural, should be “gentleman scientists”

2014-04-19
34TYPO

First paragraph after the “Functions and Pattern Matching” heading

Missing a space character: “Instead, it tries to match values to patterns.(We”

Should have a space before the “(”

2014-04-19
42TYPO

Info Box “The Old Notation” on how the & operator was used before 0.10.1 is has &, > and other special characters escaped:

The Old Notation

Prior to Elixir 0.10.1, you couldn’t use the ‘&‘operator. Instead, you’d write:

iex&gt; func = &1 + &2
&Kernel.+/2
iex&gt; func.(9, 4)
13

Although this looks simpler, it also leads to many ambiguities. This older form is
currently still supported, but it will be deprecated over time.

2014-04-19
235OK

I am currently learning Elixir macros. My understanding of the unquote function is that it code inside is evaluated at macro expansion time, the result is converted to a AST and this AST is then injected into the outer AST.

For example ExUnit.Assert contains the line:

expr: unquote(Macro.to_string(expected)),

And the function Macro.to_string is run at macro expansion time to capture a string description of the assert expression.

Now I could easily be wrong, I am still learning, but this is my current understanding. I think the description of unquote in the book is misleading especially for someone learning Elixir macros.

In the book it first says:

“It temporarily turns off quoting, and simply injects a
code fragment into the sequence of code being returned by quote”

which is not really the whole truth. And then goes on to say

“There’s another way of thinking about this. Using unquote inside a quote is a
way of deferring the execution of the unquoted code. It doesn’t run when the
quote block is parsed. Instead it runs when the code generated by the quote
block is executed.”

I think this is misleading. Macro parameters are passed as an AST thereby delaying execution. This is a feature of the macro. The unquote command evaluates it contents at macro expansion time, just like macro code outside a quote block, but finishes off by injecting the AST into the quoted block.

Perhaps including the unquote(Macro.to_string(expected)) example would help to clarify the behaviour of unquote.

2014-04-19> In the book it first says: \n> \n> "It temporarily turns off quoting, and simply injects a \n> code fragment into the sequence of code being returned by quote" \n> \n> which is not really the whole truth. \n \nI think is is the truth, although maybe a little subtle. Elixir is building an AST. `unquote` says "run this, don't just insert it." It turns off the effect of quoting temporarily. \n
28ERROR

You state:
iex> [1, fred: 1, dave: 2]
[1, [fred: 1, dave: 2]]
which I read as a list with two values, an integer and a list of key/values pairs.
However, when I run the same expression in iex, I get:
[1, {:fred, 1}, {:dave, 2}]
which I read as a list with three values, an integer and two key/value pairs.

2014-04-19
18SUGGEST

In this section you describe how “=” assigns values based on pattern matching, so the following works in iex:
$ a = 1
1
$ a = a + 1
2
Then, in the next section, you state that values are immutable. “a” does not seem immutable to me (although ^a does).
Perhaps I am missing something, but it seems like a contradiction to me.

2014-04-19Variables are not values—they are references to values. I might add a sentence to that effect, but I worry it opens a can of worms
176167?TYPO

“Can you find a way to reveal the problem (perhaps by passing in a different function, or by sleeping, or increasing the number of propcesses)?”

Processes is misspelled.

2014-04-19
42ERROR

In the purple-colored “note box” named “The Old Notation”, the code that it shows has a bunch of xml entities instead of the appropriate greater-than and ampersand symbols. I can send a screenshot if necessary.

2014-04-19
54TYPO

You write “So Elixir optimized away the anonymous function, replacing it with a direct reference to the function, IO.puts/2.”

The code example however shows that it was optimised to “IO.puts/1” instead of “IO.puts/2”.

2014-04-19
42ERROR

In the box “The old notation” HTML entities are not rendered, but shown in raw form (e.g. iex&gt;…)

2014-04-19
22TYPO

The parentheses starting with “(and there are things […]” are never closed.

2014-04-19
286TYPO

for the Line 7 description,
“size takes a collection an returns am integer (>=0)”

two typos, takes a collection and return an integer

2014-04-19
80SUGGEST

Where it reads:

iex> Enum.sort([“once”, “upon”, “a”, “time”],
…> fn a, b -> String.length(a) < String.length(b) end)
[“a”, “time”, “upon”, “once”]

Make “fn a, b -> String.length(a) < String.length(b) end)” be “fn a, b -> String.length(a) <= String.length(b) end)”

(note <= vs <) to make the output:
[“a”, “once”, “upon”, “time”]

As mentioned by Jose in a correction to the Enum.sort/2 documentation, the algorithm is only stable when the fn passed returns true for equal elements.

I’d also make a note on the stability of Enum.sort wherever Enum.sort is talked about in detail.

Github issue for context: elixir-lang/elixir/ #2163 (can’t put hyperlink because of spam filter).

2014-04-19
210SUGGEST

In the listing of otp-supervisor/2/sequence/lib/sequence/supervisor.ex,
on line 5:
result = {:ok, sup } = :supervisor.start_link(MODULE, [initial_number])
[initial_number] is passed to start_link, but the argument is discarded on line 19:
def init(_) do
Maybe just pass empty list to start_link to avoid confusion?

2014-04-19
174TYPO

Fourth paragraph (first one under the windows figure):
And, it we go back to node one, it will now know
about node two.

I think the first ‘it’ was supposed to be ‘if’. As in:

And, if we go back to node one, it will now know
about node two.

2014-04-19
250TYPO

Last paragraph on the page, first sentence starts:

I’ve decide the member? function should…

I think you meant:

I’ve decided the member? function should…

2014-04-19
287TYPO

In the listing of simple.ex, function count_atoms, this function contains the statement “length list”, which is referred to as a stub and on page 288 causes an issue with dialyzer. But this is ‘fixed’ on page 288 with the exact same code. I think on 287 you intended for this line to be empty.

2014-04-19
289TYPO

In the listing for client.ex (near top of page), the function other_function contains the line: “Simple.count_atoms [:a, :b, :c]”, but this line in the following dialyzer output:

client.ex:5: The call ‘Elixir.Simple’:count_atoms([1 | 2 | 3,…])

indicates that the line in the listing should have been “Simple.count_atoms [1, 2, 3]”. Looks like the listing was copied directly from the ‘fix’ later on that page.

2014-08-29
165SUGGEST

The ParallelMap function on page 165 and 166 is very clever and succinctly demonstrates the power of Elixir concurrent processes, however, I found the transition from the previous part of the chapter to this function a bit jarring. The function definitions within function definitions within |> operators is powerful and clever, but really hard to grasp upon first reading.

Since this is a key demonstration, I suggest you transition or lead up to this a bit slower. For example, the following might be an intermediate step:

defmodule Parallel do

# The process that will be spawned. It will take a function and element,
# apply the function and return it along with its pid.

def worker(boss, fun, elem) do
send boss, {self, fun.(elem)}
end

# Receive a result from a specific pid and return it.

defp get_a_result(pid) do
receive do
{^pid, result} -> result
end
end

# The parallel map function.

def pmap(collection, fun) do
me = self
collection |> spread(fun, me) |> collect_results
end

# Create a process for each element of the collection. Return a collection
# of the pids of the processes spawned.

defp spread(numbers, fun, me) do
Enum.map(numbers, fn (elem) -> spawn_link(Parallel, :worker, [me, fun, elem]) end )
end

# Given a collection of pids, receive a result from each one, which becomes
# the new collection.

defp collect_results(pids) do
Enum.map(pids, fn (pid) -> get_a_result(pid) end)
end

end

Just saying.

2014-04-19
109ERROR

When calling your own function defined on a Record the text mentions the record instance is the last parameter but the code example puts the record instance as the first parameter.

2014-04-19
77TYPO

Top of the page, “In this chapter…”, second bullet: THe

2014-04-22
23TYPO

Very bottom of page sentence starts with letter ‘S’, assume it’s meant to say Strings.
“S have their own chapter, and we have a couple of chapters on lists and maps (and other dictionary-like types). ”

2014-04-22
25TYPO

Footnote number 2, change ‘that’ to ‘than’: “…this is actually less convenient that the bracketed forms….”

2014-04-22
84TYPO

Erratic “]]>” at the end of the section.

2014-04-22
154TYPO

The link below the docs image gives a “Forbidden” error.
the link //media.pragprog.com/titles/elixir/code/project/5/issues

2014-04-22
154SUGGEST

The image of the docs index.html is a bit different then what I had generated from the downloaded code. I have more info in the tree in the left pane and in the main pane I have “source” and “functions” links.

Is the image a recent version?

2014-05-16
168SUGGEST

Just wondering if sad_method should be called sad_function?

2014-04-22
140ERROR

Missing `mix deps.compile` line, `mix deps.get` doesn’t do the trick alone I get this after `mix deps.get` and deps.get didn’t compile the dependencies:

```
$ mix deps

  • ibrowse (git://github.com/cmullaparthi/ibrowse.git)
    locked at 5bae730
    could not find an app file at _build/dev/lib/ibrowse/ebin/ibrowse.app, this may happen when you specified the wrong application name in your deps or if the dependency did not compile (which can be amended with `mix deps.compile`)
  • httpotion (git://github.com/pragdave/httpotion.git)
    locked at 3939fc2
    could not find an app file at _build/dev/lib/httpotion/ebin/httpotion.app, this may happen when you specified the wrong application name in your deps or if the dependency did not compile (which can be amended with `mix deps.compile`)
    ```
2014-05-16
138OK

Grammar change on “But, remember, it’s early days.”
it’s = it is, and has unnecessary commas it would be better as: “But remember its early days!” (exclamation mark added, but optional). I’m unsure if the sentence should start with a preposition though.

2014-05-16"It's" is correct
179ERROR

Node.self() returns
:nonode@nohost but with no quotation marks as indicated in the book.
I’m not sure if this is an error in the book or something strange in my setup.

2014-05-16
179ERROR

I believe “iex —name” needs to have the fully qualified name not just a short name like wibble. I got an error when I entere
iex —name wibble
as shown in the book and as far as I can tell from docs it should be
iex —name wibble@light-boy.local

The —sname example is fine.

2014-05-16
68SUGGEST

I could implement my sum without the `total` variable like:

```elixir
defmodule MyMod do
def sum([]), do: 0
def sum([head| tail]), do: head + sum(tail)
end
```

Maybe my version has a bug, but it is not exactly obvious why I would need the memo variable.

Thanks for the awesome book!

2014-05-16Indeed—the the exercise on the following page :)
30TYPO

In the states map on the top of the page “Alamaba” should be “Alabama”

In the bottom of the page when declaring the map again and the result from accessing it, the same typo exists.

2014-05-16
38TYPO

Underscores are used in a way which is non-standard. Most likely due to formatting being missed:

“(think of the ’s’ meaning script).”

2014-05-16
78TYPO

Duplicate code entry for hashdict

iex> hashdict1 = Dict.drop(hashdict, [:where, :likes])
#HashDict<[name: “Dave”]>
iex> hashdict = Dict.drop(hashdict, [:where, :likes])
#HashDict<[name: “Dave”]>

2014-05-16
81TYPO

‘now’ should be ‘know’

“In particular, it doesn’t now what you intend to do with it,”

2014-05-16
81TYPO

‘it’ should be ‘if’

“and it some keys should have default values.”

2014-05-16
9482TYPO

Duplicate line. Appears before (incorrectly) and after (correctly) the explanation paragraph.

“iex> %Subscriber{name: a_name} = s3”

2014-05-16
9785TYPO

Missing space after period:

“basic of lists and dictionaries.But
you may have noticed that”

2014-05-16
21OK

on third paragraph in Garbage Collection section should read “divided” instead of “divvied”

2014-05-12http://www.merriam-webster.com/dictionary/divvy
28TYPO

1st paragraph 1st line “However, iex does’t…” should read “However iex doesn’t…”

2014-05-16
27ERROR

In the last paragraph on records the record creation is missing, e.g.:

iex> defrecord Phone, country: “1”, area: “555”, local: nil

2014-05-16
126114TYPO

‘if’ should be ‘is’

Bad:
“only one split if performed”

Good:
“only one split is performed”

2014-05-16
27TYPO

Under the “Records” heading, the sentence: “The names are assigned at compile time, and so acccess is efficient.”

The word “acccess” is a typo.

2014-05-16
31ERROR

Underneath the code sample, there’s the text “You’ll get an ArgumentError if there’s no matching key if you use the dot notation.”

However, if the dot notation is used and no matching key exists, a KeyError is given, not an ArgumentError.

iex(16)> a = %{key: 1}
%{key: 1}
iex(17)> a.key
1
iex(18)> a.key2

(KeyError) key :key2 not found in: %{key: 1}

2014-05-16
21SUGGEST

First paragraph of Garbage Collection. Perhaps something like ‘data-mutating’ instead of ‘transformational’. The text has described programming as ‘transforming data’, which associates Elixir and ‘transforming’.

2014-05-16That association is correct—Elixir does leave items to be garbage collected.
186177TYPO

‘that’ should be ‘than’

bad:
“more that one machine”

good:
“more than one machine”

2014-05-16
231225TYPO

‘to’ should be ‘you’

Good:
“which lets you add capabilities”

Bad:
“which lets to add capabilities”

2014-05-16
246241TYPO

‘and’ should be ‘are’

Good:
“internal representation of code are contained
in the Code and Macro modules”

Bad:
“internal representation of code and contained
in the Code and Macro modules”

2014-05-16
247242TYPO

Not sure which you meant to have, but I felt the following reads similar to your style.

“Once you’re done that” should be “Once you have done that” OR “Once you’re done with that”

2014-05-16
253248TYPO

The footnote on this page simply cuts off with an amazing cliff-hanger:

“2. Don’t tell anyone, but this is actually quite like”

2014-05-16
23TYPO

At the bottom of the page, it says “S have their own chapter”. It looks like “Strings” was intended.

2014-05-16
90TYPO

In ‘A note on sorting’ the function definition has ‘>’ rather than ‘>’

fn a, b -> String.length(a) <= String.length(b) end

2014-05-16
47SUGGEST

IEx.Options is deprecated. Use IEx.configure instead.

e.g.

Use
IEx.configure colors: [eval_result: “cyan,bright”]
Instead of
IEx.Options.set :colors, eval_result::“cyan,bright”

2014-05-16
107TYPO

The Stream.resource example has a couple of typos. it should be:

Stream.resource(fn -> File.open!(“sample”) end,
fn file ->
case IO.read(file, :line) do
line when is_binary(line) -> { line, file }
_ -> nil
end
end,
fn file -> File.close(file) end)
~

2014-05-24
140SUGGEST

Don’t know if it’s my bad, probably because I’m using httpotion from github, but it appears that I have to go through ‘mix deps.compile’ to use the library:

[amit@localhost issues]$ mix deps

  • ibrowse (git://github.com/cmullaparthi/ibrowse.git)
    locked at 5bae730
    could not find an app file at _build/dev/lib/ibrowse/ebin/ibrowse.app, this may happen when you specified the wrong application name in your deps or if the dependency did not compile (which can be amended with `mix deps.compile`)
  • httpotion (git://github.com/pragdave/httpotion.git)
    locked at 3939fc2
    could not find an app file at _build/dev/lib/httpotion/ebin/httpotion.app, this may happen when you specified the wrong application name in your deps or if the dependency did not compile (which can be amended with `mix deps.compile`)
    [amit@localhost issues]$ mix deps.compile
  • Compiling ibrowse
    Could not find rebar, which is needed to build dependency :ibrowse
    I can install a local copy which is just used by mix
    Shall I install rebar? [Yn]
  • creating /home/amit/.mix/rebar
    ==> ibrowse (compile)
    Compiled src/ibrowse_socks5.erl
    Compiled src/ibrowse_sup.erl
    Compiled src/ibrowse_http_client.erl
    Compiled src/ibrowse_app.erl
    Compiled src/ibrowse_lb.erl
    Compiled src/ibrowse_lib.erl
    Compiled src/ibrowse.erl
  • Compiling httpotion
    Compiled lib/httpotion.ex
    Generated httpotion.app
    [amit@localhost issues]$ mix deps
  • ibrowse 4.0.2 (git://github.com/cmullaparthi/ibrowse.git)
    locked at 5bae730
    ok
  • httpotion 0.2.3 (git://github.com/pragdave/httpotion.git)
    locked at 3939fc2
    ok
2014-05-24
148SUGGEST

httpotion is currently not working on expm.co (I get a blank page)

Not sure if its not maintained or some other issue, but it may be worth picking another client?

2014-05-24Are you using the version from the book—it uses the forked pragdave/httpoption.
141TYPO

Where it says:
Response[body: body, status_code: status, headers: _headers ]
Should say:
%Response{body: body, status_code: status, headers: _headers }

Also because the return type is a struct and they have not been mention by this chapter a short explanation would be handy.

2014-05-24Are you using the version from the book—it uses the forked pragdave/httpotion.
78OK

When I type in the following into iex:

hd = [ one: 1, two: 2, three: 3 ] |> Enum.into HashDict.new

I get the error:

(UndefinedFunctionError) undefined function: Enum.into/2
(elixir) Enum.into([one: 1, two: 2, three: 3], #HashDict<[]>)

2014-06-12You're running an old Elixir
41ERROR

defrecord is mentioned in the last paragraph as if it had been used in the example above, which it wasn’t. It would be helpful to actually have that in the example.

2014-06-12
225ERROR

In the definition of Fib.of,
def of(n), do: Fib.of(n-1) + Fib.of(n-1)
should probably be
def of(n), do: Fib.of(n-1) + Fib.of(n-2)

Also, I get for 6765 for the (corrected) Fib.of(20)

2014-06-12
230TYPO

The command presented for starting iex in separate windows seems incorrect:
iex —sname one iex anagrams_dist.exs
No file named iex

Typo?

2014-06-12
39SUGGEST

map() and map (%{}) would seem to be a potential source of confusion, especially for someone new to functional programming. In some places, map the function gets talked about, and in others its map the datatype. This causes one’s brain (when this is all new to it) to wig out a little bit as we have two separate concepts with the same name.

2014-06-12It is confusing, but it's a part of the language...
28TYPO

Extra “a”: a list is a effectively a

2014-06-12
30TYPO

Misspelled “Alabama”:

iex> states = %{ “AL” => “Alamaba”, “WI” => “Wisconsin” }

%{“AL” => “Alamaba”, “WI” => “Wisconsin”} iex> states[“AL”] “Alamaba”

iex> states[“TX”]

2014-06-12
292TYPO

to a vaue. It returns a (new) collection.

2014-06-12
51SUGGEST

You say at the bottom of the page 51:

Elixir has a couple of its own type check functions:
Range.range? Regex.regex?

While in this section you are talking about Guard clauses and putting Range.range?(x) in guard clause causes compilation error:

cannot invoke remote function Range.range?/1 inside guard

Thank you,

Alex

2014-06-12
105ERROR

The heredocs example does not work for me:
String.split “”“, ”\
"

(SyntaxError) iex:16: heredoc start must be followed by a new line after “”"

Also, I find the section a bit too brief - I am not sure of what use the heredocs are.

2014-06-12
106ERROR

The heredoc example does not work for me:
~r“”"i

(SyntaxError) iex:27: heredoc start must be followed by a new line after “”"

2014-06-12
70TYPO

At the bottom of the page there is a link to the docs, GitHub returns a 404 error.

Please add “elixir/” to the end.

Thanks,

Leo

2014-07-15I can't find this—could you give some context?
112ERROR

In the graphemes section, my results are different from yours:
iex(6)> String.graphemes “Ā`stute”
[“Ā”, “`”, “s”, “t”, “u”, “t”, “e”]
I tried with an apostrophe, with the same result:
iex(7)> String.graphemes “Ā’stute”
[“Ā”, “’”, “s”, “t”, “u”, “t”, “e”]

2014-10-02This is a problem with the font used to render the example—it cannot represent the character "Ā̀" \n \nI'll work out a fix nearer production time.
113ERROR

The codepoint example does not work for me. When the string is empty, next_codepoint seems to return nil rather than :no_codepoint. I cut and paste the code to make sure I did not make a typo. Note - my module is named Chp11.

iex(17)> Chp11.each “∂og”, fn c -> IO.puts c end

o
g

(FunctionClauseError) no function clause matching in Chp11._each/2
chp11.ex:78: Chp11._each(nil, #Function<6.106461118/1 in :erl_eval.expr/5>)

2014-06-12
114ERROR

I do not get the same results for String.split as you:

iex(42)> String.split “the cat on the mat”, ~r{[ae]}, global: false
[“th”, " c“, ”t on th“, ” m“, ”t"]

This is the third problem I have had with the String module, perhaps the issue is with the elixir/erlang version:

Erlang/OTP 17 [erts-6.0] [source-07b8f44] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]

Interactive Elixir (0.14.0-dev)

I am running Ubuntu 14.04.

2014-06-12
134OK

Hi Dave - great book!

I think the case statement needs to be updated to parse the count value as the OptionParser returns Strings eg String.to_integer(count)

Thanks - Georgi

case parse do
{ [help: true], _ , _ } ->
:help
{ , [user, project, count], } ->
{user, project, String.to_integer(count)}
{ , [user, project],} ->
{user, project, @default_count}
_ ->
:help
end

2014-06-12ad revealed by the test in the next section :)
226TYPO

Second paragraph on page, the following sentence:

This call waits for our background task to finish, and returns it’s value.

“it’s” should be “its.”

2014-06-18
51TYPO

For footnote 5, the location moved to

elixir-lang.org/getting_started/5.html

2014-06-30
123ERROR

The example file control/case1.ex doesn’t work in Elixir 0.14.0. I get the following error:

c “case1.exs”

Compilation error on file case1.exs

(ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:3811: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3028: Kernel.define/4
(elixir) expanding macro: Kernel.def/2

(exit) 1
(elixir) lib/kernel/parallel_compiler.ex:187: Kernel.ParallelCompiler.handle_failure/5
(elixir) lib/kernel/parallel_compiler.ex:176: Kernel.ParallelCompiler.wait_for_messages/8
(elixir) lib/kernel/parallel_compiler.ex:49: Kernel.ParallelCompiler.spawn_compilers/3
(iex) lib/iex/helpers.ex:89: IEx.Helpers.c/2

I believe this is due to using the pre-0.13.0 defrecord function, which was moved in 0.13.0 to Record

The same problem also affects control/case2.ex.

These probably need to be changed to use structs to follow the new recommendations.

2014-06-30
201TYPO

Handle_call is mistakenly referred to as “handle*call” in the Handle_call section.

2014-07-01
203TYPO

There’s an extra comma in the first IEX line at the top of the page inside the parenthesis.

GenServer.start_link(, Sequence.Server, 100, name: :seq)

Just needs to be removed and all will function again…

2014-07-01
21OK

It reads: “But Elixir knows that list1 will never change, so it simply constructs a new list with a head of 4 and a tail of list1.”

This is NOT true in Elixir. It is true in Erlang. After list2 has been constructed, list1 can be changed. The fact that it does not affect the value of list2 is a different thing!

2014-06-27I think you're confusing values and variables. The list cannot be changed. The variable that is associated with it can be reassosicated with another value, though.
174ERROR

Process.spawn_monitor has been moved to Kernel in 0.14. The example for the module Monitor1 on line 10 can be updated from Process.spawn_monitor to just spawn_monitor.

2014-07-01
140ERROR

binary_to_integer was (soft) deprecated in 13.3 (see the CHANGELOG.md in the repo) in favor of String.to_integer, so the fix for the failing test case should use String.to_integer instead of binary_to_integer.

2014-06-30
144OK

After running `mix deps.get`, I got ‘could not find an app file’ errors that told me to run `mix deps.compile`. Running `mix deps.compile`, compiling ibrowse said I needed to install rebar, finall `mix.deps` was clean and matched the book. You may want to mention these extra steps and perhaps an explanation of what rebar is.

2014-06-30mix should download and install rebar for you automatically. Is it possible you were offline for the compilation step?
143ERROR

pragdave/httpotion is out of date with myfreeweb/httpotion. pragdave doesn’t work with Elixir 0.14, but myfreeweb/httpotion, but it does involve changing the code on page 145 to use the struct syntax. I have the change in a github repo here: github.com/KronicDeth/issues/compare/59fe335d1258ae9c644d160b45a6fd367906f542…9c955043c4bc15b02a2e4c78a6b124a156dfa418

(P.S. I’ll pull down the repo if you don’t want me sharing code from the book Dave. This was just the easiest way to share the code with you and other people on the forums that were getting the same error.)

2014-06-30
286ERROR

Chapter 13:: Task: Make a command line executable

escriptize now uses an escript option list in the project configuration

“project/4/issues/mix.exs
​ \t
​def​ project ​do​
[ app: :issues,
version: ​”0.0.1“​,
elixir: ​”>= 0.0.0"​,

  • escript_main_module: Issues.CLI,
    deps: deps ]
    ​end​”

should look like this:

​def​ project ​do​
[ app: :issues,
version: ​“0.0.1”​,
elixir: ​“>= 0.0.0”​,

  • escript: [main_module: Issues.CLI],
    deps: deps ]
    ​end​”
2014-07-01
289ERROR

Chapter 13::Test the Comments

In the doc test for split_into_columns/2 the first argument (list) should be a hashdict. I solved by using the convert_to_list_of_hashdicts/1 function you wrote earlier. e.g.

## Example

iex> list = [ [ {“a”, “1”}, {“b”, “2”}, {“c”, “3”}],[ {“a”, “4”}, {“b”, “5”}, {“c”, “6”}] ]
iex> list |> Issues.CLI.convert_to_list_of_hashdicts |> Issues.TableFormatter.split_into_columns([“a”, “b”, “c”])
[ [“1”, “4”], [“2”, “5”], [“3”, “6”] ]

“”"

Also, according to the peepcode interview that José did, he stresses a semantic difference between docs and comments, so this chapter might better be named Test the Docs… but that’s just a nit picky thing so that is of course entirely up to you.

2014-07-01
66SUGGEST

“the in operator” should be a heading like the others with the purplish/blue color, not black text like the definitions.

2014-06-30
72SUGGEST

When explain how to import a module, the book explains how to delimit the amount of functions imported. My suggestion is when talking about this, specify that we must use [ function: arity]. The book says [function, arity]. The example is correct, but the general case, not much.

2014-06-30
43SUGGEST

The term “arity” is mentioned here on page 43 but it isn’t defined until page 46. I had watched a video before diving into the book, so I knew what arity was. But I imagine that someone coming in cold would be confused by the term.

2014-06-30
70SUGGEST

In previous examples, you use “func” as the variable name for functions. Here, you use “fun”. I think it would be more consistent to use “func” here as well.

2014-06-30
21OK

“But the cool thing about Elixir is that you write your code using lots and lots
of processes, and each process has its own heap. The data in your application
is divvied”

I guess you mean “divided”

2014-06-30Nope :)
160SUGGEST

With jsonex incompatible with Elixir 0.14, and you already using jsx for the default implementation, Exercise OrganizingAProject-5 becomes no op and could be removed.

2014-07-15
89TYPO

“For example, a primitive Elixir list is just a ordered list of values”

The “a ordered” should be “an ordered”.

2014-07-15
99TYPO

“Here’s you’d have to execute the query”

Here you’d have to execute the query

2014-07-15
99TYPO

“lists, you can to supply the keys as symbols:” should be: “lists, you can supply the keys as symbols:”

2014-07-15
49SUGGEST

You end the chapter with “we’ll see how to organize these into modules and named functions.” and the chapter immediately after is named “Anonymous function”. That sounds a bit confusing.

2014-07-15
183TYPO

iex> Node.self
:nonode@nohost

Note that the name that’s returned is an atom—it’s in quotes because it
contains an at-sign.

The atom doesn’t contain quotes so you can remove “—it’s in quotes because it
contains an at-sign.”

2014-07-15
183TYPO

In regards to #76951

So once you name the node like:

iex —name wibble@light-boy.local

and call ‘iex> Node.self’ the result is quoted. What causes the atom to be quoted isn’t the at-sign it’s the dot and hyphen.

Sorry for posting twice on this

2014-07-15
210ERROR

Example: otp-supervisor/1/sequence/lib/sequence.ex

`use Application.Behaviour`

should be:

`use Application`

2014-07-15
69SUGGEST

I would develop more note 2: this is a perfect example of what it means to transform data. As you said the invariant always applying to the data, but we produce a new form (the sum) by transforming the data

2014-07-15
105ERROR

In this page it reads:

```
iex> Enum.sort([“once”, “upon”, “a”, “time”], fn a, b -> String.length(a) <= String.length(b) end)
[“a”, “time”, “upon”, “once”]
```

Yet the result for the lines should be revised, the outputs should be:
```
iex(2)> Enum.sort([“once”, “upon”, “a”, “time”], fn a, b -> String.length(a) <= String.length(b) end)
[“a”, “once”, “upon”, “time”]
```

This is consistent with the note on page 107 of the PDF

2014-07-15
30ERROR

Chapter 4, Binaries section. There are two examples, the first one has been updated from the deprecated `Kernel.size` to `byte_size`; however, the second example (the one with bit widths of 2, 4, and 2) continues to use the deprecated `size`.

2014-07-15
113OK

I just bought this book, so I believe its the latest. This is using the epub. On page 113. It shows an example of a keyword list

“\t
[ name: ​”Dave“​, city: ​”Dallas“​, likes: ​”Programming“​ ]”

converts to:

“[ {:name, ​”Dave“​}, {:city, ​”Dallas“​}, {:likes, ​”Programming“​} ]”

But, in my shell, I dont see this

Interactive Elixir (0.12.0)

iex(1)> [name: “Dave”, city: “Dallas”, likes: “Programming”]
[name: “Dave”, city: “Dallas”, likes: “Programming”]

2014-07-15
105OK

Enum.each [1,2,3,4], fn x -> IO.inspect x end

should be IO.puts

another thing is using & Notation, in the latest elixir its 0.12 the syntax is

Enum.each [1, 2, 3, 4] &(IO.puts &1)

2014-07-15
79TYPO

“We can use this may ways” where “may” should be “many”. This text is located at the bottom of page 79

2014-07-15
72TYPO

Alternative, you can give only…

Should start with Alternatively

2014-07-15
60TYPO

Link to Elixir documentation in the footnotes points nowhere. The “stable/” at the end should be removed.

2014-07-15
191TYPO

In the paragraph just before the example IEx sessions:

“Let’s run it. We’ll start up our two nodes. We’ll call Server.start on node one. Then we’ll call Client.start on both node one and node two.”

`Server.start` should be `Tick.start`

2014-07-15
189SUGGEST

The module for the server is named Tick, but the file name is ticker.ex and the Node name is also ticker. Renaming the server module to Ticker could be clearer.

2014-07-15
123TYPO

the syntax highlight on the lines entered on this page are wrong, there’s a trailing green on lines for “iex>” prompt.

2014-07-15Unfortunately this is not easily fixed.
124TYPO

“Elixir does not check the nexting of…” should be “Elixir does not check the nesting of…”

2014-07-15
131ERROR

On this page the line that goes: `MyString.each “doge”, fn c -> IO.puts c end`

prints characters one per line, not as it says it would, the page shows output to be space separated

2014-07-15
137TYPO

the outputs that read “true part” and “false part” are syntax highlighted, even though these are just strings being returned by the expression and not true/false boolean values. These outputs should not be highlighted like the input is.

2014-07-15AGain, hard to fix
92TYPO

Result of Enum.sort([“once”, “upon”, “a”, “time”], fn a, b -> String.length(a) <= String.length(b) end) is [“a”, “once”, “upon”, “time”] not [“a”, “time”, “upon”, “once”] as shown. The result would be correct if <= was changed to <.

2014-07-15
50SUGGEST

Please add a paragraph on functions with default arguments and several bodies.
In Elixir 0.14.3 you will need a function head without body to define the default arguments, which is IMHO a new concept.

2014-07-15
97TYPO

The second line of ‘Creating Your Own Streams’ at the bottom of the page has:

doen’t

rather than

doesn’t

2014-07-15
203ERROR

In the list of GenServer callbacks, handle_call has the following:

Invoked when a client uses :gen_server.call(pid, request}.

The closing curly brace should be a closing paren and :gen_server.call can be changed to GenServer.call

2014-07-15
203ERROR

In the list of GenServer callbacks, handle_cast has the following:

Invoked when a client uses :gen_server.call(pid, request}

:gen_server.cast(pid, request) can be updated to GenServer.cast(pid, request)

2014-07-15
196ERROR

Looks like we don’t need to pass in the empty list of options anymore. I’m guessing the empty list is the default? The code shows that, but the write-up in the next paragraph refers back to an empty array that we’re passing in, but that’s not in the code explicitly:

“In this case, there’s no need to set any options, so we pass an empty array.”

2014-07-15
227ERROR

Application.get_env is now /2 instead of /1. (Using 0.14.3)
I had to change the `mix.exs` listing to:
```
def application do
[
mod: { Sequence, []},
env: [ initial_number: 456 ],
registered: [ :sequence ]
]
end
```
I also had to change the `sequence.ex` listing to:
```
Sequence.Supervisor.start_link(Application.get_env(:sequence, :initial_number))
```

2014-08-01
271ERROR

The previous example of Sequence.Server didn’t start with “use GenServer.Behaviour” as indicated at the very beginning of this chapter. It’s just “use GenServer” now.

2014-08-01
197SUGGEST

When generating the Sequence project we don’t pass the —sup flag so the Supervisor isn’t setup in lib/sequence and it isn’t added to the mod tuple in the application function in mix.exs.

In the Supervisors And Workers section of Chapter 17 it seems to be implied that the lib/sequence/supervisor.ex file already exists and Sequence has been added to the mod tuple in mix.exs.

I suggest we either generate the project back on page 197 using —sup or expand the Supervisors and Workers section to create those files on our own and then demonstrate how using the —sup flag can do this for us on new projects.

2014-08-01
212ERROR

In the example code for sequence.ex, `use Application.Behaviour` can be changed to just `use Application`

2014-08-01
224ERROR

In the paragraph just after running `mix compile`:

“Mix tells us it has created a sequence.app file, but where is it? As of Elixir 0.11.2, it is tucked away in _build/shared/lib/sequence/ebin.”

As of Elixir 0.11.2 _build/ now has directories based on environments by using the build_per_environment application setting. This setting originally defaulted to false in 0.11.2, but as of 0.12.3 build_per_environment now defaults to true.

2014-08-01
225TYPO

In the line of text in between mix.exs and lib/sequence.ex code samples we have:

“and then accessed the value using gen_env:”

This should be corrected to get_env or Application.get_env to be more explicit.

2014-08-01
238ERROR

Copypasta errors for the distributed anagram examples.

Window #1: sname is `one`, but iex session shows `node_one`
Window #2: sname is `one`, which is incorrect because you can’t have two with the same sname, but also the the iex session shows `node_two` and tries to connect to `node_one`.

Additionally, a couple lines below (on page 239), the next Window #2 shows loading words from file `words/list2`, which I believe is supposed to be `words/list4` since the output doesn’t show duplicated output from words/list2.

2014-08-01
94TYPO

The sorting examples have been changed in this edition and you no longer use <= in your sample. This makes the note on sorting seem a little odd.

2014-08-01
155OK

The mix escript.build returns an error:
(Mix) The task escript.build could not be found
I am using Elixir v0.14.0-dev with Erlang/OTP 17.

I found an article on planet.elixircentral.com which uses mix escriptize instead. After minor changes to the mix.exs, this worked.

2014-08-01Your elixir is out of date
160OK

When I run mix docs, I get an error:

Compilation error on file lib/ex_doc/markdown/earmark.ex

(CompileError) lib/ex_doc/markdown/earmark.ex:27: Earmark.Options.struct/0 is undefined, cannot expand struct Earmark.Options
(elixir) src/elixir_map.erl:55: :elixir_map.translate_struct/4
(elixir) src/elixir_clauses.erl:36: :elixir_clauses.clause/7
(elixir) src/elixir_def.erl:182: :elixir_def.translate_clause/7
(elixir) src/elixir_def.erl:171: :elixir_def.translate_definition/8
(elixir) src/elixir.erl:156: :elixir.erl_eval/2

It refers to earmark.ex, the first line of the following:
options = %Earmark.Options{
gfm: Keyword.get(opts, :gfm, true),
breaks: Keyword.get(opts, :breaks, false),
smartypants: Keyword.get(opts, :smartypants, true),
}
I thought it might be caused by what looks like an extra comma at the end of the smartypants line, but that did not change the error.

2014-08-01You might want to update your elixir
230SUGGEST

The last time we visited the Sequence.Server code base we had added the functionality for the Stash.Server. The code sample on page 230 doesn’t have the Stash.Server logic. We are also registering the process name as :sequence, which could be used already by the main Sequence application because we added `registered: [ :sequence ]` to application/0 in mix.exs.

Would it be clearer for the readers if the code sample reflected the most recent version of Sequence.Server?

2014-08-01
234TYPO

At the top of the page:

“The call to Task.async creates an separate process that runs the given function.”

“an” can just be “a”

2014-08-01
235ERROR

In the IEx session for the counter Agent, the return value of final Agent.get(count, &(&1+1)) is shown as being 2. Since we increment the number in this Agent.get, the proper value is 3.

2014-08-01
263TYPO

In the section “protocols/bitmap_access.exs” the “defimpl Access” should have a “do” after it and “def access” should be “def get”.

2014-08-01
87OK

When I enter the code from the example get_in_func.exs I get the following error:

(ArgumentError) the access protocol for lists expect the key to be an atom, got: #Function<0.37978502 in file:get_in_func.exs>
(elixir) lib/access.ex:56: Access.List.get/2
(elixir) lib/kernel.ex:1630: Kernel.get_in/2
get_in_func.exs:14: (file)
(elixir) src/elixir_lexical.erl:17: :elixir_lexical.run/2
(elixir) lib/code.ex:296: Code.require_file/2

2014-08-01Strange: works here \n \n \n[code/maps] elixir get_in_func.exs \n \n["José", nil, "Larry"] \n \n
148TYPO

The decode_response function in the pdf has a typo (and does not match the code online):

def decode_response({:error, msg})

rather than :

def decode_response({:error, error})

2014-08-01
255TYPO

It’s instructive to try creating values and inspecting them with records: false
=>
It’s instructive to try creating values and inspecting them with structs: false

2014-08-01
148OK

I believe there is a “:” missing before “error” in the following:
def decode_response({:error, msg}) do
{_, message} = List.keyfind(error, “message”, 0)
i.e. the last line should be
{_, message} = List.keyfind(:error, “message”, 0)

2014-08-01Actually, the error is in the unction head, which should be \n \ndef decode_response({:error, error})
303TYPO

Both examples are the same, showing the correct version. The first one should have Simple.count_atoms [1, 2, 3] instead it has the correct atoms Simple.count_atoms [:a, :b, :c] which can be confusing.

2014-08-29
113ERROR

Wrong:

iex> list_to_tuple str
{111, 108, 233}

Right:

iex> List.to_tuple str
{111, 108, 233}

2014-08-01
55TYPO

val |> f(a,b) is basically the same as calling f(val,a,b) , and

should be f(val(a,b))

2014-08-29
43TYPO

The octal number should be 0o756 in sentence “Integer literals can be written as decimal (1234), hexadecimal (0xcafe), octal (0765), and binary (0b1010).”

2014-08-29
144TYPO

Top of page.

The version of httpoison in the example is “0.3”, however in the text it is “3.0”.

2014-08-29
184TYPO

The fib.exs example on the bottom of page 184 has

to_process = [ 37, 37, 37, 37, 37, 37 ]

The text on the top of page 185 says

The to_process list contains … the same number, 37, ten times.

2014-08-29
157TYPO

First sentence, “determine at compile timethe minimum level of logging”.

Need space between ‘time’ and ‘the’.

2014-08-29
157ERROR

In the new text about Logger. You reference the Logger module consistently except in the examples in the middle of the page where you say:

Log.debug “Order total #{total(order)}”
Log.debug fn -> “Order total #{total(order)}” end

I think this should be:

Logger.debug “Order total #{total(order)}”
Logger.debug fn -> “Order total #{total(order)}” end

2014-08-29
144ERROR

You say:

“In this case, we give the version as ”~> 3.0“.”

When in fact the example above (correctly) shows the version as ‘~> 0.3’.

Additionally, I think that HTTPoison has an external Erlang dependency which is NOT included in Hex, the hackney library. In the README for HTTPoison it says:

“Be aware that for now, hackney is not on (link to Hex dot PM) If you are using hex dependencies you will need to add hackney as dependency.”

def deps do
[
{:httpoison, “~> 0.3”}
{:hackney, github: “benoitc/hackney”, tag: “0.13.0” }
]
end

This is maybe a good opportunity to also talk about included Erlang libs as a dependency in Mix.exs.

2014-08-29
105ERROR

You use a comma inside a ~w sigil, which seems strange. Although the resulting output is correct, I think it would be more intuitive to write `~w{ cat dog }`, or to even use a “normal” list `[“cat”, “dog”]` since sigils are only discussed later in the book.

2014-08-29
78OK

In the extra box “How Lists Are Displayed by iex”, I believe this is actually an issue with how Erlang interprets lists/strings. Elixir has the unfortunate privilege of inheriting this fun syntactic bungle.

2014-08-29
186TYPO

As you know, * Exlir* modules are basically buckets of functions—they cannot
hold state.

2014-08-29
195ERROR

“inside the Tick.register function, it locates the node contai…”

Module name is Ticker, and therefore the call should be Ticker.register

2014-08-29
195TYPO

“Let’s run it. We’ll start up our two nodes. We’ll call Tickgrer.start on node one.”

2014-08-29
236TYPO

“This is pretty mush the same as specifying any other worker”

Mush! Mush!

2014-08-29
95ERROR

The output of the section “A Stream is a Composable Enumerator” at the end of the page reads “Stream.Lazy” yet it’s this on my computer:

“#Stream<[enum: [1, 3, 5, 7], funs: [#Function<37.75994740/1 in Stream.map/2>]]>”

I’m guessing Stream.Lazy is an out-of-date name, there are many more cases in the section and possibly throughout the book.

2014-08-29
197SUGGEST

“Note that we’ve registered the pid, we can access it from the other node.”

shouldn’t it be phrased “Note that once we’ve registered the pid, we can access …”

2014-08-29
144TYPO

This shows that the HTTPoison library is installed, but tht it hasn’t yet been.

Missing ‘a’ in ‘tht’

2014-08-29
195TYPO

Tickgrer.start instead of Ticker.start

2014-08-29
157SUGGEST

Should there be a mention to “require Logger” in code example of github_issues.ex?

2014-08-29
223ERROR

HTTPotion is referred to in the OTP:Applications fourth chapter and probably other places in the book, these are remnants of before the change to HTTPoison.

2014-08-29
148ERROR

on the “project/3/issues/lib/issues/github_issues.ex” only :jsx.decode(body) is added, and not for handling non-200 status codes (for errors) on handle_response.

Github errors are returned in json format too as assumed for creating decode_response. a :jsx.decode for the error body is needed.

2014-08-29
157TYPO

Related to comment about p.148 by Jamiel Almeida, “handle_response(%{status_code: status, body: body})” should decode “body” like “{ :error, :jsx.decode(body) }”.

2014-08-29
148ERROR

On Transformation: Convert Response we decode the json response on handle response with :jsx.decode(body) but only when the pattern is {status_code: 200, body: body} when the pattern is{status_code: _, body: body } we keep the not decoded response.

The problem with that is when we run the Issues.CLI.run with a invalid repo for example like [ “maurogeorge”, “nonexistent” ]. The List.keyfind/4 expects a list not a string return a error:

(ArgumentError) argument error
(stdlib) :lists.keyfind(“message”, 1, “{\\”message\\“:\\”Not Found\\“,\\”documentation_url\\“:\\”github api url“}”)
(elixir) lib/list.ex:178: List.keyfind/4
(issues) lib/issues/cli.ex:53: Issues.CLI.decode_response/1

To fix we need to decode the response like:

def handle_response(%{status_code: _, body: body }) do
{ :error, :jsx.decode(body) }
end

This way when we run the CLI with invalid data we got our error handling message.

Error fetching from github: Not Found

Thats it. I hope I helped =)

2014-08-29
178TYPO

At the bottom of page 178, to execute `spawn/link3.exs`, the command should be:

```
$ elixir -r link3.exs -e Link3.run
```

2014-08-29
215TYPO

“No our supervisor process calls the start_link function”.
Should be “Now …”

2014-08-29
227ERROR

(using Elixir 15.1)
It seems that:
Sequence.Supervisor.start_link(Application.get_env(:sequence, :initial_number))
doesn’t work, when using:

mod: { Sequence, [initial_number: 456] }

The API for Application suggests using:
def application do
[mod: {Sequence, []},
env: [initial_value: 456]]
end

which appears to be working

2014-08-29
232SUGGEST

iex output upon recompile is different a bit from what the text reports. Effectively the output is:
iex(5)> c(“lib/updated_server.ex”)
lib/updated_server.ex:1: warning: redefining module Sequence.Server
lib/updated_server.ex:5: warning: redefining module Sequence.Server.State
[Sequence.Server, Sequence.Server.State]

That is, iex report the change in the State module as well

2014-08-29
232ERROR

I’m using Erlang/OTP 17 with Elixir 0.15.1
calling
:sys.resume :sequence
results in

(exit) exited in: :sys.suspend(:sequence)

(EXIT) no process
(stdlib) sys.erl:284: :sys.send_system_msg/2

calling
:sys.resume Sequence.Server
does what it should

2014-08-29
37SUGGEST

The third exercise in Exercise: Functions-1

- pair_tuple_to_list.( { 8, 7 } ) #=> [ 8, 7 ]

Example should use different numbers, 8 and 7 correspond to `BS` and `BEL` so Iex displays `[8, 7]` as ‘\\b\\a’. There’s not an explanation of why this happens until Chapter 11.

2014-08-29
295ERROR

To define own exception,
```
defmodule KinectProtocolError do
defexception [message: “Kinnect protocol error”, can_retry: false]

def full_message(me) do
# …
end
end
```

2014-08-29
236TYPO

“This is pretty mush the same as specifying any other worker:”

2014-08-29
177ERROR

At the end of the spawn/link1.exs file there’s the statement “Link1.run”. However, the command that is used to run the file has “-e Link1.run” in it, causing Link1.run to be run twice, and the output shows up twice.

2014-08-29
241TYPO

All be need to do

2014-08-29
241SUGGEST

Explain what happens under the hood. Which node stores the state? What are performance implications?

2014-08-29
46TYPO

“This means that new software needs to use as many cores as it can if it is to maximum its use of the machine.”

Excerpt From: Dave Thomas. “Programming Elixir.” iBooks.

Should be “maximize” instead of maximum

2014-08-29
246TYPO

myif Or my_if ?

“When we call the myif function, Elixir has to evaluate all of its parameters
before passing them in. So both the do: and else: clauses are evaluated, and
we see their output. Because IO.puts returns :ok on success, what actually gets
passed to my_if is”

2014-08-29
253OK

“The myif macro receives a condition and a keyword list”

Few lines above (p. 252):
“defmacro if(condition, clauses) do”

2014-08-29It is correct—the clauses parameter is a keyword list.
263ERROR

The list of Available Types needs to include Map.
(Going by the list given in elixir-lang.org/getting_started/16.html )

2014-08-29
281TYPO

Under “Writing Your Own Sigils”, third para: “…Elixir converts in into..” should be “…Elixir converts it into…”.

2014-08-29
308TYPO

Bibliography - in the reference to Joe’s book, “Second, 2013” should be “Second Edition, 2013”.

2014-08-29
104TYPO

uses an comprehension

2014-08-29
104TYPO

should mix_maxes be min_maxes?

2014-08-29
85TYPO

Last sentence of “Nested Dictionary Structures” section is a fragment:

“However, there’s one cool trick that both these functions support: rathe”

2014-08-29
3TYPO

4th paragraph reads:

“But no one would write pmap like this—you’re coding at the lowest level. Instead, you’d likely use Elixir’s build-in tasks:”

Suggest changing “build-in” to “built-in”.

2014-08-29
100TYPO

s/funtion/function/

2014-08-29
82TYPO

“And updates follow suite:” should be “And updates follow suit:”

2014-08-29
100TYPO

spawn fn -> :os.cmd(‘say #{text}’) end

The # in the interpolation causes the rest of the line to be rendered as a comment, possibly to do with using ’ instead of "

2014-09-16
257ERROR

At the line
~
iex> fragment = quote(hygiene: [vars: false], do: IO.puts(a))
~
`hygiene: [vars: false]` option of quote is not supported anymore.

For demonstrate binding variable outside of quote, we can use `var!` like:
~
fragment = quote do
IO.puts(var!(a))
end

maybe

2014-08-29
146SUGGEST

OTP is the framework that manages suites of running applications. The app function is used to configure the contents of these suites. By default, this app function does nothing.

Now mix start ‘logger’ by default. So the code example underneath should change to:

~
def application do
[
applications: [ :logger, :httpoison ]
]
end
~

2014-08-29
146TYPO

“But HTTPoison relies on a library called Hackney, and today that” … “isn’t in hex.pm.”[p.147)

It is now (although this is still a good exercise in manual dependency resolution).

Also, HTTPoison has been bumped to 0.4.1.

2014-08-29
148SUGGEST

Others have mentioned that you use :jsx.decode only on the 200 response from github. I notice also that you have a function in issues_cli.ex called decode_response, that doesn’t actually decode the response.

I’d suggest that the decoding is left out of the GithubIssues module (as it’s sole responsibility should be to communicate with github), the decode_response method should do the decoding, and another function used to process the response (including conversion into hashdicts), e.g.

```
def process({user, project, _count}) do
Issues.GithubIssues.fetch(user, project)
|> decode_response
|> process_reponse
end

def decode_response({code, body}), do: {code, :jsx.decode(body)}

def process_response({:ok, body}), do: convert_to_list_of_hashdicts(body)
def process_response({:error, body) do
{_, message} = List.keyfind(error, “message”, 0)
IO.puts “Error fetching from Github: #{message}”
System.halt(2)
end
```

This just seems a more concise set of transformations and responsibilities to me.

(Also, meta: errata should be able to include markdown!)

2014-08-29
18TYPO

“Today, a similar phenomena is happening.”

“Phenomena” is plural; should be “a similar phenomenon.”

2014-08-29
24ERROR

There’s an error in the following paragraph:

Integer literals can be written as decimal (1234), hexadecimal (0xcafe), octal (0765), and binary (0b1010).

Octals are prefixed with “0o” so the example should be 0o765

2014-08-29
144ERROR

You write:

In this case, we give the version as “~> 3.0”. This matches any version of HTTPoison with a major version of 3 and a minor version of 0 or greater.

but the major and minor version numbers should be switched around, both in the version string and in the explanation following that:

In this case, we give the version as “~> 0.3”. This matches any version of HTTPoison with a major version of 0 and a minor version of 3 or greater.

The mix.exs listing above this paragraph however uses the correct version number 0.3.

2014-08-29
20TYPO

4th pp: “But a few months before starting this boook”

2014-09-16
22TYPO

Example code defines function as “pmap1” but then calls “pmap” with no 1.

2014-09-16
18TYPO

Almost at the end, “Your current probgramming language is probably designed to make it easy to change data.” “probgamming”

2014-09-16
50TYPO

The link to coding style guide no longer points to coding style guide and it is just a contribution guide.

2014-09-16
207TYPO

Last sentence in `handle_call` section ends with “for every call time your server implements.”

2014-09-16
209TYPO

Towards the end of the “Naming a Process” section, the pid returned by the call to `GenServer.start_link` and in the result of the call to `:sys.get_status` do not match, though they do in my REPL, and seem like they should.

2014-09-16
186SUGGEST

The FibAgent cache uses a value of 0 for fib(0) whereas the prior example in FibSolver uses a value of 1 for fib(0). The wikipedia article mentions 2 sequences, one beginning with 0, and another with 1. For comparison of FibSolver to FibAgent, suggest modifying FibSolver to read: defp fib_calc(0), do: 0

2014-09-16
210TYPO

Exercise 4 mentions “`gen_server` calls”, though `GenServer` seems more appropriate as that’s what’s in all of the code.

2014-09-16
155SUGGEST

The widths_of function doesn’t consider the headers so you end up with output like this:

nu | created_at | title
—-——————————————————————————————————
7 | 2012-09-15T10:48:11Z | Should have a websocket demo ?
45 | 2013-02-23T14:40:56Z | Raise an error if a layout can’t be found.
46 | 2013-02-24T21:42:23Z | Force mix dynamo CamelCase to raise exception

Ideally, the widths of the headers should also be considered and the output should look like this:

number | created_at | title
—————————————————————————————————————
7 | 2012-09-15T10:48:11Z | Should have a websocket demo ?
45 | 2013-02-23T14:40:56Z | Raise an error if a layout can’t be found.
46 | 2013-02-24T21:42:23Z | Force mix dynamo CamelCase to raise exception

2014-09-16Agreed, but to be honest I think I've already beaten this horse to death...
148TYPO

First sentence of last paragraph: “Remember that when we created the project using mix new, it added a config/ directory containing confix.exs.”

confix.exs should be config.exs.

2014-09-16
143TYPO

“straighforward” is missing a “t”

Context: “We add new dependencies to the deps function. As the project is in hex.pm, that’s very straighforward.”

2014-09-16
215TYPO

In the third bullet point on the page: “…and a set up options…”

2014-09-16
220TYPO

Second bullet point, missing closing parenthesis.

2014-09-16
221TYPO

State shown after the Sequence.Server crashes is inconsistent with rest of REPL. Should be `State: {226, …`

2014-09-16
274TYPO

Similarly, you may —way— to suspend

2014-09-16
123139TYPO

Chapter 11 Familiar and Yet Strange:

``But, once you ghet over the slightly stange…’’.

Further down: ``This deliberate:’’ <- should be ``This is …’’.

2014-09-16
244SUGGEST

Chapter 1: Running Elixir:

Sentence reads: ``On your system, the prompt will be different’’.

Should read: ``On your system, the prompt may be different’’.

2014-09-16
123139SUGGEST

Page numbers are backwards, but leaving it this way for consistency with another typo on this same page.

Second sentence in Chapter 11: Familiar and Yet Strange: ``If we were starting from scratch, we’d probably look a little different.’’ This sentence reads awkwardly. Are we talking about how the language would look differently (if starting from scratch) or how we programmers would approach Elixir strings and binaries differently? I presume the former, but this wording is misleading and distracting.

2014-09-16
237TYPO

Last sentence of last paragraph on page starts with “This this”

2014-09-16
21SUGGEST

The “Copying Data” section begins with “Although common sense might dictate that all this copying of data is ineffi-
cient, but the reverse is true.” The word “but” seems out of place, and the sentence could probably end with “, the reverse is actually true.” instead.

2014-09-16
170155TYPO

Sentence before showing the change to lib/issues/cli.ex,

``If fact, …’’’ <- should ``In fact, …

2014-09-16
55ERROR

“val |> f(a,b) is basically the same as calling f(val(a,b)), and”
should be:
“val |> f(a,b) is basically the same as calling f(val,a,b), and”

2014-09-16
126SUGGEST

The strings “true part” and “false part” in the explanation of “unless” are misleading, as “true part” is returned when the condition is false and vice versa. To me it seems better to reverse those for “unless”.

2014-09-16
126TYPO

The sentence “The value of if and unless is the value of expression that was evaluated.” is missing the article “the” for “expression”.

2014-09-16
222209SUGGEST

Chapter 16: Tidying up the Interface:

``As we’ll see in a couple of chapters when we look at supervisors, …’’ Since the next chapter seems to have solidified into the supervisors chapter, this wording could be cleaned up to something along the lines of: ``As we’ll see in the next chapter about supervisors, …’’. This sort of fix has been done in prior pages (specifically, the GenServer Callbacks: `terminate`).

2014-09-16
192178TYPO

That’sthe default bahviour of linked processes

should be

That’s the default behaviour of linked processes

2014-09-16
192178TYPO

In the run method of the Link3 module you accidentally use spawn_link with the Link2 module:

spawn_link(Link2, :sad_function, [])

but it should be

spawn_link(Link3, :sad_function, [])

2014-09-16
235223TYPO

First sentence, 5th paragraph: ``… fetching GitHub issues using the HTTPoisonn …’’

2014-09-16
246235TYPO

Chapter 19: Second paragraph, third sentence: ``But we don’t want to be bother…’’ <- should be bothered.

2014-09-16
252241ERROR

Window #2, ``WordlistLoader.load_from_files(..`` loads ``words/list2`` twice. I presume this should read ``..(~w{words/list3 words/list4})``.

2014-09-16
252241SUGGEST

First Window #1 should have the ``Dictionary.start_link`` invoke for completeness.

2014-09-16
118ERROR

String.next_codepoint(str) returns nil, not :no_codepoint, when str is empty.. Example code does it right, but text is wrong.

2014-10-02
119ERROR

String.next_grapheme(str) returns nil, not :no_grapheme, when str is empty..

2014-10-02
200186ERROR

There’s a minor Problem with exercise “Exercise: WorkingWithMultipleProcesses-9”.

First, I think you should prefer the term ‘scheduler’ over ‘server’ in the exercise description.

Second, there’s a small problem with the scheduler code: The message :fib is hard coded, I think it is cleaner to pass it to Scheduler.run. The signature could for example be something like this instead:

defmodule Scheduler do
def run(num_processes, module, spawn_func, work_func, queries) do
# …
end

defp schedule_processes(processes, queue, work_func, results) do
# …
end
end

2014-10-02
144OK

Current version of httpoision is 0.4.2 instead of 0.3

2014-10-02These kinds of things will always happen :)
148TYPO

Below “Application Configuration” at the bottom, “Before we move on from the GithubFetch module” got the module wrong; it should be “GithubIssues”.

2014-10-02
148ERROR

Code at the top of the page, for decode_response({:error, error}), doesn’t work at this point. List.keyfind(error, “message”, 0) isn’t getting a list, but rather a string, since we didn’t call :jsx.decode() for the error case in handle_response().

2014-10-02
30TYPO

Under “Acknowledgements” first paragraph: “[…] ecosystem that feels way more mature that its years”.

Shouldn’t the second “that” say “than”?

2014-10-02
157ERROR

The debug logging in handle_response(%{status_code: 200, ..) calls inspect(response.body), should be inspect(body).

2014-10-02
235ERROR

HTTPoison uses hackney instead of iBrowse. So this sentence:

When we then started it, HTTPoison in turn started a couple of other applications that it needed (SSL and iBrowse)

Should probably read as:

When we then started it, HTTPoison in turn started a couple of other applications that it needed (SSL and hackney)

2014-10-02
230218SUGGEST

I had a small typo somewhere in my SubSupervisor so it would not start. The issue was hard to track down for me, because the example supervisor does not match the call to start_child against the tuple {:ok, pid}. I would suggest adding that to the Supervisor module, as it shows immediately where things went wrong. So im my opinion the last line of Sequence.Supervisor.start_workers should be

{:ok, _} = Supervisor.start_child(sup, supervisor(Sequence.SubSupervisor, [stash]))

2014-10-02
24TYPO

Value types: Floating point: in the example literal values you have 0.314158e1 (and 314159.0e-5). That should be 0.314159e1

2014-10-02
25SUGGEST

In the bulleted lists of types on page 23 (first page of Chapter 4), regular expressions come before ranges. But in the text on page 25 (value types), ranges are described before regular expressions. I think this is the only discrepancy between the bulleted lists and the order of the text - you might want to correct it.

2014-10-02Wow. Good spotting.
28SUGGEST

Chapter 4, section on Lists, page 28 - code examples showing the use of list operators have comments. The use of # to delimit comments is not introduced until page 31 - perhaps you could mention it earlier.

2014-10-02
235223TYPO

For example, back when we were fetching GitHub issues using the HTTPoisonn

should be

HTTPoison

2014-10-02
237225ERROR

You write

In our case, the sequence server registers itself under the name :sequence,
so we’ll update the configuration to read:

def application do
[
mod: { Sequence, 456 },
registered: [ :sequence ]
]
end

but actually, the Server is registered under `Sequence.Server` (aka `:Elixir.Sequence.Server`),
because it is started like this (see p. 222 PDF, 209 print)

def start_link(current_number) do
GenServer.start_link(MODULE, current_number, name: MODULE)
end

You should either change the Supervisor.Server Module to actually register the name
`:sequence` and use it everywhere like this:

defmodule Sequence.Server do use GenServer
#####
# External API

def start_link(current_number) do
GenServer.start_link(MODULE, current_number, name: :sequence)
end

def next_number do
GenServer.call :sequence, :next_number
end

def increment_number(delta) do
GenServer.cast :sequence, {:increment_number, delta}
end

#####
# GenServer implementation

# …
end

or change the application method in mix.exs to this:

def application do
[
mod: { Sequence, 456 },
registered: [ Sequence.Server ]
]
end

2014-10-02
33SUGGEST

Under “Join operators”, the list difference operator is described as “# set difference between two lists”. That’s only true if the lists are treated as sets (containing no duplicate elements). Otherwise the number and order of repeated elements matters. I suggest you just describe it as “# difference between two lists”.

2014-10-02
19OK

“you believe that 99 will always have the value 99” should be “you believe that count will always have the value 99”

2014-10-02No—the belief is the immutability of the value, not the variable that references it.
51SUGGEST

In the part about Guard Clause Limitations, you wrote that the in operator can be used in a guard clause to test membership in a collection. It can also be used to test membership in a range.

2014-10-02
262253TYPO

The myif macro …

should be

The if macro …

or

The My.if macro …

2014-10-02
51ERROR

`xor` is not available as a boolean operator. Only `and`, `or` and `not`.

2014-10-02
95SUGGEST

Section: Dictionaries, at the end of the second paragraph you will find this sentence: ‘We’ll look at this in <ref linkend=”sec.collectable”’. I think that you need to close the `ref` tag.

2014-10-02
109ERROR

In the ‘Select elements by position or criteria’ examples you showed `Enum.filter(list, &Integer.even?/1)` and you should note that `Integer.even?/1` is deprecated. Instead you can use `Enum.filter(list, &Integer.is_even/1)`. In both cases you require Integer before invoke the macro.

2014-10-02
262253SUGGEST

In Exercise MacrosAndCodeEvaluation-2, it would have been helpful to get a hint that the def macro takes symbol arguments. I spent quite some time figuring this out, although in the end I got there without external help. However, I think this detail was just hindering me and has not much to do with the actual topic of the exercise. Maybe a hint would be useful, decide for yourself.

2014-10-02
7961ERROR

The exercise “ModulesAndFunctions-7” asks us to “Convert a float to a string with 2 decimal digits”, but your solution in the forum prints it:

:io.format(“~.2f~n”, [2.0/3.0])

to obtain an actual string we could use

hd(:io_lib.format(“~.2f~n”, [2.0/3.0]))

I think you should either update the task in the book to “Print a float with 2 decimal digits” or change the proposed solution in the forum to the above.

2014-10-02
118ERROR

The source code in enum/countdown.exs shows a warning in this situation:

iex(10)> speaker |> Enum.take(5)
3
2
1
warning: returning nil from Stream.resource/3 is deprecated, please return {:halt, acc} instead
(elixir) lib/stream.ex:1153: Enumerable.Stream.do_each/4
(elixir) lib/enum.ex:1731: Enum.take/2
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6
(elixir) src/elixir.erl:175: :elixir.erl_eval/3

You can fix the situation replacing this line:

count when count == 0 -> nil;

By this one:

count when count == 0 -> {:halt, 0}

2014-10-02
285277ERROR

in the example “protocols/bitmap_inspect.exs” you define the inspect function as

“%Bitmap{#{value}=#{bitmap}}”

but later in the text you say it outputs #Bitmap[…] (286 PDF, 278 print),
which does not match the implementation. You should probably have doctests for
your book ;-) I think the #Bitmap[…] notation is better, because you say
earlier in the text that inspect should give a representation starting with #
when it is not a valid literal.

2014-10-02
286278ERROR

again the format for the Bitmap inspect implementation in protocols/bitmap_algebra.exs
should read

concat([
“#Bitmap[”,


  1. “]”])

instead of

concat([
“%Bitmap{”,


  1. “}”])

(brackets instead of braces and # instead of %) The example Iex session on the
next page should reflect that as well.

2014-10-02
146TYPO

In the following piece “The app function is used to configure the contents of these suites. By default, this app function does nothing. ”

“app” should be “application” and by default it now starts the “:logger” app.

2014-10-02
285277ERROR

Inspect.Opts[] is deprecated and throws an error with Elixir 1.0. As far as I can see, the inspect function works just fine with the following signature:

def inspect(bitmap=%Bitmap{value: value}, _opts)

If we wanted to supply a default value we would now use a struct:

def inspect(bitmap=%Bitmap{value: value}, _opts = %Inspect.Opts{})

2014-10-02
286278ERROR

Inspect.Opts[] is deprecated, must be fixed here as well.

2014-10-02
293285ERROR

To illustrate the process, we’ll create a simple Erlang evaluator

should be

To illustrate the process, we’ll create a simple Elixir evaluator

2014-10-02
295287ERROR

Inside the listing “odds/eval/apps/evaluator/lib/evaluator.ex” which is meant to
be put inside a mix project, you have a trailing IO.inspect which I think can be
safely removed.

2014-10-02
25OK

An atom word is a sequence of letters, digits, underscores, and at-signs. It may end with an exclamation point or question mark. Running on iex this isn’t true for all cases. This might either be a bug in the implementation or an error in the book.

iex(24)> :var@2!
:var@2!
iex(25)> := :=
iex(26)> :===!

(SyntaxError) iex:26: syntax error before: ‘!’

2014-10-02The previous sentence says that it can be an atom word or an elixir operator. Only atom words can end !
46SUGGEST

On page 45, the book says “A pid is a reference to a local or remote process, and a port is a reference to a resource (typically external to the application) that you’ll be reading or writing.”

Yet on page 46, opening a file returns a pid. I used h(File.open) and it has a good explanation of while the file is returned as a pid.

{:ok, io_device} - the file has been opened in the requested mode.
io_device is actually the pid of the process which handles the file. This
process is linked to the process which originally opened the file. If any
process to which the io_device is linked terminates, the file will be
closed and the process itself will be terminated.

It is confusing to read the resources are returned as port only for the very first example to return a pid. Is a explanation in order?

2014-10-02I see no inconsistency.
51ERROR

iex(73)> a xor b

(RuntimeError) undefined function: xor/1

From elixir website
Elixir also provides three boolean operators: or, and and not

2014-10-02
21TYPO

Performance Implications of Immutability

“going top leave lots of old values” should be “going to leave lots of old values”

2014-10-02
178TYPO

‘bahviour’ I assume you meant behavior?

2015-12-30
32OK

arithmetic operators

I believe that rem and dev ar no operators (any more?).
Or am I doing something stupid in my iex?

2015-12-29See the next paragraph. It is called as a function.
298TYPO

These same benefits can aso apply to Elixir code. (aso -> also)

2015-12-31
303ERROR

There’s no need to manually remove Supervisor, since mix projects by default do not come with the supervisor.ex anymore.

2015-12-31
305OK

Last line: And so it goes ? Either incomplete sentence or missing punctation.

2015-12-31It's a Vonnegut reference :)
306TYPO

What happens if we change the call to Simple.count_atoms [[:a, :b], :c]?

This should be:

What happens if we change the call to NoSpecs.length_plus([:a, :b], :c)?

I think it might help to show the resulting code:

defmodule NoSpecs do
def length_plus_n(list, n) do
length(list) + n
end
def call_it do
length_plus_n([:a, :b], :c)
end end

2015-12-31
271TYPO

Thats what the fallback_to_any line does. -> That's what the fallback_to_any line does.

2015-12-30
2SUGGEST

Table of Contents looks terrible.

Previous versions show the chapters and topics well indented.

In this version, there is no indentation on .epub version.
(I’m using iBooks with Yosemite and Mavericks too.)

2016-07-03
73ERROR

The book has this example:

iex> l = List.zip([[1,2,3], [:a,:b,:c], [“cat”, “dog”]])
[{1, :a, “cat”}, {2, :b, “dog”}]
iex> List.unzip(l)
[[1, 2], [:a, :b], [“cat”, “dog”]]

…, but the unzip does not work. What could work is as follows:

iex(1)> l = List.zip([ [1,2,3], [:a,:b, :c], [“cat”, “dog”] ])
[{1, :a, “cat”}, {2, :b, “dog”}]
iex(2)> :lists.unzip3(l)
{[1, 2], [:a, :b], [“cat”, “dog”]}

or

iex(3)> l = List.zip([ [1,2,3], [:a,:b,:c] ])
iex(4)> :lists.unzip(l)
{[1, 2, 3], [:a, :b, :c]}

I’m using elixir 1.0.2, OSX 10.10. From what I can tell, List.unzip isn’t even defined:

iex(5)> h List.zip

def zip(list_of_lists)

Zips corresponding elements from each list in list_of_lists.

The zipping finishes as soon as any list terminates.

Examples

┃ iex> List.zip([[1, 2], [3, 4], [5, 6]])
┃ [{1, 3, 5}, {2, 4, 6}]

┃ iex> List.zip([[1, 2], [3], [5, 6]])
┃ [{1, 3, 5}]

iex(6)> h List.unzip
No documentation for List.unzip was found

2015-12-29
104TYPO

Under ‘Your Turn’: “… you wrote a span funtion”. Should be ‘function’ (missing c).

2015-12-29
104TYPO

Under “Here is a list of orders”, the last order id is 120. Should probably be 130, since the rest are in numerical order.

2015-12-29
124TYPO

Output from iex shows ‘true part’ with true formatted as a keyword and part formatted as regular code. It should be formatted like a string, i.e. with quotes and in italics.

127TYPO

Nitpicking: In snippet from control/case.ex, there are two spaces between ‘File.open(“case.ex”)’ and ‘do’, both in the code and the output. Should be just one space.

2015-12-29
135SUGGEST

I suggest a footnote or explanation stating that CLI == Command Line Interface, as some readers may not be familiar with the acronym. (And thus may wonder why the module is called that.)

2015-12-29I think my readers will be able to work this out :)
268TYPO

In “Implementing a Protocol”, You need to change iolist_to_binary to IO.iodata_to_binary, since that’s what is in the source code now and iolist_to_binary no longer exists.

2015-12-30
62OK

The example under “Using Head and Taill to Process a List” lists/mylist.exs reports this error when loaded into iex: can use only variables and \\\\ as arguments of bodyless clause

2015-12-29I don't see that error here.
155TYPO

When displaying Issues.CLI.process in iex, the first line of the output is printed in a normal typeface up until ‘project elixir’. The output is in italics from that point on.

182ERROR

The results you show for running $elixir fib.exs are:
[{37, 39088169}, {37, 39088169}, {37, 39088169}, {37, 39088169},
{37, 39088169}, {37, 39088169}]

Which would be the result of calculating the fibonacci value of 37 if fib(0) = 1. However, on page 180, you define it as
fib_calc(0), do: 0

which will give the results
[{37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}]

This might send some readers into a bit of confusion, since their results will different from the expected results in the book.

2015-12-30
90ERROR

Before using `Integer.is_even/1` twice in the example, you must `require Integer` in iex, or you get “ (CompileError) iex:16: you must require Integer before invoking the macro Integer.is_even/1”

2015-12-29
141ERROR

HTTPoison changed its `HTTPoison.get()` function in version 0.5.0 to return a tuple instead of a map. This change breaks the `Issues.GithubIssues.fetch()` code presented in the book. To shield myself from this breaking change, I had to provide as stricter version number constraint for HTTPoison in my `mix.exs` file:

~diff
diff —git a/mix.exs b/mix.exs
index c692d31..2eb46ce 100644
—- a/mix.exs
+ b/mix.exs
@@ –23,7 +23,7 @@ defmodule Issues.Mixfile do

defp deps do
[
- { :httpoison, “~> 0.4” }
+ { :httpoison, “~> 0.4.0” }
]
end
end
~

Hope that helps, cheers!

2015-12-30Good catch. I updated the example to work with 0.8.0
159ERROR

The “ex_doc” dependency alone isn’t enough for the `mix docs` command to succeed: it fails, complains about a missing Markdown processor. I had to add the suggested `{:earmark, “>= 0.0.0”}` line to my deps() function and then run `mix deps.get` in order for `mix docs` to work correctly.

2015-12-30
159SUGGEST

As of 2 August 2014, ex_doc is available as a Hex package and shows up in hex.pm, so installing it from GitHub (and that too from the master branch which might contain unstable code changes) isn’t really necessary.

2015-12-30
78OK

Broken reflink at end of second paragraph. Shows metadata for link rather than actual hyperlink.

I can't find this.
83ERROR

In the first paragraph of the subsection “Nested Accessors and Nonstructs”. I think Dave had his Ruby hat on here and where says “you can supply keys as symbols” he actually meant /s/symbol/atom.

2015-12-29
72TYPO

The footnote that links to the Erlang docs for format/2 has a “>” at the end: …erlang.org/doc/man/io.html#format-2>

Hah, the form doesn’t allow hyperlinks, so I had to drop the ‘http’ from the example :)

2015-12-29
64SUGGEST

The section on default parameters could use better examples.

To follow on from the ‘greeting’ example that’s in the book, you could have something simple like:

```
defmodule Greeter do
def greet(greeting \\\\ “Hello”, name) do
IO.puts(“#{greeting}, #{name}”)
end
end

iex(80)> Greeter.greet ‘Dave’
Hello, Dave
:ok
iex(81)> Greeter.greet ‘Hi there’, ‘Dave’
Hi there, Dave
:ok
```

You’ll still want a fuller example that shows how confusing the binding can be, and the existing p1, p2, p3, p4 one is good for that, I guess.

I only mention it because the book is really great so far, and this is the only part I’ve seen so far that felt phoned in. Nice work!

2015-12-29Thanks for the suggestion, but I think I'll leave it for now. I'm trying to keep things terse.
139ERROR

As printed: mix run -e ‘Issues.CLI.run([“-h”])’ will not work for me however: mix run -e “Issues.CLI.run([‘-h’])” does (note switched single/double quotes).

Elixir 1.0.2
Windows 8.1

2015-12-30That must be a Windows thing. I think you still need the double quotes round the -h, so I suspect the correct Windows fix would be to escape the outer quotes.
174SUGGEST

The spawn/link1.exs example on page 174 includes the line:

Process.flag(:trap_exit, true)

But that line is not needed in this example. It is later “revealed” in link3.exs where it makes the spawn_link call interesting

What I did was copy link1.exs to link2.exs then changed the spawn line without realizing I had to remove the Process.flag call in order to get the results shown for link2.exs

My suggestion is to simply remove the line from link1.exs

2015-12-30
177SUGGEST

Really, really, really pedantic…

In the monitor1.exs sample, the name of the “sad” routine changed from “sad_function” (in the linkx.exs samples) to “sad_method”.

Hazards of being an OO programmer I expect. My suggestion is to change it to sad_function like the others. (unless that would make it even more sad)

2015-12-30
177SUGGEST

In the command line used to run monitor1.exs the suggested line is:

$ elixir -r monitor1.exs -e Monitor1.run

However, because the last line of monitor1.exs also includes “Monitor1.run”, this causes the run function to be called twice.

I had a similar issue when working with the “link” examples from the previous sections where the suggestion was to call:

$ elixir -r link1.exs

but I had missed the trailing “Link1.run” lines when typing in the samples (so stuff didn’t work)

My suggestion would be to make these consistent across the board. Either include the code to invoke the function at the end and leave the “-e” option off the sample command line… or take the line that invokes the function off of the samples and add the “-e” line to all of them.

Which you choose is a matter of style I think.

2015-12-30
215SUGGEST

The “supervisor diagram” on this page looks very nice in the PDF. The same image in the ebook version (read in iBooks on a Mac) is pretty terrible. I would provide a screen shot if I could figure out how to do it.

I don’t know if the image on the ebook side can be improved, but it couldn’t hurt if it can.

272ERROR

On the page, when describing the way the code recognizes the construct ‘fifty[bit]’ it says that:


<> then looks for a module called Bitmap.Access and invokes its ‘access’ function, passing in the original value and the parameter between the square brackets.
——

It actually calls the function ‘get’ not ‘access’.

2015-12-30
138OK

At the bottom of the page, the example showcasing pattern matching has an error. A map is bound to the variable `dave`, but subsequent references to that map refer to it as `person`.

2015-12-30Actually, the code is correct. The %{state: } = person -> is a pattern match on the whole dave variable.
145TYPO

When convert_to_list_of_hashdicts is discused, it is unclear where the example is supposed to go. Only on page 148 does the reader figure out where that code should have been placed.

2015-12-30
159SUGGEST

While this suggestion has been reported before, it would be interesting to note the `only: :dev` deps option at this point. When I checked Hex for ex_doc (as others did), and noticed it was available there, I also checked the github project. The example docs suggest the following: `{:earmark, “~> 0.1”, only: :dev}, {:ex_doc, “~> 0.6”, only: :dev}` (since earmark is a good default choice and one is required to use ex_doc). Using the suggestion from the ex_doc GH project page worked like a charm.

2015-12-30
266ERROR

Using Elixir 1.0.2 here, and IO.ANSI.escape looks like it may no longer exist. IO.ANSI.format works just dandy, however.

2015-12-30
231TYPO

The link to the exercise Exercise: OTP-Applications-3 is broken resp. the exercise is not available.

269ERROR

The output of the example code on this page seems to be incorrect, and this may changed from a previous case before Elixir 1.0.2.

HashDict does not match `for: [List, Tuple, BitString]`, so it prints out false, not true.

elixir-lang.org /getting_started /16.html#16.1-protocols-and-structs talks about matching protocol impl for struct types, and using this, we can explicitly add HashDict to the list of matched types.

If I wanted to match `HashSet.new,HashDict.new, {}, and{foo: :bar}`, it looks like I’d have to write:

defimpl Collection, for: [Map,HashDict,HashSet] do
def is_collection?(_) do
:hashy_or_mappy
end
end

2015-12-30
276TYPO

This page has the following near the top.
>>>
IO.inspect fifty # => %Bitmap{50=0110010}
IO.inspect fifty, structs: false # => %{struct: Bitmap, value: 50}

Run this, and you’ll see
#Bitmap[50=0110010]
{Bitmap,50}
<<<

The “… and you’ll see” part is incorrect, while the example output trailing the iex prompt and command is correct.

2015-12-31
276ERROR

Bitmap.new(value: 12345678901234567890) does not work (likely changed by elixir 1.0.2 time-frame).

Standard struct type creation works, though: %Bitmap{value: 12345678901234567890} .

2015-12-31
281ERROR

binary_to_atom needs to change to String.to_atom in the example code

2015-12-31
98ERROR

The code for the Stream.open example using Stream.resource causes an error. It seems that instead of the line:
fn file ->
it needs to be: fn {:ok, pid}. IO.read cannot take in a tuple and throws an error unless just given the pid.

2015-12-29
290ERROR

The `raise` in the code example, which is used to re-raise the exception seems to now need to literally be Kernel.reraise/3 (although the /2 form should work too).

2015-12-31
104OK

LPRALL-M-7063:elixir lprall$ iex
Erlang/OTP 17 [erts-6.3] [source-f9282c6] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.0.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [ name: “Dave”, city: “Dallas”, likes: “Programming” ]
[name: “Dave”, city: “Dallas”, likes: “Programming”]
iex(2)>

Per the book, this should return a list of two-value tuples:
[ {:name, “Dave”}, {:city, “Dallas”}, {:likes, “Programming”} ]

Don’t know whether this has changed in the current version, but the behavior is different than described.

2015-12-29You're missing the three item term at the end: { :where, "Dallas", "TX"} \n \nThis will change the output formatting you're seeing
58OK

in iex 1.0.4 both “Elixir.IO” === IO and “Elixir.IO”.puts 123
now result in an error, so something has changed here in Elixirs internal processing.

2015-12-29I hate to do this, but it works for me on 1.2.
21OK

“divvied” should have been “divided”

2015-12-29"Divvied" is a word... :)
301TYPO

In the example output for the program tasks/anagrams.exs, the result is a 7-element list of anagrams for the word “organ.” My program returns 9 anagrams, and from my visual inspection that appears to be the correct result.

2015-12-31
143TYPO

Github’s issue_url is incorrect and returns a 404.
“api.github.com/#{user}/#{project}/issues” should actually be “api.github.com/repos/#{user}/#{project}/issues”

2015-12-30
162SUGGEST

The comparison output in the “Output is correct” test must include the trailing spaces. While the online file contains these trailing spaces, its not obvious from the listing in the PDF that the trailing spaces are required to be there.

2015-12-30
71OK

lists/weather.exs:

def test_data do [
[1366225622, 26, 15, 0.125],
[1366225622, 27, 15, 0.45],
[1366225622, 28, 21, 0.25],
[1366229222, 26, 19, 0.081],
[1366229222, 27, 17, 0.468],
[1366229222, 28, 15, 0.60],
[1366232822, 26, 22, 0.095],
[1366232822, 27, 21, 0.05],
[1366232822, 28, 24, 0.03],
[1366236422, 26, 17, 0.025]
]
end

This results in an error:
… undefined function test_data/0

I guess there should be brackets in the definition of ‘test_data’:
def test_data() do [

end

2015-12-29I don't see that issue here.
58SUGGEST

The word “in” in “ (ArithmeticError) bad argument in arithmetic expression” should not be highlighted, as it is output and not elixir code.

182TYPO

“In our case, we give it the same number, 37, ten times.”
The code above it only shows six 37s.

2015-12-30
82ERROR

The example “maps/derive.exs” doesn’t work.

The example code:

defmodule Attendee do
@derive Access
defstruct name: “”, over_18: false
end

The error:

(ArgumentError) Access is not a protocol, cannot derive Access for Attendee2
(elixir) lib/protocol.ex:76: Protocol.assert_protocol!/2
(elixir) lib/protocol.ex:591: Protocol.derive/5
(stdlib) lists.erl:1337: :lists.foreach/2
(elixir) lib/protocol.ex:579: Protocol.derive/3
test.exs:258: (module)

Elixir 1.1.1

2015-12-29
491ERROR

In OTP:Servers
> “The VM doesn’t hot-swap code until you explicitly access it by module name. So, to try our new functionality we’ll create a new server.”

In my test, when I have recompiled the Sequence.Server module by `r Sequence.Server`, I could immediately invoke GenServer.cast(pid, {:increment_number, 100}). It seems that the VM would hot-swap code automatically, so there is no need to start a new server.

24SUGGEST

“Atoms” section: A few pages down, while experimenting in iex with maps that have atoms as keys, I was getting an error about aliases. I had made state-abbreviation atoms like :MN and it turns out that atom names that start with a capital letter are “atom aliases.” Might be worth a mention when atoms are introduced on this page, that regular atoms should start lower-case?

2015-12-29
89SUGGEST

“Some of them share an additional trait: you can add things to them.”

Technically, this isn’t true. If data is indeed immutable in Elixir, you can never “add” something to another thing. You can construct a collection that is a union of both things, but that would be a new collection.

89SUGGEST

“Some of them share an additional trait: you can add things to them.”

Technically, this isn’t true. If data is indeed immutable in Elixir, you can never “add” something to another thing. You can construct a collection that is a union of both things, but that would be a new collection.

215SUGGEST

On line 4 of the start_link function of the Sequence.Supervisor module, we are passing “initial_number” to the Supervisor.start_link, but the init function ignores any passed arguments. Wondering if we can pass an empty list in the Supervisor.start_link. Thanks.

214ERROR

This is a comment about an example used in Managing Process State Across Restarts section. I am wondering if there is a flaw in using a pid of a stash process instead of a registered name. Let’s say the stash process crashes and gets restarted, the new process will have a new PID, but the sequence server will still reference the old one and the next time it crashes, it will try to communicate its state to the dead process. Am I missing something here? Thanks

29SUGGEST

Install hyperlink is outdated.

98TYPO

Enum.into IO.stream(:stdio, :line), IO.stream(:stdio, :line)

should be

Enum.into IO.stream(:stdio, :line), IO.stream(:stdout, :line)

34ERROR

Version of Book, Version 1.3, brandnew from 10/2017:

Code section down the page

[_,uid,gid] = Regex.run(~r/_lp:.*?:(\\d):(\\d)/, content)

should read:

[_,uid,gid] = Regex.run(~r/_lp:.*?:(\\d):(\\d)/m, content)

Modifier m was forgotten.

60ERROR

def changeset(model, params \\\\ :empty) do
model
|> cast(params, ~w(name username), [])
|> validate_length(:username, min: 1, max: 20)
end

:empty is no longer part of Phoenix, so I replaced it with %{}

My setup:
defp deps do
[{:phoenix, “~> 1.2.5”},
{:phoenix_pubsub, “~> 1.0”},
{:phoenix_ecto, “~> 3.0”},
{:postgrex, “>= 0.0.0”},
{:phoenix_html, “~> 2.6”},
{:phoenix_live_reload, “~> 1.0”, only: :dev},
{:gettext, “~> 0.11”},
{:cowboy, “~> 1.0”}]
end

203SUGGEST

In my opinion, this is a much clearer Chain example:

defmodule Chain do
def process(prev_pid) do
receive do
num ->
IO.puts “process ##{num} saying hi (#{inspect self()})”
send(prev_pid, num+1)
end
end

def create_processes(n) do
create_processes(self(), n)
end

def create_processes(prev_pid, 1) do
spawn(Chain, :process, [prev_pid])
end
def create_processes(prev_pid, n) do
pid = spawn(Chain, :process, [prev_pid])
create_processes(pid, n-1)
end

end

defmodule Test do
def go(n) do
last = Chain.create_processes(n)
send last, 1

receive do
n when is_integer(n) ->
“Count was: #{n}”
end

end

def timeit(n) do
:timer.tc(Test, :go, [n])
|> IO.inspect
end
end

Using the Enum.reduce() trick just servers to obfuscate the code. If you run the example above with n=10, you’ll see the output:

iex(3)> c “chain.exs”
[Test, Chain]

iex(4)> Test.go(10)
process #1 saying hi (#PID<0.108.0>)
process #2 saying hi (#PID<0.107.0>)
process #3 saying hi (#PID<0.106.0>)
process #4 saying hi (#PID<0.105.0>)
process #5 saying hi (#PID<0.104.0>)
process #6 saying hi (#PID<0.103.0>)
process #7 saying hi (#PID<0.102.0>)
process #8 saying hi (#PID<0.101.0>)
process #9 saying hi (#PID<0.100.0>)
process #10 saying hi (#PID<0.99.0>)
“Count was: 11”

The output is proof that the processes are being created. Who knows if the processes are actually being created in the book’s example?

Then, if you comment out the statement:

IO.puts “process ##{num} saying hi (#{inspect self()})”

you can run the timeit() function from the command line and see how long it takes to create n processes:

~/elixir_programs$ elixir -r chain.exs -e “Test.timeit(10)”
{1333, “Count was: 11”}

~/elixir_programs$ elixir -r chain.exs -e “Test.timeit(100)”
{1852, “Count was: 101”}

~/elixir_programs$ elixir -r chain.exs -e “Test.timeit(1_000)”
{12524, “Count was: 1001”}

~/elixir_programs$ elixir -r chain.exs -e “Test.timeit(10_000)”
{108247, “Count was: 10001”}

~/elixir_programs$ elixir -r chain.exs -e “Test.timeit(400_000)”

21:13:36.313 [error] Too many processes

(SystemLimitError) a system limit has been reached
:erlang.spawn(Chain, :process, [#PID<0.74.8>])
chain.exs:19: Chain.create_processes/2
chain.exs:28: Test.go/1
(stdlib) timer.erl:197: :timer.tc/3
chain.exs:39: Test.timeit/1
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:192: Code.eval_string/3

~/elixir_programs$ elixir —erl “+P 1000000” -r chain.exs -e “Test.timeit(400_000)”
{4011042, “Count was: 400001”}

~/elixir_programs$ elixir —erl “+P 1000000” -r chain.exs -e “Test.timeit(1_000_000)”
{9821899, “Count was: 1000001”}

If you are wondering why the count is always n+1, that also happens with the books example—it’s just that the book cheats and send()’s 0 to the last process. The chain example creates n processes — in addition to the main process — so there are n+1 total processes receiving a message.

Categories: