The Artima Developer Community


Errata for Programming in Scala
Chapter: All
Return to errata index.

Page 0 (PDF page 0):
Right at the top, under 6.1, it says:
"A rational number is a number that can be expressed as a ratio n/d,
where null and null are integers, except that null cannot be zero. null
is called the numerator and null the denominator."
I don't believe the "null"s here are intended ;)

[FIXED (Thanks!)]
Page na (PDF page 0):
In the HTML version
(http://www.artima.com/pins1ed/functional-objects.html) I can read in the
first sentence:

A rational number is a number that can be expressed as a ratio n/d, where
null and null are integers, except that null cannot be zero. null is
called the numerator and null the denominator. 

Please correct the "null".

Thank you

[FIXED (Thanks!)]
Page 8 (PDF page 46):
The end of the 4th sentence of the 2nd paragraph reads:

"... and sends the result back to the requester using the message send
requester ! sum."

It should read:

"... and sends the result back to the requester using the message send
requester ! c
Page 19 (PDF page 55):
Section 1.4, Paragraph 3, Sentence 2:
"Scala programs often look a bit like programs written in a dynamically
typeddynamic!typing scripting language."
I guess should be:
"Scala programs often look a bit like programs written in a dynamically
typed scripting language."

[FIXED]
Page 48 (PDF page 82):
"Both mutable and immutable sets offer a + method, but their behavior
differs. Whereas a mutable set will add the element to itself, an
immutable
set will create and return a new set with the element added."

This statement is incorrect, + semantics does not change. Example below:

import scala.collection.mutable.Set

val first = Set("A", "B")
val second = first + "C"
println(first)
println(second)

"first" set is not altered.
Page 45 (PDF page 89):
execute thrill.sort((s,t)=> s.charAt(0).toLower< t.charAt(0).toLower) 
gives 
"error: value sort is not a member of List[String]"

should use method "sortWith"
Page 55 (PDF page 89):
Listing 3.10 works in Scala 2.7, not in 2.8. Here are the necessary
changes:
import scala.io.Source

if (args.length > 0) {
  // Changes: fromFile now requires a file, not a String; use fromPath
  //          getLines must be getLines()
  //          newline not returned; use println instead of print
  for (line <- Source.fromPath(args(0)).getLines())
    println(line.length + " " + line)
  println()
}
else
  Console.err.println("Please enter filename")
Page 55 (PDF page 99):
(Based on the Safari version)

The code in listing 3.10 works as-is in Scala 2.9, and the existing
erratum for this page is misleading. Source.fromPath() appears to have
been removed, and Source.fromFile() accepts a single string argument.
Page 57 (PDF page 101):
Code listed in 3.10 and 3.11 does prints the file in a singleline, and
not as specified in the example in the book. 
The 
print(padding + line.length + " | "+ line)
should be 
println(padding + line.length + " | "+ line)
Page 74 (PDF page 108):
Table 5.1: String is shown as a "Value type" in the table, although
String is a reference type as correctly shown on page 207, Figure 11.1.

=> String should be removed from that table.
Page 71 (PDF page 109):
The Application trait used in Listing 4.4 has been deprecated in 2.9.0
and is no longer available in 2.11.6 (can't find the exact release it was
removed in). 

object FallWinterSpringSummer extends Application {

should now be

object FallWinterSpringSummer extends App {
Page 92 (PDF page 126):
Last paragraph - "So if b is an expression..." should read "So if a is an
expression..." (a, not b).

FIXED
Page 93 (PDF page 127):
Last sentence of section 5.8: ...code<insert space>!
Page 102 (PDF page 146):
The lessThan method will yield the wrong result if exactly one of the
denominators is negative.
Page 117 (PDF page 151):
gcdLoop should work like gcd in
Listings 6.3, 6.5, 7.4
-- `exchange' parameters x and y.

def gcdLoop(x: Long, y: Long): Long = {
  var a = x
  var b = y
  while (b != 0) {
    val temp = b
    b = a % b
    a = temp
  }
  a
}
Page 111 (PDF page 155):
In listing 6.5, the add (+) and subtraction (-) method definitions where
the parameter is an Int, it occurs to me that in keeping with DRY might
be better written as:

def + (i: Int): Rational = this + new Rational(i)

and

def - (i: Int): Rational = this - new Rational(i)
Page 124 (PDF page 158):
Listing 7.9
Add a semicolon after "line <- fileLines(file)".
Page 125 (PDF page 159):
Listing 7.10
Add a semicolon after "line <- fileLines(file)".
Page 125 (PDF page 159):
Second paragraph:
Replace "For each of these it generates an Iterator[String]..." by "For
each of these it generates an List[String]...".
Remove the following sentence ("An Iterator offers...").
Replace "This initial iterator is transformed into another
Iterator[String]..." by "This initial list is transformed into another
List[String]...".
Page 132 (PDF page 166):
Listing 7.16 · Looping without break or continue.
Will yield the wrong index. The statement
i = i + 1
is executed even if the string is found. It should be
if (!foundIt) i = i + 1
Page 132 (PDF page 166):
The while loop in Listing 7.16 should not increase the i var when foundIt
== true. Otherwise, the value of i would always be 1 more than in the
example in Listing 7.15.

Great book btw, thanks.
Page 124 (PDF page 168):
Some users reported an error in the listing 7.9 (pag. 124) that in my
opinion it is not an error.

The user says to add a semicolon at the end of
"line <- fileLines(file)"

Why that? We are using curly braces, not parenthesis, so the semicolon is
not needed! 
If not, I think we have to review the rules of the semicolon inference
(see chapter 4.2)

To be honest I did not test that code, but from what it is written in the
book, I think the example it is correct.

Please let me know
Page 124 (PDF page 168):
It is written "To do so, you prefix the body of the for expression by the
keyword yield"
I think it is wrong the word 'prefix', because the keyword 'yield' is the
at the end of the body, not before (postfix)
Page 125 (PDF page 169):
Page 125 Listing 7.10
The code is unsafe. A better solution is to add another if clause
"file.isFile" to check that there is a non-file type in the filesHere
list before getting the lines for the file in the fileList.  

I found this bug when I was testing printScalaFiles2() and
printScalaFiles3() to see if they were functionally different.  My test
was to add a directory named test.dir.scala.  Then I ran the sample code
in Files.scala that is on the web for this book.  I get a the error:

java.io.FileNotFoundException: ./test.dir.scala (Is a directory)

I spent time trying to figure this out, fixing/documenting it would be
cool so others do not run into the same problem.

The safe/correct code is:

  val forLineLengths =
    for {
      file <- filesHere
      if file.isFile
      if file.getName.endsWith(".scala")
      line <- fileLines(file)
      trimmed = line.trim
      if trimmed.matches(".*for.*")  
    } yield trimmed.length
Page 125 (PDF page 169):
Mmm, I just filed an errata request to add an if clause for "file.isFile"
on the listing 7.10 "val forLineLengths".  But, it just dawned on me that
the same "if file.isFile" clause is needed on listing 7.8 and and listing
7.9.  Seems like it should be standard operating procedure for this type
of algorithm.  Which also implies there should be a file-only access
method in java.io.File...  Perhaps
have.io.File(<dirName>).listFiles.isFiles access method...
Page 141 (PDF page 175):
Section 8.2, Paragraph 2, Sentence 2:
"In the interpreter this not so much of a problem, [...]"

I guess that should be:
"In the interpreter this _IS_ not so much of a problem, [...]"

FIXED
Page 141 (PDF page 175):
Section 8.2, example:
To produce the same output as Listing 8.1 the line:

print(filename + ": " + line)

should be changed to:

print(filename + ": " + line.trim)
Page 147 (PDF page 181):
Ch.8 Functions and Closures, p.147 [pdf 181], top line
replace "at most once" by "exactly once"
(appear implies at least once)
Page 148 (PDF page 182):
typo:
    in which an underscore used to represent
->  in which an underscore is used to represent

FIXED
Page 162 (PDF page 195):
First paragraph, last line: replace "FilesMatcher" by "FileMatcher".

FIXED
Page 187 (PDF page 219):
Listing 10.6 should be

class LineElement(s: String) extends ArrayElement(Array(s)) {
  override val width = s.length
  override val height = 1
}

It uses def instead of val which gives the following compiler error:

LineElement.scala:2: error: overriding value width in class Element of
type Int;
 method width needs to be a stable, immutable value
  override def width = s.length
               ^
LineElement.scala:3: error: overriding value height in class Element of
type Int;
 method height needs to be a stable, immutable value
  override def height = 1
Page 190 (PDF page 222):
In the implementation of the class `UniformElement',
  private val line = ch.toString * width
should really be
  private def line = ch.toString * width

Otherwise, the code can compile, but will throw a
 java.lang.ExceptionInInitializerError
 Caused by: java.lang.NullPointerException

Tested at Debian Squeeze, with Scala version 2.7.7final
Page 184 (PDF page 222):
class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private val line = ch.toString * width
def contents = Array.make(height, line)
}

Array does not have a make method (scala 2.10.0-RC2. I'm using ItelliJ
and this is syntax highlighted as unknown and I can't find it in the
documentation
Page 191 (PDF page 223):
2nd, 3rd line: Replace "We'll override demo in in ArrayElement..." by
"We'll override demo in ArrayElement...".

FIXED
Page 194 (PDF page 235):
class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private val line = ch.toString * width
def contents = Array.make(height, line)
}

Array.make(height, line) can be replaced with
Array.fill(height)(Line)
Page 199 (PDF page 237):
I'm reading the chinese version of Programming in Scala 2 Edition so I'm
not sure about the real page number in english version.
In chapter 16.6, Reverse List, the following method
def rev[T](xs: List[T]): List[T] = xs mathch {
  case List() => xs
  case x :: xs1 => rev(xs1) ::: List(x)
}
The book says the complexity of this method is
  n + (n-1) + ... + 1 = (1+n)*n/2
I think rev on list of length 1 needs only one 'append' step,
rev on list of length 2 needs 2 steps(one more than rev on list of length
1),
rev on list of length 3 needs 3 steps(one more than rev on list of length
2),
...
...
so rev on list of length n needs n steps(one more than rev on list of
length n-1) and there is no duplicate invocation on each length of
sub-list.
I have also modified the previous method to prove that the complexity is
n :
var countOfAppend = 0
def rev[T](xs: List[T]): List[T] = xs mathch {
  case List() => xs
  case x :: xs1 =>
    countOfAppend += 1
    rev(xs1) ::: List(x)
}
If I test the following code:
val list = 1 :: 2 :: 3 :: 4 :: 5:: Nil
rev(list)
then I will get countOfAppend of 5(not 15), am I wrong?
Page 214 (PDF page 246):
It says: ..."For example, given a trait HasLegs, you could mix both
Philsophical and HasLegs"
It should say: ..."For example, given a trait HasLegs, you could mix
both Philosophical and HasLegs"

Sorry - missed the book version just now

[FIXED]
Page 215 (PDF page 247):
It says: ..."Frog still mixes in trait Philosophize,"...
It should say: ..."Frog still mixes in trait Philosophical,"...

FIXED
Page 209 (PDF page 250):
The code listing under Section 11.1 reads `def ##: Int`.  It should read:
`final def ##: Int`.
Page 210 (PDF page 251):
Footnote 1 reads: "The only cases where == is does not directly...". The
word 'is' appears to have wrongfully remained after a rephrasing.
Page 224 (PDF page 265):
The source:

def < (that: Rational) = 
    this.numer * that.denom > that.numer * this.denom

should be:

def < (that: Rational) = 
    this.numer * that.denom < that.numer * this.denom

i.e. less than.

Kind Regards,
Thomas
Page 247 (PDF page 278):
In the second sentence, the method name "canGetHome" in class Rocket
should be "canGoHomeAgain".

FIXED
Page 245 (PDF page 285):
It states on p245:

"...import the normal Java date class as simply Date..."

Shouldn't it be SDate?

If we do as suggested; eg:

import java.sql.{Date => SDate}

and add a method to a class; eg:

def sql(date: String) : Date = { Date.valueOf(date) }

we will get a compiler error.

However, if we use SDate the compiler is happy:

def sql(date: String) : SDate = { SDate.valueOf(date) }


PS. I find the inclusion of:

import java.sql.{Date => SDate}

in the text redundant as it adds nothing to the previous example of:

import Fruits.{Apple=>McIntosh,Orange}

after reading this example we now the => mapping syntax.
Page 261 (PDF page 291):
line 8 with > which

FIXED
Page 261 (PDF page 291):
l.8 JAR files from with to load
-->                which

FIXED
Page 260 (PDF page 300):
import junit.framework.TestCase
    import junit.framework.Assert.assertEquals
    import junit.framework.Assert.fail
    import Element.elem
    class ElementTestCase extends TestCase {
      def testUniformElement() {
        val ele = elem('x', 2, 3)
        assertEquals(2, ele.width)
        assertEquals(3, ele.height)
        try {
          elem('x', -2, 3)
          fail()
        }
        catch {
          case e: IllegalArgumentException => // expected
        }
      }
    }
The IllegalArgumentException will never be raised(there are no illegal
argument) but // expected comment can make people confused.
Page 270 (PDF page 300):
l.1 The default cases uses
-->             case

FIXED
Page 271 (PDF page 301):
Index / Ch.15 Case Clases and Pattern Matching, p.271 [pdf 301]: 
to index entry for "`(backtick)" add "in constants, 271"

DONE
Page 273 (PDF page 303):
A very little mistake:
"You can use a typed pattern as a a". The 'a' is written twice

FIXED
Page 277 (PDF page 307):
the '@'-sign entry in the index should include variable binding as a
sub-entry

DONE
Page 288 (PDF page 318):
Divisions such as "x / (x + 1)"

FIXED
Page 280 (PDF page 320):
It states at the bottom of p280:

"The operators isInstanceOf and asInstanceOf are treated as predefined
methods of class Any..."

Looking at the ScalDoc I see that isInstanceOf and asInstanceOf ARE
methods of Any.

Thus, I would rewrite the above as:

"The operators isInstanceOf and asInstanceOf are predefined methods of
class Any..."

The use of "treated" suggests alias/synonym.
Page 278 (PDF page 325):
At the bottom:

case s: String if s(0) == 'a' => ...

will throw a StringIndexOutOfBoundsException if s == ""
Page 300 (PDF page 330):
in the last paragraph: "a, b andc" -> "a, b and c"

FIXED
Page 322 (PDF page 352):
First line: "1, 2, 3@" -> "1, 2, 3"

FIXED
Page 338 (PDF page 368):
mutaSet: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

Not Set(3,2,1).
Page 347 (PDF page 377):
Expected:
capital ++= List(...

Actual:
capital ++ List(...
Page 347 (PDF page 378):
6th line: Paris is the capital of France (not France is the capital of
Paris)

FIXED
Page 361 (PDF page 391):
Ch.18 Stateful Objects, p.361 [pdf 391], Listing 18.4
replace "... var m = 12" by "... var m = 0"

FIXED
Page 378 (PDF page 408):
Bottom of the page:
Replace simulator.BasicCircuitSimulation$Wire with
BasicCircuitSimulation$Wire 4 times.

FIXED
Page 404 (PDF page 433):
Last paragraph:
"... a sort function that takes advantage OF the Ordered trait."

FIXED
Page 408 (PDF page 436):
Last line:
"... main use of type members IS TO declare ..."

FIXED
Page 403 (PDF page 441):
"Because the result type of a Function1 is defined as covariant, the
inheritance relationship of the two result types, shown at the right of
the diagram, is in the same direction as that of the two [function types]
shown in the center. By contrast, because the parameter type of a
Function1 is defined as contravariant, the inheritance relationship of
the two parameter types, shown at the left of the diagram, is in the
opposite direction as that of the two [function types]."
Page 444 (PDF page 480):
The book says:

> ... and the fact that the argument is an `ActionListener` are all
implied ...

It should read:

> ... and the fact that the argument is an `ActionEvent` are all implied
...
Page 454 (PDF page 482):
1st and 2nd paragraph: text contains repeatedly ‘ordered’ instead of
‘orderer’ (as in program)

FIXED
Page 482 (PDF page 509):
l.-2/-3 generators that that bind
-->                   that

FIXED
Page 482 (PDF page 509):
Line 5:
Replace "The next case handles for expressions that statrt with two
filters..." with "The next case handles for expressions that statrt with
two generators...".

FIXED
Page 483 (PDF page 510):
First paragraph, second expression: expr should be replaced by expr1.

FIXED
Page 491 (PDF page 518):
object EMail extends (String, String) => String { ... }

does not compile.  It apparently needs to be

object EMail extends ((String, String) => String) { ... }

FIXED
Page 481 (PDF page 519):
"In that case, you need to abort that part of the search in order to
continue with a different configuration of queens in [rows] 1 to k−1."
Page 483 (PDF page 521):
l.9 expr.map { case
--> expr_1.map

FIXED (see it in 3rd printing)
Page 487 (PDF page 525):
"
for (x <- expr_1 if expr_2; seq) yield expr_3
is translated to
for (x <- expr_1 withFilter (x => expr_2); seq) yield expr_3
"

( "expr_2" is replaced by "(x => expr_2)". )
Page 515 (PDF page 541):
Section 26.3

Says: The compile will go into an XML-input mode ...

Should say: The compiler will go into an XML-input mode ...

FIXED
Page 506 (PDF page 544):
In chapter 24:

"xs.zipWithIndex: An iterable of pairs of elements from xs with
their [indicies]"
Page 510 (PDF page 548):
"xs.lengthCompare ys: Returns -1 if xs is shorter than ys, +1 if it is
longer, and 0 is they have the same length. Works even if one [of] the
sequences is infinite."
Page 523 (PDF page 549):
2nd line of last paragraph:
Replace "...of a a single..." with "...of a single...".

FIXED
Page 518 (PDF page 556):
"Or you can leave out the ordering argument but give an element type [of]
the empty set."
Page 519 (PDF page 557):
footnote 3: "Immutable bit sets of elements in the range of 0 to 127
optimize the array away and store the bits directly in [] one or two Long
fields."
Page 524 (PDF page 562):
"You could also have implemented cachedF directly, using just basic map
operations, but it would { have have } taken more code to do so: [...]"
Page 555 (PDF page 567):
Typo end of third paragraph:
  "as shown in and Listing" -> "as shown in Listing"

FIXED
Page 530 (PDF page 568):
"A push on an immutable stack is the same as a :: on a list, and a pop on
a stack is the same [as] a tail on a list."
Page 540 (PDF page 578):
"[On] the one hand, Scala arrays correspond one-to-one to Java arrays.
That is, a Scala array Array[Int] is represented as a Java int[], an
Array[Double] is represented as a Java double[] and an Array[String] is
represented as a Java String[]. But at the same time, Scala arrays offer
much more [than] their Java analogues."
Page 554 (PDF page 579):
(Section 28.2)

Says: For p it is Point, whereas for pAnon it is an anonymous class of
Point.

Should say: For p it is Point, whereas for pAnon it is an anonymous
subclass of Point.

FIXED
Page 561 (PDF page 586):
l.-8 all, Branch[_] is a technically a type
-->  all, Branch[_] is   technically a type

FIXED
Page 567 (PDF page 592):
advice about taking elements of array into account when calculating hash
code seems to contradict earlier advice about not basing a hash code on
mutables (done indirectly here)

THAT'S A GOOD POINT. MAYBE WORTH A FOOTNOTE. WILL CONSIDER THIS FOR A
FUTURE EDITION.
Page 561 (PDF page 599):
"it.zipWithIndex: An iterator of pairs of elements returned from it with
their [indices]."
Page 563 (PDF page 601):
"[...] or whether it is an trait such as Seq, Set, or Traversable."
Page 571 (PDF page 609):
"class TraversableLike[+Elem, +Repr] {"

should read

"trait TraversableLike[+Elem, +Repr] {"
Page 589 (PDF page 613):
At top of page, Thread.current should be Thread.currentThread.  (I assume
this is a reference to java.lang.Thread because I did not find any Scala
class called Thread.)

FIXED in 2ed
Page 600 (PDF page 624):
l.17 mixed into to any class
-->  mixed into    any class

FIXED
Page 602 (PDF page 626):
l.-11 avoid sending message to actors
-->                 messages

FiXED
Page 613 (PDF page 637):
l.-5 stays is the same
-->  stays    the same

FIXED
Page 627 (PDF page 650):
Line -2:
Replace "... are represented in as the Scala..." with "... are
represented as the Scala...".
Page 628 (PDF page 651):
l.1 To produce to this
--> To produce    this

FIXED
Page 631 (PDF page 654):
Line 8:
Replace "... at the end of the each..." with "... at the end of each...".

FIXED in 2ed
Page 632 (PDF page 655):
Line 10:
Replace "andthen factor" with "andThen factor"

FIXED in 2ed
Page 637 (PDF page 660):
Error is in the first sentence of the page.

Says: Class Parsers defines a generic parser elem

Should say: Trait Parsers defines a generic parser elem

FIXED in 2ed
Page 638 (PDF page 661):
Mistake is in the paragraph immediately after code listing 31.6 ("an
binary" vs. "a binary")

Says: This is analogous to the situation for patterns, where an binary
pattern

Should say: This is analogous to the situation for patterns, where a
binary pattern

FIXED
Page 643 (PDF page 666):
Line -3:
Replace "lastFailure:" with "lastFailure".

FIXED in 2ed
Page 644 (PDF page 667):
Line -5:
Replace "though" with "through".

FIXED in 2ed
Page 663 (PDF page 685):
l.-5 a main program that creates Spreadsheet component.
-->                            the

FiXED
Page 664 (PDF page 686):
l.-2 go into into the cell.
-->  go into      the cell.

FIXED
Page 666 (PDF page 688):
Line -7/-6:
Replace "the Model trait" with "the Model class".

FIXED in 2ed
Page 669 (PDF page 691):
Line -11:
Replace "the FormulaParser class" with "the FormulaParsers class".

FIXED in 2ed (actually it is the FormulaParsers *object* not class. Fixed
that too)
Page 680 (PDF page 702):
l.8 the value of every of cell
--> the value of every    cell

FIXED
Page 692 (PDF page 712):
In the definition of the term "direct superclass", it:

says: The class from which a class or trait it is immediately derived

should say: The class from which a class or trait is immediately derived

FIXED in 2ed
Page 711 (PDF page 729):
The index entry for () i.e. open / close parentheses should cross refer
to the apply function, and page 39, at least.

DONE in 2ed
Page index (PDF page 730):
There is no reference under @ in the index (page 712 paper, 730 pdf) to
the use of @ as a variable assignment in pattern matches, as introduced
on page 277 (307 pdf).

This is unfortunate as it is quite difficult to search electronically for
references to symbols using engines optimised for words.

FIXED in 2ed
Page 724 (PDF page 742):
Typo:
  lamda -> lambda

FIXED in 2ed
Page 3247 (PDF page 3285):
"By contrast, the function literal _.endsWith(query), used in the most
recent example, contains one bound variable, the argument represented by
the underscore, and one free variable named query"

I believe query is the bound variable, underscore is the free variable.

Copyright © 2021 Artima, Inc. All rights reserved.