We try to keep our books accurate, but sometimes mistakes creep
in. This page lists the errors submitted by our astute readers.
If you've found a new error, please
submit it.
The latest version of the book is P5.0,
released about 1 year ago.
If you've bought a PDF of the book and would like to upgrade
it to this version (for free), visit your
home page.
| PDF |
Paper |
Description |
Found in |
Fixed in |
| 23% |
|
#50212: During Day 2 of Io the reader is suddenly told to "Think of doMessage as somewhat like Ruby's eval". eval however was never mentioned any where in the Ruby section an far as I could see. Which can cause readers to stumble a bit. The explanation of what eval is follows in the next sentence, but it's a bit weird to suddenly learn eval first after you are told to think of something else as eval. #50212: During Day 2 of Io the reader is suddenly told to "Think of doMessage as somewhat like Ruby's eval". eval however was never mentioned any wher ...more...
|
P5.0
26-Nov-12
|
|
| 25 |
|
#50350: In the 3rd paragraph of the "I Won’t Be Your Programming Reference" section, "I will walk you through examples in each languages" should be "I will walk you through examples in each language".--Dan Parson #50350: In the 3rd paragraph of the "I Won’t Be Your Programming Reference" section, "I will walk you through examples in each languages" should be "I ...more...
|
P5.0
09-Dec-12
|
|
| 32 |
|
#50089: You list the "logical operators" | and & as behaving more or less like || and && but without shortcutting.
This is incorrect. | and & are the bitwise operators and the only reason they can behave somewhat like || and && in some circumstances is due to the specific types you have been comparing and how they have these operators implemented.
It is misleading not to specifically refer to these as the bitwise operators.--Oliver Hookins #50089: You list the "logical operators" | and & as behaving more or less like || and && but without shortcutting.
This is incorrect. | and & are t ...more...
|
P1.0
30-Oct-12
|
|
| 35 |
|
#50464: In the check out code of Duck Typing when discussing the type system the example
>>a = ['100', 100.0] returns ["100", 100.0] not ['100', 100.0]--IshtarIS
|
P5.0
13-Jan-13
|
|
| 43 |
|
#50102: You describe "methods that test" as those that end in a question mark. I think you can be clearer than that about this Ruby idiom.
Specifically, methods that are expected to return a boolean are expected to end in a question mark. You could probably combine the description to include both ideas - testing something and the expectation of a boolean return value.--Oliver Hookins #50102: You describe "methods that test" as those that end in a question mark. I think you can be clearer than that about this Ruby idiom.
Specific ...more...
|
P3.0
31-Oct-12
|
|
| 43 |
45 |
#49405: The attr keyword defines an instance variable. Several versions exist. The most common are attr (defining an instance variable and a method of the same name to access it)…
Presumably this should be attr_reader rather than attr?--Vincent Bray #49405: The attr keyword defines an instance variable. Several versions exist. The most common are attr (defining an instance variable and a method of ...more...
|
P5.0
04-Jun-12
|
|
| 44 |
|
#50080: In the Tree code example, visit_all method, it should say @children.each instead of children.each
|
P5.0
28-Oct-12
|
|
|
105 |
#48885: On fourth bullet (line 16) Tail2-2 must read Tail2-B, Tail2 must read Tail2-A--Norbert Müller
|
P3.0
04-Mar-12
|
|
|
131 |
#48887: The book translates some Scala to Ruby as:
args.each {|arg| println(arg)}
println isn't a Ruby function so it should be 'puts'--Nigel Lowry
|
P2.0
04-Mar-12
|
|
| 144 |
|
#49230: In section "Classes in Scala": class Person(firstName: String, lastName: String) doesn't result in a class with firstName and lastName attributes, as the text says. It merely results in a class whose constructor takes two arguments but doesn't do anything with them.
To get attributes, "val" must be added in from of the two parameters. Otherwise readers will be confused that they cannot access the supposed attributes if they experiment with the example:
scala> class Person(firstName: String, lastName: String)
defined class Person
scala> val gump = new Person("Forrest", "Gump")
gump: Person = Person@43900f17
scala> gump.firstName
<console>:10: error: value firstName is not a member of Person
gump.firstName
^
with val though:
scala> class Person(val firstName: String, val lastName: String)
defined class Person
scala> val gump = new Person("Forrest", "Gump")
gump: Person = Person@707cdc58
scala> gump.firstName
res1: String = Forrest--Robin #49230: In section "Classes in Scala": class Person(firstName: String, lastName: String) doesn't result in a class with firstName and lastName attribu ...more...
|
P5.0
29-Apr-12
|
|
| 148 |
|
#49231: In scala/employee.scala: Using "override val" for the name attribute in Employee is not necessary. It's easier to write it like this:
class Employee(name: String, val number: Int) extends Person(name) {
...
}
This results in the Employee constructor taking the names as an argument and passing it on to Person, where it will live as a field.
If you use override val, it results in an override of the public getter method, which is not necessary as Person already provides that.
The same thing for scala/nice.scala, this way is much better:
class Character(name: String) extends Person(name) with Nice--Robin #49231: In scala/employee.scala: Using "override val" for the name attribute in Employee is not necessary. It's easier to write it like this:
class ...more...
|
P5.0
29-Apr-12
|
|
| 148 |
|
#49232: In scala/employee.scala: "id():String" isn't recommended style, the colon should always be followed by a space. It's right most of the time, but it's not consistent (it looks unclean).
Other examples of missing space after colon is in scala/nice.scala, on page 151. Maybe other places, but I'm not yet as far :).--Robin #49232: In scala/employee.scala: "id():String" isn't recommended style, the colon should always be followed by a space. It's right most of the time, b ...more...
|
P5.0
29-Apr-12
|
|
|
150 |
#48929: In the description of the sort example it is said "that will yield a case-insensitive sort".
This is not true as the comparison is only performed on the first character of each word--Norbert Müller #48929: In the description of the sort example it is said "that will yield a case-insensitive sort".
This is not true as the comparison is only perfo ...more...
|
P3.0
11-Mar-12
|
|
|
152 |
#51341: (Note that the page# is a guess based on other submissions since I'm reading the Kindle version.)
Under "What We Learned in Day 2", in the fourth paragraph, the second sentence reads:
"We also used count, isEmpty, and first methods for obvious purposes."
I looked manually and searched via the search function, but could find no example of a method named "first" being used.--Glenn #51341: (Note that the page# is a guess based on other submissions since I'm reading the Kindle version.)
Under "What We Learned in Day 2", in the ...more...
|
P5.0
19-Apr-13
|
|
| 167 |
|
#49148: In the first paragraph of the Scala subsection titled "Concurrency" (bottom of the page numbered 167 on the page in the PDF --- my reader thinks it's page 163), you've a sentence "Often, the actor uses a pattern matcher to detect the message and perform the appropriate message." I think the last word should be "action". Also, "classify" might be more appropriate than "detect", but that's a minor preference.
Thanks for writing the book!--Conrad Hughes #49148: In the first paragraph of the Scala subsection titled "Concurrency" (bottom of the page numbered 167 on the page in the PDF --- my reader thin ...more...
|
P5.0
19-Apr-12
|
|
|
173 |
#49449: 4 + "string".
"Unlike Scala, there's no coercion between strings and ints."
Yes, but the example is misleading since + doesn't concatenate strings, e.g.
"4" + "string".
yields the same exception.--Jerry Morrison #49449: 4 + "string".
"Unlike Scala, there's no coercion between strings and ints."
Yes, but the example is misleading since + doesn't concate ...more...
|
P1.0
22-Jun-12
|
|
|
175 |
#49450: {comic_strip, {name, "Calvin and Hobbes"}, {character, "Spaceman Spiff"}}.
"We've represented a hash for a comic strip."
...
"If you are used to Ruby or Java-style hashes, it may seem strange to have the initial atom ..."
The code shows a way to represent key-value associations but I don't think there's any hashing going on here. The order of key-value pairs matters and a key may appear multiple times. Can it look up values by key?
The initial atom is a simple way to indicate type information (what Scala does with case classes) and indeed it doesn't fit the hash table concept.--Jerry Morrison #49450: {comic_strip, {name, "Calvin and Hobbes"}, {character, "Spaceman Spiff"}}.
"We've represented a hash for a comic strip."
...
"If you ar ...more...
|
P1.0
22-Jun-12
|
|
|
215 |
#49642: Section: Booleans and Expressions
(= 1 1.0) returns false in Clojure 1.3. Is that a language change? (== 1 1.0) does return true.--Jerry Morrison
|
P1.0
13-Aug-12
|
|
| 219 |
|
#50403: Clojure: Under the Booleans and Expressions section, you give an example of
(= 1 1.0)
and in the example, it evaluates to true. When I run the example on my machine, it evaluates to false. --Brad Cantin #50403: Clojure: Under the Booleans and Expressions section, you give an example of
(= 1 1.0)
and in the example, it evaluates to true. When I run ...more...
|
P5.0
21-Dec-12
|
|
| 232 |
|
#49000: In "you’ll define a higher-order function with the fn function", "higher-order" should be "anonymous". Using "fn" always defines an anonymous function which may or may not be higher order. Higher-order function may also be defined using "defn". In fact your example using fn is not higher-order.--art gittleman #49000: In "you’ll define a higher-order function with the fn function", "higher-order" should be "anonymous". Using "fn" always defines an anonymous ...more...
|
P5.0
27-Mar-12
|
|
|
235 |
#49643: Section: Infinite Sequences and take
Perhaps it's a language change in Clojure 1.3, but the fib-pair example as written gets an ArithmeticException integer overflow. Starting iterate with [1N 1N] gets it to happily use BigInt values.
BTW there's no need to map first over all the iterated values -- it's enough to take the first of the nth pair -- but maybe you wrote it that way to demonstrate that map works on infinite sequences.
Is it typical Clojure code to compute one more fibonacci number than needed vs. returning the second element of the previous fib-pair?--Jerry Morrison #49643: Section: Infinite Sequences and take
Perhaps it's a language change in Clojure 1.3, but the fib-pair example as written gets an ArithmeticE ...more...
|
P1.0
13-Aug-12
|
|
|
238 |
#48966: On line 4-5
(SomeType.arg) means fire the constructor for SimpleCompass, binding arg to the first parameter.
should be
(SomeType.arg) means fire the constructor for SomeType, binding arg to the first parameter.
--Norbert Müller #48966: On line 4-5
(SomeType.arg) means fire the constructor for SimpleCompass, binding arg to the first parameter.
should be
(SomeType.arg) m ...more...
|
P3.0
20-Mar-12
|
|
| 251 |
|
#49690: One of the titles used in "Working with Atoms" does not match. "Seven Languages" becomes "Seven Languages in Seven Weeks".
user=> (swap! top-sellers conj {:title "Seven Languages", :author "Tate"})
[{:title "Seven Languages in Seven Weeks", :author "Tate"}]
--Christophe Verre #49690: One of the titles used in "Working with Atoms" does not match. "Seven Languages" becomes "Seven Languages in Seven Weeks".
user=> (swap! to ...more...
|
P5.0
15-Aug-12
|
|
|
258 |
#50849: This page says:
"[...] if/then/else statement"
and later:
"In Haskell, if is a function"
Both are wrong -- 'if/then/else' is an expression with special syntactic support. --Matt Fenwick #50849: This page says:
"[...] if/then/else statement"
and later:
"In Haskell, if is a function"
Both are wrong -- 'if/then/else' is an e ...more...
|
P1.0
24-Feb-13
|
|
|
260 |
#50850: "[...] use the let function [...]"
let is not a function.
"in Haskell, let binds a variable to a function"
'function' should be replaced by 'value', as is shown in the following example.--Matt Fenwick #50850: "[...] use the let function [...]"
let is not a function.
"in Haskell, let binds a variable to a function"
'function' should be repla ...more...
|
P1.0
24-Feb-13
|
|
|
263 |
#48967: There is a discrepancy between the two implementations of the Fibonacci sequence on pages 262-263 of the UK edition.
The 1st fib implementation prints out the nth Fibonacci number like a zero based array (write out the 1st 10 numbers starting with a 0). For example fib 10 returns 89, which is the 11th Fibonacci number. The 'x' in the fibTuple is the correct fibonacci number though.--Tom Kealy #48967: There is a discrepancy between the two implementations of the Fibonacci sequence on pages 262-263 of the UK edition.
The 1st fib implement ...more...
|
P4.0
20-Mar-12
|
|
|
267 |
#50851: "Haskell includes first-class ranges and some syntactic sugar to support them"
Ranges are not first-class, they're just sugar for calls to functions from the Enum typeclass.--Matt Fenwick #50851: "Haskell includes first-class ranges and some syntactic sugar to support them"
Ranges are not first-class, they're just sugar for calls to ...more...
|
P1.0
24-Feb-13
|
|
|
276 |
#51522: Two issues [page 276-277]
The composition operator [pg276] is misused; "foo(bar x)" would be "(foo . bar) x". "(foo x).(bar x)" can be written "(foo <*> bar) x" using applicatives, but that goes beyond the scope of the section.
Second, the starter 'monad' example [pg277] is also applicitive functor-ish rather than monad-ish. '>>==' and 'rtn' are typed 'Position a -> Position a'; to be monadic they must be type 'a -> Position a'
Evaluation in a 'do' block is enforced by composition, but it is not the same as stringing functions together with the compose operator; if "(bar . foo) x" is valid for a monadic x, then the equivalent bind would be "return x >>= foo . return >>= bar . return".--Ryan Domigan #51522: Two issues [page 276-277]
The composition operator [pg276] is misused; "foo(bar x)" would be "(foo . bar) x". "(foo x).(bar x)" can be writt ...more...
|
P5.0
15-May-13
|
|
|
277 |
#50852: "f . g x" is not shorthand for "f (g x)".
Example: "sum . map (+1)" is a valid function. "sum (map (+1))" is a type error.--Matt Fenwick
|
P1.0
24-Feb-13
|
|
| 279 |
|
#49417: Instead of
"foldl1 (+) 0 [1 .. 3]"
it should either read
"foldl (+) 0 [1 .. 3]"
or
"foldl1 (+) [1 .. 3]"
Anyway, it might be a good idea to shortly discuss the difference between foldr/foldl and foldr1/foldl1 or leave out the latter version. IMO this difference is not related to the application of an operator, e.g. (+), in contrast to an anonymous function.--Kay-Uwe Kirstein #49417: Instead of
"foldl1 (+) 0 [1 .. 3]"
it should either read
"foldl (+) 0 [1 .. 3]"
or
"foldl1 (+) [1 .. 3]"
Anyway, it might be a good id ...more...
|
P5.0
08-Jun-12
|
|
|
282 |
#50853: at the top of the page:
"the types that each statement returns"
Those are expressions, not statements. Also, expressions do not return types.--Matt Fenwick
|
P1.0
24-Feb-13
|
|
|
282 |
#50855: "a string is an array of characters [...] represent the array of characters, with an array [...]"
s/array/list/--Matt Fenwick
|
P1.0
24-Feb-13
|
|
|
282 |
#50856: "That means that the type Boolean will have a single value, either True or False."
I think I get what this is saying, but it's confusing, and taken literally is wrong -- the type Boolean has two values.--Matt Fenwick #50856: "That means that the type Boolean will have a single value, either True or False."
I think I get what this is saying, but it's confusing, a ...more...
|
P1.0
24-Feb-13
|
|
|
283 |
#50854: At the top of the page:
"Suit and Rank are type constructors"
Suit and Rank are not type constructors -- they're types.--Matt Fenwick
|
P1.0
24-Feb-13
|
|
|
287 |
#50857: "You can also specify boilerplate implementations."
That should be 'default', not 'boilerplate'.--Matt Fenwick
|
P1.0
24-Feb-13
|
|
|
289 |
#50858: "Haskell allows us to chain let expressions together and express the final form in an in statement."
The example doesn't show chained let expressions -- it shows a single let expression.
There is no such thing as an 'in statement'. That is part of the syntax of let expressions.--Matt Fenwick #50858: "Haskell allows us to chain let expressions together and express the final form in an in statement."
The example doesn't show chained let e ...more...
|
P1.0
25-Feb-13
|
|
|
289 |
#50859: "Monads let you simulate program state."
Many monads have nothing to do with state. This seems to imply that monads are only/best for stateful patterns.
"do syntax allows programs in the imperative style."
'Do syntax' also allows non-imperative programs when working with other monads. Also, such programs can always be written without 'do syntax'.
A monad has "a type constructor that's based on some type of container."
(p. 290) "type that can hold a value"
Many people (myself included) find this intuitive explanation actually makes it harder to grok monads. The problem is that some monads act like containers, and some don't.--Matt Fenwick #50859: "Monads let you simulate program state."
Many monads have nothing to do with state. This seems to imply that monads are only/best for st ...more...
|
P1.0
25-Feb-13
|
|
|
290 |
#50861: "return wraps up a function into a monad"
'return :: Monad m => a -> m a'. It injects any value, not just functions, into the monad.
">>= unwraps a function"
Same thing.--Matt Fenwick #50861: "return wraps up a function into a monad"
'return :: Monad m => a -> m a'. It injects any value, not just functions, into the monad.
...more...
|
P1.0
25-Feb-13
|
|
|
291 |
#50860: As mentioned in the 2nd monad law, "m >>= return = m". However, both the treasureMap example on p. 291 and the last example on p. 294 make the mistake of using "m >>= return" instead of simply "m".
If return needs to be demonstrated, it should be a useful example.--Matt Fenwick #50860: As mentioned in the 2nd monad law, "m >>= return = m". However, both the treasureMap example on p. 291 and the last example on p. 294 make th ...more...
|
P1.0
25-Feb-13
|
|
|
294 |
#50862: Just is not a type. It is a function of type ':: a -> Maybe a'.
The examples at the top of the page are confusing. They should probably be:
Prelude> Just "some string" :: Maybe String
...
Prelude> Nothing :: Maybe String
...
This shows that there can either be a value or not. However, "Just Nothing" is of a totally different type than 'Just "some string"'.
"The bind is also easy. For Nothing, it returns a function returning Nothing. For Just x, it returns a function returning x."
The Maybe implementation of >>= does not return a function.--Matt Fenwick #50862: Just is not a type. It is a function of type ':: a -> Maybe a'.
The examples at the top of the page are confusing. They should probably b ...more...
|
P1.0
25-Feb-13
|
|
|
296 |
#50863: "The fully polymorphic template system"
The type system is not a template system. Although there is something separate and unrelated called Template Haskell.--Matt Fenwick #50863: "The fully polymorphic template system"
The type system is not a template system. Although there is something separate and unrelated cal ...more...
|
P1.0
25-Feb-13
|
|
|
296 |
#50864: Haskell's type system is referred to as 'strong' on this page and again on p. 298. It should be 'static'/'statically'.--Matt Fenwick
|
P1.0
25-Feb-13
|
|
| PDF |
Paper |
Description |
Found in |
Fixed in |
|
35 |
#48024: You say "... class will be much more difficult to debug because Ruby can no longer tell when a method is missing. We would definitely want strong error checking to make sure it was accepting valid Roman numerals."
But, adding a line such as
return super if (!name.to_s.match(/[IVXLC]+$/))
first thing in the method_missing definition, Ruby will be able to handle the missing methods just fine.
The problem of finding the definition of the methods remains, of course.
I'd personally strip the quoted lines from that paragraph and add them as an introduction to an exercise to find the return super if cannot_handle_method idiom.--Vinko #48024: You say "... class will be much more difficult to debug because Ruby can no longer tell when a method is missing. We would definitely want str ...more...
Bruce Tate says: Your design is better than mine. Perhaps in the next edition?
|
P3.0
23-Nov-11
|
|
| 42 |
|
#47508: Figure 2.1 is correct but to make it consistent with the code you show, the three blue boxes on the left should be moved down with the left arrow coming from Fixnum, not Numeric. Then add an Object box above Numeric with an up arrow showing the inheritance.--art gittleman #47508: Figure 2.1 is correct but to make it consistent with the code you show, the three blue boxes on the left should be moved down with the left ar ...more...
Bruce Tate says: Good catch. Changes like this are a little bit dangerous and expensive, so I am going to live with this problem and fix it in the next edition, ok?
|
P3.0
05-Sep-11
|
|
| 92 |
|
#47649: In the chapters about Prolog, tuples and list are mentioned.
1. Prolog does not have a real tuple type, and especially not a constant access one.
2. It is not true that lists and tuples are "containers" respectively of variable and fixed size.
In Prolog there is a binary left associative term constructor ,/2 which is what is used to build things which look as tuples:
?- (1, (2, (3, 4))) = (1, 2, 3, 4).
true.
?- (((1, 2), 3), 4) = (1, 2, 3, 4).
false.
In fact, what looks like a tuple is simply a nested term, not different from lists. Things are slightly more complicated as there is a ,/2 predicate which represents the logical conjunction of two predicates:
?- (true, false).
false.
?- (true, true).
true.
The list functor is '.'.
?- .(3, []) = [3].
true.
The usual [...] syntax is just syntactic sugar.
Essentially a list is not a "mutable size container" (lists are essentially immutable[0]).
It is just a cons list, like in Scheme. Simply the pair constructor is . and not cons.
?- ','(3, 4) = (3, 4).
true.
The 'term' syntax can be used essentially to bypass usual precedence rules which would make the desugared version ,(3, 4) a syntax error.
Since in Prolog it is possible to use any functor (including ',') to build terms of arbitrary arity, it is correct to write:
?- X = ','(3, 4, 5).
X = ','(3, 4, 5).
However, that is *not* a tuple type:
?- ','(3, 4, 5) = (3, 4, 5).
false.
Because (1, (2, (3, 4))) = (1, 2, 3, 4).
----
[0] In some sense it can be "modified" because if we have variables we can "extend" the list through unification if the last term is a variable
(this is also the basis for difference lists). Same applies to tuples, though.
?- (1, A) = (1, 2, 3).
A = (2, 3).
--Enrico Franchi #47649: In the chapters about Prolog, tuples and list are mentioned.
1. Prolog does not have a real tuple type, and especially not a constant acce ...more...
Bruce Tate says: Ah... the danger of writing about a language that is relatively new to me. Unfortunately, this error is pervasive in the chapter, and pretty difficult to fix at this stage. I am going to have to wait until the next edition.
Thanks for the catch, and sorry for the error.
|
P4.0
27-Sep-11
|
|
| 171 |
|
#48059: The Fibonacci sequence is defined with the 0th element as 0. The definition on page 171, as another_fib, starts with the 0th element as 1.--Tyler Bindon
Bruce Tate says: You're right, of course. I'm not going to change it here, as the intention is clear enough and I would be likely to inject more errors in the manuscript by fixing the problem.
I am going to wait for the next edition to fix this one, ok?
|
P4.0
28-Nov-11
|
|
| 193 |
|
#47401: Immediately after mentioning Erlang is tail recursion optimized, two recursive examples are given - factorial and fibonacci. But neither of them are implemented in a tail recursive fashion. This could be confusing. --Martin Leech #47401: Immediately after mentioning Erlang is tail recursion optimized, two recursive examples are given - factorial and fibonacci. But neither of th ...more...
Bruce Tate says: Good catch. I will revise these in next edition, ok?
|
P3.0
17-Aug-11
|
|
| 239 |
|
#48034: In Hackers and Painters, Graham chronicles a start-up that leveraged produc- tivity with Lisp to achieve productivity that no other vendors could match.
should probably be:
In Hackers and Painters, Graham chronicles a start-up that leveraged Lisp to achieve productivity that no other vendors could match.--Julian Ceipek #48034: In Hackers and Painters, Graham chronicles a start-up that leveraged produc- tivity with Lisp to achieve productivity that no other vendors co ...more...
Bruce Tate says: Good suggestion. Will consider for next edition.
|
P4.0
25-Nov-11
|
|
| 250 |
|
#48060: The Fibonacci sequence is defined with the 0th element as 0. The definition on page 250, as fib, starts with the 0th element as 1. This gives different results from the alternative definition on page 251 where the 0th element is 0.--Tyler Bindon #48060: The Fibonacci sequence is defined with the 0th element as 0. The definition on page 250, as fib, starts with the 0th element as 1. This gives ...more...
Bruce Tate says: Good catch, but I think the intent is clear, and don't want to risk turning a small problem into a bigger one. Will consider for the next release. Thanks for finding this one.
|
P4.0
28-Nov-11
|
|