By Developers, For Developers
PDF Pg | Paper Pg | Type | Description | Fixed on | Comments |
---|---|---|---|---|---|
14 | TYPO | In the example following “Back to the match operator,” the result of `list = [ 1, 2, 3 ]` should be `[1, 2, 3]` rather than `[1, 2, 3, 4]` | 2016-08-10 | ||
4 | TYPO | In the Installing Elixir section it reads “This book assumes you’re using at least Elixir 1.2.”. I guess it should be 1.3? :) | 2016-08-10 | ||
89 | TYPO | s/amd/and/ | 2016-08-10 | ||
124 | TYPO | s/Trimss/Trims/ Trimss leading and trailing whitespace from str. | 2016-08-10 | ||
147 | TYPO | The paragraph describing version “~> 0.8” and minor version “8” should be referring to “~> 0.9” and “9”. | 2016-08-10 | ||
286 | OK | The “use/tracer.ex” code example shouldn’t have, use Tracer since the Tracer module hasn’t been defined. | 2016-08-10 | That's correct. The example code shows how I'd like to be able to use it. It won't run until it is implemented. \n \nI often write my code this was—write want I want, then implement the stuff to make it work. | |
31 | TYPO | There is a mention about equality between dates of different precision, however it looks like there is a copy-paste error and only a fragment of that sentence remains. “”" of seconds means that ~T[12:34:56.0] is not equal to ~T[12:34:56.00]. | 2016-08-10 | ||
172 | SUGGEST | Whe you click de hyperlink excheck. , it contains even the last point | 2016-08-10 | ||
5 | ERROR | In the output of the h/0 helper, it is missing the listings for c/1, nl/2, pid/1, and recompile/0. | 2016-08-19 | ||
6 | ERROR | The output from ‘h IO.puts’ has changed from what is in the book. | 2016-08-19 | ||
16 | TYPO | In the last paragraph, second sentence, s/with/the/. It should say, “But the second b corresponds to the value 2 on the right.” | 2016-08-19 | ||
125 | ERROR | The examples for String.trim/2 give examples with a codepoint as the `to_trim` parameter, however this should be “!” instead of ?! I believe. The result of running the code in 1.3 is: (FunctionClauseError) no function clause matching in String.replace_leading/3 | 2016-08-19 | ||
20 | SUGGEST | > There are several ways of exiting from iex—none are tidy. The easiest two are typing `Ctrl`-`C` twice or typing `Ctrl`-`G` followed by `q` and `Return`. You can also `Ctrl`-`\\` (Control-Backslash) which is quite a bit tidier :) | 2016-08-19 | ||
8 | TYPO | The link “[1]” that points the reader to the website where they can find the Source Code points to the old version 1.2 It should be pointing to the latest version (1.3). | 2016-08-19 | ||
182 | 172 | TYPO | Quote from book: “That’s where the property testing libraries come it.” I believe that “come it” is a typo; I expect that “come in” was the intended phrase. | 2016-08-19 | |
31 | TYPO | “However, they are currently little more that data holders” | 2016-09-22 | ||
115 | ERROR | “In addition, Elixir defines three additional sigils, ~D, ~T, and ~N” but these three were already mentioned in the list so “in addition” doesn’t feel right. | 2016-09-22 | ||
67 | OK | In your “How iex Displays Lists” box, I would suggest using at least 1 multibyte character in your example (where you use ‘cat’). This would clarify that the numeric values are truly code points and not single-byte values such as used in <<>> binaries. As a novice, I was asking myself are these really byte values in disguise, and, if so, how are multibyte characters handled. Using a multibyte character in the example would remove this ambiguity. Using a multibyte character might be a little more complicated for speakers of most western languages, but more precise, and more helpful for the rest of us. | 2016-09-22 | I don't think it does display multibytes as characters in a char list. | |
72 | SUGGEST | For consistency (unless there’s a reason I’m not aware of), I suggest standardizing the name to ‘fun’, ‘func’, or ‘fn’, everywhere you refer to it. Also, in the ‘reduce’ signature, as a reader I would prefer to see ‘func’ there rather than ’’ so I could know what it is that’s being ignored. | 2016-09-22 | ||
148 | OK | HTTPoison doesn’t return an `{:error` tuple with a second argument containing a map with a `:body` key but instead something like: `{:error, %HTTPoison.Error{id: nil, reason: :econnrefused}}`. This causes our error handler to not match: `(FunctionClauseError) no function clause matching in Issues.GitHubIssues.handle_response/1` | 2016-09-23 | It seems to work here... \n \n~~~ elixir \niex(2)> Issues.GithubIssues.fetch("elixir-lang99", "elixir") \n{:error, \n "{\\"message\\":\\"Not Found\\",\\"documentation_url\\":\\"https://developer.github.com/v3\\"}"} \n~~~ \n | |
150 | OK | `deps` originally declared (page 147) as a list of tuples: `[ {:httpoison, “~> 0.9” } ]` but when adding Poison (page 150), it’s switched to the keyword list shorthand: `[ httpoison: “~> 0.9”, poison: “~> 2.2” ]`. Should probably either mention the switch or be consistent. | 2016-09-23 | I kinda assumed that by the time we got here people would understand :) | |
85 | SUGGEST | The definition of the ‘may_attend_after_party’ function may be a good place to introduce the use of ‘?’ in a function name. IMHO it would be good to encourage the reader to name all methods returning boolean values with ‘?’ at the ends of their names, and doing so for all boolean methods in the book would make that clear (if that’s something you want to do). | 2016-09-22 | ||
93 | TYPO | “is just ordered group of values” should probably be something like “is just an ordered group of values”. | 2016-09-22 | ||
228 | TYPO | In “Move into the sequence direcory” | 2016-09-23 | ||
151 | ERROR | In decode_response({:error, error}), this code, “{_, message} = List.keyfind(error, ”message“, 0)” produced an error. | 2016-09-23 | ||
225 | TYPO | Within the ‘nested’ dictionary, the actor Cary Elwes’ last name is declared to be a typo (“#typo!”) when it is his first name that is a typo (“Cary”, not “Carey”). The last name is spelled correctly. This actual typo is carried through the rest of the chapter, where the first name “Carey” persists. On the following page the example for ‘put_in’ seems to suggest that the aforementioned “Elwes” non-typo is corrected with the code, when indeed this ‘correction’ is ineffectual as the last name was already spelled properly. | 2016-09-23 | ||
235 | TYPO | In the second paragraph, “For example, a primitive Elixir list is just ordered group of values” is missing an ‘an’: “For example, a primitive Elixir list is just an ordered group of values” | 2016-09-23 | ||
101 | 87 | TYPO | There is a typo of a typo. In the example map called nested the actor Carey Elwes name appears with a comment that there is a typo which will later be fixed. However the name is not spelled incorrectly. Later, when correcting the typo the name is again spelled properly. Thus it is confusing on the next page when put_in is used to correct the spelling. | 2016-09-22 | |
208 | TYPO | This is not strictly a typo, but the twin terminals shown in Chapter 16 (with one above the other) are not rendered properly in the Kindle version, while they are fine in PDF. No matter what font size or orientation is chosen the box is only about 10 characters wide, so it’s unreadable. | |||
191 | 180 | TYPO | Running processes exhibits ETS tables screenshot vice versa ETS tables exhibit on the next page shows processes. The screenshots got switched. | ||
127 | TYPO | After the list of sigil types is the following sentence: > In addition, Elixir defines three additional sigils, ~D, ~T, and ~N, which con- struct dates, times, and native datetimes respectively. The “in addition” part of this doesn’t really make sense as all three of those sigils are listed above this paragraph. | |||
89 | TYPO | After the call to function `get_and_update_in`, the output shows: %{actor: %{first: “Cary”, last: “EWES”}, …} It looks like an L was accidentally omitted from the actor’s last name; I believe this should be %{actor: %{first: “Cary”, last: “ELWES”}, …} | |||
44 | ERROR | I think there is an error in the pin operator example, in file functions/pin.exs. I am just learning the language, but I think the pin operator makes no difference in the function behaviour. When I remove it, it works exactly the same in both cases shown in the example. | |||
All | ERROR | Code is not indented properly on Kindle. | |||
32 | SUGGEST | When creating the new times on the previous page: iex(35)> t1 = Time.new(12, 34, 56) t1 is a tuple, while t2 is a time. If we compare t1 directly with t2, there are more reasons for the comparison to be false than the time difference that we’re trying to emphasize in this section. We can use a similar strategy as we had for dates, or otherwise even something like t1 == {:ok, t2} iex(37)> t1 == {:ok, t2} | |||
39 | SUGGEST | This could be considered either a suggestion or technical omission, but: “Exercise: Functions-1” on page 39 does not appear to have a corresponding downloadable solution…at least, if it does, I couldn’t find the corresponding code in the directory of provided solutions. Having to work-through to discover the right solution is helpful, but not if the answer remains elusive and there is no way to look at the correct solution—that simply derails momentum. So if some of the exercise examples don’t have corresponding solutions available, providing them would be really appreciated. Which leads to a second suggestion: It would be helpful if the downloadable directory of solutions had chapter numbers instead of (or in addition to) the named ones that currently exist. For example, the code shown on page 40 is found inside a directory called “first_steps”…only that name appears to have no connection with the“handle_open.exs” file found within it, nor the chapter (“Anonymous Functions”) in which the example code is cited. | |||
127 | TYPO | Exercise: StringsAndBinaries-7 says “Chapter 7 had an exercise about calculating sales tax on page 110.” The page number is correct (Exercise: ListsAndRecursion-8 is on page 110); however, it is in Chapter 10, not Chapter 7. | |||
546 | TYPO | The code sections, when viewed on the Kindle app on an iPad Pro, are formatted horribly: and extended bold serif font, indentation lost. Same pages look okay reading the mobi file on the Kindle Mac desktop app. | |||
p151 | ERROR | The code for `def decode_response({:error, error}) do` needs to be updated. As written, an errorful call to the github API will produce something like the following: (ArgumentError) argument error It can be fixed by changing the first line from {_, message} = List.keyfind(error, “message”, 0) to message = Map.get(error, “message”, 0) | |||
28 | ERROR |
Example is wrong. I verified in Elixir 1.2.7 and 1.3.4 that it actually works the opposite way as described in the book! ## Example of the book doesn’t have the described output Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help) ## The supposed output as described in the book generates the input used in the book Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help) | |||
28 | SUGGEST |
The book only mentions that “square” brackets can be left off, but the last code example on page 28 shows that “curly” brackets are left off too. I’m also struggling to understand what is happening. It looks: - a list ending with a keyword lists gets converted into a list of two-value tubles, where the first tuple element is now an atom | |||
29 | ERROR | Maps Syntax example seems to indicate that the “key” can be duplicated in a map. But this is not the case and the first value would be overwritten by the second one, something not described in the book, so I doubt this was the intention to be described. Better example: | |||
28 | ERROR | Keyword Lists I think I finally figured out what was supposed to happen in the last keyword list example. Wrong example from the book
List ending with a Keyword List
Tuple ending with a Keyword List
| |||
194 | TYPO | “It then exits with a status of 99.” | |||
191 | ERROR | The chain.exs example should exclude the `when is_integer(final_answer)` guard clause in the `create_process` function. The bug you linked to on GitHub has long been fixed (or rather disappeared on its own) and the code works correctly without the guarg clause. The related paragraph on the next page “Why do we need this, though? It turns out there’s a bug in some versions of Elixir. 1…” should be removed too. | |||
8 | TYPO | Compile and Run This reads very strange. I assume it should probably rather be: Once you get tired of writing … | |||
1 | SUGGEST | This may seem bizarre, but I’m a little concerned about the title of Chapter 1: “Take the Red Pill.” I appreciate the Matrix reference, especially given the introductions and the exhortation to the reader to take a leap of faith into Elixir. But, given events within and outside of the programming biosphere over the past year (Gamergate, the general rise of MRAs, Trump’s election, etc), the phrase “Red Pill” has been overwhelmingly co-opted by people whose voices loudly and openly seek a world less welcoming to those who are not, by and large, cis-gender, straight, white men. Is this perhaps overthinking the problem with 4 words in a chapter heading? Maybe. But I feel strongly that in a world where language is being ever more often deployed and misused as weaponry, every word and sentence counts. Is the tile of the chapter going to keep someone who picks up the book from reading further? Probably not. But it falls on us who would see the programming world become more open to make that path as welcoming as possible. Anyway, just a thought, perhaps overthunk. I’m a huge fan of this book and your others. | |||
83 | SUGGEST | Under “Updating a Map”, the last line reads: “However, this syntax will not add a new key to a map. To do this, you have to use the Map.put_new/3 function” Is it better to say Map.put considering Map.put_new is a for the case where you want to add a new entry only if that key doesn’t already exist? | |||
70 | SUGGEST | The motivation for the section “Keeping Track of Values During Recursion” is a bit misleading I believe. The opening paragraph suggests adding up the numbers in a list is a different problem to what we’ve seen so far, says that we need to keep track of the partial sum, and gives as pseudocode sum([]) -> 0 Then it is said that there is no way to keep track of that “total” and that gives place sum/2. Well, this introduction is not super clear I’d say, adding up a list of numbers is no different than what the book did in previous sections: defmodule MyList do and, the way things are worded, the reader could certainly interpret that is not the case. The section might be better motivated by talking about the stack, and introducing tail-call optimization. If this concept should be rather explained when the book is more advanced (on page 190 in this edition), then you could motivate the implementation as a technique to “carry” partial results, interesting by itself, to lead to reduce/3. Xavier PS: By the way, the book is really good, very well-written, enjoying it a lot. | |||
34 | ERROR | with-scope.exs does not seem to compile. I first tried entering it directly into iex and got ‘missing do keyword in with’. Tried to just compile the file with c and got: (MatchError) no match of right hand side value: nil Line 6 is the final line of the with before the do. | |||
145 | ERROR | Won’t Run = mix run -e ‘Issues.CLI.run([“-h”])’ Will Run = mix run -e “Issues.CLI.run([‘-h’])” Single verses double quotes for a char | |||
146 | ERROR | 1)- Won’t Run = mix run -e ‘Issues.CLI.run([“elixir-lang”, “elixir”])’ 2)- Will Run = mix run -e “Issues.CLI.run([‘elixir-lang’, ‘elixir’])” function Issues.GithubIssues.fetch/2 is undefined using windows 10 cmd as admin | |||
127 | TYPO | In the very last line of the page (the last line of the depicted file), the ID should be 130, not 120. That would be consistent with the example list of orders from the referenced earlier exercise. | |||
308 | ERROR | It seems like the mix.exs example is missing something to add LineSigil to the deps. | |||
73 | ERROR | The example for the exercise ListAndRecursion-3 shows an incorrect output: instead of ‘elixir’ it shows ? | |||
70% | TYPO | 18. OTP: Supervisors / Supervisors and Workers: >> Nothing looks different, but open lib/sequence.ex. should be: “Nothing looks different, but open lib/sequence/application.ex.” | |||
279 | SUGGEST | The last of chapter 21 says “Next we’ll look at protocols, a way of adding functionality to built-in code”, | |||
13 | TYPO | Second paragraph from the bottom, last sentence: “Elixir calls = the match operator.” I see two reasons to fix this. Firstly, I am not aware of multiple match operators in Elixir (I’d be interested to learn otherwise) so = is not “a” member of the group of “match operators,” it is instead “the” match operator. Secondly, the previous code example had used “a” as a variable name, and the next code example illustrates the fact that the variable “a” could fit on either side of the match operator, so seeing “= a” in the text can be slightly visually surprising. | |||
83 | SUGGEST | Updating a map Consider using Map.update for updating and inserting a new value in a map | |||
151 | ERROR | The decode_response({:error, error}) line apparently expects “error” to be a list since it calls List.keyfind on it. But it’s not a list, it’s a map and this generates an “ArgumentError”; the code download handles this properly with a simple: | |||
21 | 21 | TYPO | In the section Garbage Collection in chapter 2, line number 9 -> you have used ‘divved’ which I think should be ‘divided’ | ||
173 | ERROR | The github identifier for ‘triq’ is out-of-date. It is now: | |||
38 | TYPO | Omission of parentheses is stated as being possible within function definitions but not within expressions (As I understand) However, the examples given both seem to be assignments of function expressions and neither omits the use of parenthesis when being invoked:``` | |||
126 | TYPO | iex> String.valid? “∂og” # => true, not false as indicated on p. 126 | |||
74 | SUGGEST | In the section “Lists of Lists” I think more emphasis should be put on the fact that the readings are lists inside of a list, and not just in the heading of the section (“List of Lists”). This confused me at first when the “def for_location_27( [time, 27, temp, rain ] | tail) do” had brackets surrounding the readings variables. I didn’t realize the head WAS a list. So then I thought the book had made a mistake when saying you could summarize from what I thought was “def for_location_27( time, _, temp, rain, temp | tail) do” to “def for_location_27( _ | tail) do” which would be incorrect if the values were in a flattened list. This confused me enough that I thought I had seen a technical error in the book and wrote up the following below, so more clarification here would probably be useful to future readers….. (Not an accurate bug report but what I mistakenly thought, then caught:) There appears to be a technical error / bug for the WeatherHistory example on Page 74 of the printed book. Near the bottom of the page it says, “We could have written” then “for_location_27([ [ time, , temp, rain ] | tail])“. This would be the correct way to write the third line of the WeatherHistory example. The shortened solution provided, ”def for_location_27([ | tail), do: for_location_27(tail)” because, according to the book, “in reality we don’t care what is in the head at this point,” is wrong because you need to “read in” 4 data points at a time to prevent the recursion from accidentally reading in 27 in another column, say temperature. For instance, imagine if your test data was this: def test_data do Do you see the problem? The second line of data is read in like so: and the third row is effectively skipped, also. Note the above bug isn’t really there, I just thought it was because I was confused that this was a “list of lists”, which I feel wasn’t sufficiently emphasized in the section besides the section title which I didn’t notice, or didn’t notice the significance of. | |||
74 | SUGGEST | In the section “Lists of Lists” I think more emphasis should be put on the fact that the readings are lists inside of a list, and not just in the heading of the section (“List of Lists”). This confused me at first when the “def for_location_27( [time, 27, temp, rain ] | tail) do” had brackets surrounding the readings variables. I didn’t realize the head WAS a list. So then I thought the book had made a mistake when saying you could summarize from what I thought was “def for_location_27( time, _, temp, rain, temp | tail) do” to “def for_location_27( _ | tail) do” which would be incorrect if the values were in a flattened list. This confused me enough that I thought I had seen a technical error in the book and wrote up the following below, so more clarification here would probably be useful to future readers….. (Not an accurate bug report but what I mistakenly thought, then caught:) There appears to be a technical error / bug for the WeatherHistory example on Page 74 of the printed book. Near the bottom of the page it says, “We could have written” then “for_location_27([ [ time, , temp, rain ] | tail])“. This would be the correct way to write the third line of the WeatherHistory example. The shortened solution provided, ”def for_location_27([ | tail), do: for_location_27(tail)” because, according to the book, “in reality we don’t care what is in the head at this point,” is wrong because you need to “read in” 4 data points at a time to prevent the recursion from accidentally reading in 27 in another column, say temperature. For instance, imagine if your test data was this: def test_data do Do you see the problem? The second line of data is read in like so: and the third row is effectively skipped, also. Note the above bug isn’t really there, I just thought it was because I was confused that this was a “list of lists”, which I feel wasn’t sufficiently emphasized in the section besides the section title which I didn’t notice, or didn’t notice the significance of. - Austin Barnes | |||
302 | SUGGEST | Syntax highlighting of odds/line_sigil.exs is broken due to page break. | |||
230 | ERROR | Not an error for 1.3, but mixing a new supervisor has changed in 1.4 so the text will need to be updated for the next edition. | |||
142 | SUGGEST | defining the default count as a module attribute has a real disadvantage here, because later in the test, we can not import the attribute into our test, and have to hardcode `“4” in the test case. Sure, the attribute could be exported as a 0-arity function to the test, but wouldn’t it be simpler to just define it like this? def default_count, do: 1 and use it in the test like this: import Issues.CLI, only: [parse_args: 1, default_count: 0] | |||
156 | SUGGEST | instead of :io.format(format, fields) using ExPrintf might be a nice choice, as most people are familiar with sprintf formats | |||
208 | ERROR | On PDF page 208 it talks about how the file ~/.erlang.cookie contains the cookie / shared secret , It looks like 255 characters is the max length It might be a good idea to mention that | |||
125 | ERROR | iex> String.valid? “∂og” its wrong. On my iex it says true. |