The Artima Developer Community


Errata for Programming in Scala, 2nd Edition
Chapter: All
Return to errata index.

Page 0 (PDF page 0):
Webpage error for the page
http://booksites.artima.com/programming_in_scala_2ed:

Link to http://www.cs.kuleuven.be/~adriaan/files/higher.pdf (PDF) only
leads to an error message

[Fixed, thanks.]
Page 0 (PDF page 0):
General: the URL http://booksites.artima.com currently refers to the
original version of the Book. Please revise it to point to
http://booksites.artima.com/programming_in_scala_2ed instead.

Thought there is no separate errata for 2nd ed because of this.
Page xlii (PDF page 39):
"We would also like to think those ..." (-> thank)
Page 3 (PDF page 49):
The footnote reference at the end of the first paragraph as indicated by
the 1 in superscript seems like it should be placed directly after the
first occurrence of the word Scala rather than at the end of the
paragraph. At its currently location I expected I would find a footnote
regarding the use of Scala in large systems since this is the preceding
thought.
Page l (PDF page 50):
In the paragraph following the class CheckSumActor, you write "it
calculates a checksum from the current value of sum and sends the result
back to the requester using the message send requester ! sum"

That last piece should actually say "requester ! checksum"
Page 5 (PDF page 51):
First of all, I really enjoy reading this book, even though I have just
started :-)

You write that "In Raymond's work the bazaar is a metaphor for
open-source development", as though the cathedral isn't. But Raymond
compares in his essay two different types of open-source development
strategies, Emacs being the canonical "cathedral" example, and Linux
being the "bazaar" example. One the other hand, it's hard to imagine
proprietary, closed-source software being developed in bazaar style...
Page 11 (PDF page 57):
It states on p11:
"C and C++ ... function pointers can only refer to global functions, ..."

C++ supports member/method functions pointers; eg:

int (Fred::*)(char,float)

for a non-static member function of class Fred.
Page 14 (PDF page 60):
class MyClass(index: Int, name: String) {}

will NOT produce two private instance variables index and name.
It should be

class MyClass(val index: Int, val name: String) {}
(produces instance variables plus getters)

or 

class MyClass(var index: Int, var name: String) {}
(produces instance variables plus getters and setters)
Page 14 (PDF page 60):
class MyClass(index: Int, name: String) {}

it does produce two private instance variables (as does the associated
java program), they are simply not accessible outside the class, however
that may be the intention
Page 32 (PDF page 77):
There is a qwertist statement in the second paragraph. Welcome relief to
right little finger doesn't hold true for dvorak typists.
Page 33 (PDF page 78):
You write that args.foreach(println) "takes advantage of a special
shorthand". But this piece of code is actually just using a function as
first-class object.

Additionally, you write that "if a function literal consists of one
statement that takes a single argument, you need not explicitly name and
specify that argument". Again, this is just using a function as a value,
and it is not restricted to functions of one argument.

The text in the footnote about "partially applied functions" is just
showing off, it's not really relevant to that text...
Page 38 (PDF page 80):
Discussion of arrays should describe how to create/use multidimensional
arrays in Scala.
Page 42 (PDF page 86):
location 968 of 16616

Chapter 3 Step8

Scala's LIst, scala.List, differs from Java's java.util.List...

My feedback: No scala.List there but scala.collection.immutable.List

right?
Page 43 (PDF page 87):
Description of Why not append to lists is inaccurate.  Please see the
following.
Your options if you want to build a list efficiently by appending
elements is to prepend them, then when you're done call reverse.

Example - Append 4 to List(1,2,3) is expected to be List(1,2,3,4).
In Scala interpretor, you get List(3,2,1,4) which is not expected.
scala> val l1 = List(1,2,3)
l1: List[Int] = List(1, 2, 3)

scala> (4 :: l1).reverse
res17: List[Int] = List(3, 2, 1, 4)
Page 45 (PDF page 89):
With Scala 2.11.7, this example:

thrill.sort((s, t) => s.charAt(0).toLower < t.charAt(0).toLower)

now not only is deprecated (as stated by an existing note), but fails:

scala> thrill.sort((s, t) => s.charAt(0).toLower < t.charAt(0).toLower)
<console>:12: error: value sort is not a member of List[String]
       thrill.sort((s, t) => s.charAt(0).toLower < t.charAt(0).toLower)


Instead, use sortWith:

scala> thrill.sortWith((s, t) => s.charAt(0).toLower <
t.charAt(0).toLower)
res39: List[String] = List(fill, until, Will)
Page 45 (PDF page 89):
Deprecation warnings for some examples:

scala> val thrill = "Will" :: "fill" :: "until" :: Nil
thrill: List[java.lang.String] = List(Will, fill, until)

scala> thrill.remove(s => s.length == 4)
warning: there were deprecation warnings; re-run with -deprecation for
details
res13: List[java.lang.String] = List(until)

scala> thrill.sort((s, t) => s.charAt(0).toLower < t.charAt(0).toLower)
warning: there were deprecation warnings; re-run with -deprecation for
details
res14: List[java.lang.String] = List(fill, until, Will)
Page 45 (PDF page 89):
In "Table 3.1 Some List methods and usages" the examples

thrill.remove(s => s.length == 4) and
thrill.sort((s, t) => s.charAt(0).toLower < t.charAt(0).toLower)

are valid and working but they are deprecated in Scala 2.8.1. The
documentation of the Scala Standard Library recommends the usage of the
filterNot instead of the remove method and sortWith instead of the sort
method.
Page 46 (PDF page 90):
"... but unlike lists, tuples can contain different types of elements".

List(4, "5", 6.0)

compiles well, containing an Int, String and Double.
Page 46 (PDF page 90):
It is written:
Scala infers the type of the tuple to be Tuple2[Int, String]

However, in Scala 2.11.6 REPL, the code
scala> val pair = (99, "luft") //gives
pair: (Int, String) = (99,luft)

Thus, no mention of type as given in book to be
Tuple2[Int, String]
Page 48 (PDF page 92):
"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 48 (PDF page 92):
"As this example shows, you can create sets in Scala similarly to how you
create lists and arrays"

Should it be 'similar' instead of 'similarly' ?
Page 48 (PDF page 92):
In the second paragraph: 

"Both mutable and immutable sets offer a + method, but their behavior
differs."

This is not true, the + methods of both kinds of sets do exactly the same
thing.
Page 83 (PDF page 97):
location 1238 of16616 : Amazon eBook
def formatArgs(arg: Array[String]) = args.mkString("\n")
...
Thus if args contains three elements "zero", "one" and "two", formatArgs
will return "zero\one\two".

My feedback:
#1 
 from: def formatArgs(arg: Array[String]) = args.mkString("\n")
 to:   def formatArgs(arg: Array[String]) = args.mkString("\\")
or
#2
 from: formatArgs will return "zero\one\two".
 to:   formatArgs will return 
       zero
       one
       two

EndOfMyFeedback
Page 56 (PDF page 100):
$ scala -version
Scala code runner version 2.8.0.final -- Copyright 2002-2010, LAMP/EPFL
$ cat countchars1.scala 
import scala.io.Source 

if (args.length > 0) {

  for (line <- Source.fromPath(args(0)).getLines()) 
    println(line.length +" "+ line)
} 
else
  Console.err.println("Please enter filename")
$ scala countchars1.scala countchars1.scala 
/Users/binil/temp/countchars1.scala:5: error: value fromPath is not a
member of object scala.io.Source
  for (line <- Source.fromPath(args(0)).getLines()) 
                      ^
one error found
$

[FIXED]
Page 56 (PDF page 100):
Source.fromPath should be Source.fromFile

[FIXED]
Page 56 (PDF page 100):
"The getLines method returns an Iterator[String], which provides one line
on each iteration, including the end-of-line character."

The end-of-line character is not included, according to the API
documentation of Source.getLines().

[FIXED]
Page 66 (PDF page 110):
Note refers to scala.collection.jcl which is removed in 2.8
Page 69 (PDF page 113):
The last paragraph on page 113 says

"...Thus if you try to run Summer.scala as a script, the Scala
interpreter will complain that Summer.scala does not end in a result
expression (assuming of course you didn’t add any expression of your own
after the Summer object definition)..."

but what happens when trying to execute the Summer.scala as a script with
the command

scala Summer.scala

is that it ends up with the compiler complaining about
ChecksumAccumulator is not being found when the
ChecksumAccumulator.calculate is imported:

error: not found: value ChecksumAccumulator
import ChecksumAccumulator.calculate
Page 71 (PDF page 115):
P71 talks about extending Application. This gives a compile error. It
appears one now should use App instead. 
Using scala 2.11.1
Page 75 (PDF page 119):
More of a "note for future book versions":

Leading zero octal notation is deprecated.

REPL output:
scala> val oct = 035
<console>:1:warning: Treating numbers with a leading zero as octal is
deprecated.
       val oc = 035
                ^
Page 76 (PDF page 120):
"if it were a Short" instead of "if it was a Short" in the sentence:

"If an Int literal is assigned to a variable of type Short or Byte, the
literal is treated as if it were a Short or Byte type so long..."
Page 92 (PDF page 136):
{ val x = a; b.:::(x) }

The parameter passed to the ::: method is wrong - it should be a ...

{ val x = a; b.:::(a) }
Page 112 (PDF page 156):
In order to use implicit conversions, you need to import
scala.language.implicitConversions. Also need to start scala with flag
-feature

Environment: Win8.1 + scala 2.10.4
Page 114 (PDF page 158):
It says "In Chapter 21, you'll learn how to place implicit method
definitions in a companion object for Rational, so they can be more
easily placed into scope when client programmers are working with
Rationals".

It's true that we can place the implicit method in the companion object
of Rational, however, it does not work as one expects. Please see
explanation in
http://stackoverflow.com/questions/4569192/implicit-conversion-import-requ
ired-or-not

Actually in Chapter 21, it use the same implicit method example as the
one in page 112 for the Rational class. This confuses a beginner a lot
during study.
Page 118 (PDF page 162):
The code listed below listing 7.3 behaves differently than the book
states:
  scala> def greet() {println("hi")}
  greet: ()Unit

  scala> greet() == ()
  <console>:9: warning: comparing values of types Unit and Unit using
`==' will always yield true
              greet() == ()
                      ^
  hi
  res0: Boolean = true

Book doesn't mention the warning until the next, "Java style" listing on
the next page (163-pdf).
Page 124 (PDF page 168):
Executing the code in Listing 7.9 with scala 2.9.0.1 gives the following
error:

error: value trimmed is not a member of List[String]
possible cause: maybe a semicolon is missing before `value trimmed'?
    trimmed = line.trim
    ^
one error found

Adding a semicolon as suggested, i.e.:

  line <- fileLines(file);

fixes the problem
Page 125 (PDF page 169):
The first line:
"the last expression of the block"
should be
"the first expression of the block"
Page 132 (PDF page 176):
Listing 7.16 does not give the same result as the Java example it is
supposed to "transliterate".  The counter variable i is incremented one
more time than in the Java example because of the lack of a break
statement.
Page 133 (PDF page 177):
The word "is" is missing in the following sentence:

"Here an example how this library-supplied break method could be applied:"
Page 133 (PDF page 177):
There is a grammatical error in the following sentence.

"Class Breaks in package scala.util.control
offers a break method, which can be used to exit the an enclosing block
that’s marked with breakable."

The phrase "exit the an enclosing block" has two consecutive articles.
Page 134 (PDF page 178):
Explicit scala.language.postfixOps enablement not mentioned in a book.

REPL example:

scala> val r = 7 toLong
<console>:7: warning: postfix operator toLong should be enabled
by making the implicit value scala.language.postfixOps visible.
This can be achieved by adding the import clause 'import
scala.language.postfixOps' or by setting the compiler option
-language:postfixOps.
See the Scala docs for value scala.language.postfixOps for a discussion
why the feature should be explicitly enabled.
       val r = 7 toLong
                 ^
r: Long = 7
Page 149 (PDF page 181):
First example of the Partially Applied Functions (PAF) section:

someNumbers.foreach(println _)

And soon after, this quote (pertaining to it):

"Thus, the underscore in this case is not a placeholder for a single
parameter. It is a placeholder for an entire parameter list."

Just looking at "println _," this is true. But that's not all of the
code. In fact, '_' is first used as a placeholder (as in Placeholder
Syntax, the previous section) to someNumber's foreach, then substitutes
println's arg list with that placeholder (..and, hence, becomes a
Partially Applied Function).

So I think, firstly, the quoted text is confusing, especially considering
the PAF section follows on the heels of the PS section. But I also think
the example is powerful, as it shows '_' used as PS and PAF in the same
statement. The latter text does a good job of explaining PAF as its own
construct. Stylistically, I suggest this example close the PAF section,
not open it, and mention the combined usage.
Page 163 (PDF page 206):
The last sentence of the **Section 8.9**:

"If you don’t fully understand tail recursion yet, see Section 8.9"
Page 165 (PDF page 207):
Missing word "that" in the sentence:

"One benefit of higher-order functions is they enable you to..."
                                          ^
Page 172 (PDF page 214):
Interpreter output, in scala 2.10.2, for the expression:
  scala> def first(x: Int) = (y: Int) => x + y

is
  first: (x: Int)Int => Int

not, as the book states:
  first: (x: Int)(Int) => Int
Page 184 (PDF page 225):
The book states that “The two pairs of definitions [defining `height` and
`width` as `def`s vs. `val`s] are completely equivalent from a client’s
point of view.”  This is not completely accurate, since defining them as
`val`s will result in a null pointer exception later on when
instantiating an instance of the `UniformElement` class as given on p.
235.

`height` and `width` must be defined as `def`s to avoid the exception.
Page 188 (PDF page 229):
Section 10.4, last paragraph.

Class ArrayElement is “composed” out of class Array[String]

should be

Class ArrayElement is “composed” out of Array[String]
Page 190 (PDF page 231):
Sorry, this is nitpicking, but the claim "It's as if the class had been
written as follows, where x123 ..." is not quite true. (Maybe change to
"almost as if".)

It makes a difference when using named arguments. With the definition

  class ArrayElement(val contents : Array[String]) ...

I can use 'new ArrayElement(contents = something)'. But with

  class ArrayElement(x123 : Array[String]) ...

I can't.

Btw: great book!
Page 192 (PDF page 233):
In Section 10.8 it is stated that "Scala requires such a modifier for all
members that override a concrete member in a parent class.".  However,
playing with factory objects using private subclasses, I found that the
compiler does not require the override modifier in a parametric field
definition in a private inner subclass and that the expected override
does not occur:  

Contents of ObjWithPrivSubClass.scala:
package scalafeaturestest

class ConcretePubSuperClass {
  val a: Int = 1
}

/** 
 * Using the override modifier in the parametric field definition 
 * of a public subclass is required by the compiler.
 * But the compiler does not require the override modifier 
 * if the subclass is a private inner class (see below).
 * 
 */
class PubSubClass( override val a: Int ) extends ConcretePubSuperClass {
}

abstract class AbstractPubSuperClass {
  val a: Int
}

/**
 * Object containing inner private sub classes that attempt to 
 *  override 'a' with the value 2 in the public superclasses above.
 * 
 */
object ObjWithPrivSubClass {

  // For a concrete superclass, not using the override modifier 
  // in the private subclass parametric field definition compiles.
  private class PrivSubClass1( a: Int ) extends ConcretePubSuperClass {
  }
  // But a factory method using this subclass definition 
  // does not override 'a'; it retains the superclass value.
  // Note, the factory method must return the public super class type 
  // because the subclass is private.
  val
instancePrivSubClassExtendsConcretePubSuperClassNoParameterOverrideModifie
r: ConcretePubSuperClass = new PrivSubClass1( 2 )

  // For a concrete superclass, using the override modifier 
  // in the subclass parametric field definition compiles.
  private class PrivSubClass2( override val a: Int ) extends
ConcretePubSuperClass {
  }
  // In this case, a factory method using this subclass definition 
  // does override 'a'; it uses the new value.
  val instancePrivSubClassExtendsConcretePubSuperClassHasParamet
Page 192 (PDF page 233):
Oops, regarding my previous submission, I found a coding error which
explains the issue.  I forgot to include the "val " in my subclass
definition: "private class PrivSubClass1(a: Int) extends
ConcretePubSuperClass { }". So the class just takes a parameter that it
never uses.  Adding "val " to correctly define the parametric field
causes the compiler to require the override modifier so that the correct
definition is "private class PrivSubClass1(override val a: Int) extends
ConcretePubSuperClass { }".  As an aside, I note that it would be nice if
the compiler would warn when a parameter is defined that is never used
and suggest that the "val " might have been left off.  Thanks.
Page 200 (PDF page 241):
Readability glitch. The following two sentences seem to be saying the
same thing to me, and break the otherwise perfect flow in the text.

"Here, the two arrays this.contents and that.contents are transformed
into an array of pairs (as Tuple2s are called) using the zip operator.
The zip method picks corresponding elements in its two arguments and
forms an array of pairs."

I'd remove the later sentence.

[I improved it by saying operator and operands instead of method and
arguments. Method and arguments was wrong.]
Page 203 (PDF page 244):
On the bottom of the pages 244 (and also on the page 245) the book uses:

new ArrayElement

although we already refactored the code to use only factory methods for
Element creation, thus ArrayElement is private class of the Element
singleton.

The code should say:

'Element.elem' instead of 'new ArrayElement'
Page 206 (PDF page 247):
Not quite an errata, but perhaps it would be worth calling this out.

Back on page 183, there is a discussion which ends with the comment "This
means you cannot define an element with a height of zero and a non-zero
width".  By the time we get to page 206, this is true for ArrayElement's,
but not for UniformElement's.  Indeed, the correctness of the code
depends upon the ability of UniformElement to have a non-zero width but a
zero height, because in heighten(), it is possible for "top" to be of
zero height, but the subsequent use of the  "above()" operator will only
work if "top" can return an appropriate width (without an
index-out-of-bounds exception).

Of course, this works because the parameters in UniformElement's
constructor override the width() and height() function in the base class,
which is easy to overlook.

Thanks! Great book!
Page 206 (PDF page 247):
var right = elem(' ', w - width - left.width, height)

should be

val right

and also

var bot = elem(' ', width, h - height - top.height)

on same page
Page 207 (PDF page 248):
The book's version of Spiral outputs this for 14 edges:
+-------------
|             
| +---------+ 
| |         | 
| | +-----+ | 
| | |     | | 
| | | +-+ | | 
| | | + | | | 
| | |   | | | 
| | +---+ | | 
| |       | | 
| +-------+ | 
|           | 
+-----------+ 

I would suggest this version of `spiral`, as the shapelier solution,
that, IMHO, better fits the book's philosophy (simple over easy):
+-----------
| +-------+ 
| | +---+ | 
| | | + | | 
| | +-+ | | 
| +-----+ | 
+---------+ 

It's "more square", if nothing :)
 
def spiral(nEdges: Int, direction: Int): Element = {
    if(nEdges == 1)
      corner  // we already have `corner`, so why not use it
    else {
      val sp = spiral(nEdges - 1, (direction + 3) % 4)
      def verticalBar = elem('|', 1, sp.height - 1)
      def horizontalBar = elem('-', sp.width, 1)
      if(direction == 0)
        (corner beside horizontalBar) above (sp beside space)
      else if(direction == 1)
        (sp) beside (corner above verticalBar)
      else if(direction == 2)
        (space beside sp) above (horizontalBar beside corner)
      else
        (verticalBar above corner) beside (sp)
    }
  }
Page 210 (PDF page 251):
Minor errata; typo/grammar.

Footnote, 4th line.

"was necessary correct this discrepancy" should read 
"was necessary to correct this discrepancy"
Page 210 (PDF page 251):
Footnote, 1st line.

"..where == is does not.."
should read
"..where == does not.."
Page 211 (PDF page 252):
ScalaObject is deprecated according to
http://www.scala-lang.org/api/2.10.4/index.html#scala.ScalaObject
Page 224 (PDF page 265):
In the code snippet there are 4 operators defined.
The text then states "...three of the comparison operators are defined in
terms of the first one..."
Thus, we are to assume that the first is < and "three" refers to the
latter of the 4 shown operators.
If this is the case then only 2 of the 3 latter operators refer to <. The
last of the 4 operators, >=, refers to >, || and == and not <.
Page 224 (PDF page 265):
def < seems to have the wrong symbol: should be
  def < (that: Rational) =
    this.numer * that.denom < that.numer * this.denom
Page 225 (PDF page 266):
The compare method for Rational is not robust as it can easily overflow. 
The same could be said for the whole of chapter 6.
Page 226 (PDF page 267):
The last paragraph of the chapter 12.4 mentions "type erasure".
Since this term wasn't mentioned previously in the book it would be
consistent with the rest of the book to add a note/link that "the type
erasure is explained in chapter 15.2" (or a footnote that briefly
explains it).
Page 241 (PDF page 281):
The comment in the code at the bottom of the page looks wrong.

package bobsrocket
package fleets
class Fleet {
	// Doesn't compile! Ship is not in scope.
	def addShip() { new Ship }
}

It should read (like in Listing 13.4):
	// No need to say bobsrockets.Ship
Page 250 (PDF page 290):
Minor errata.

Second to last paragraph.

"the distance variable in class LegOfJourney in Listing 13.12" should
read "the distance value ..."

distance is a val in Listing 13.12.
Page 251 (PDF page 291):
"..the Rocket class above can access.."

Unfortunately, due to layout, the Rocket class in Listing 13.13 is on the
following page.

Suggestions: "the Rocket class below"
"the Rocket class in Listing 13.13"
Page 253 (PDF page 293):
Minor errata; typo/grammar.

Last paragraph.

"that are the located in the directory" should read 
"that are located in the directory"
Page 256 (PDF page 296):
Similarly to page 206,

var right = ...

should be

val right = ...
Page 257 (PDF page 297):
"Assertions can be enabled and disabled using the JVM's -ea and -da
command-line flags."

This does not work. Assertions may be disabled at compile time using the
"-Xdisable-assertions" scalac option. But this is different from the
JVM's -ea and -da runtime option.
Page 257 (PDF page 297):
Listing 14.3, and all applicable listings below it in the chapter.

"import org.stairwaybook.layout.Element" needs to be added above "import
Element.elem" in order for the class to compile.

-- snip --
import org.scalatest.Suite
// import org.stairwaybook.layout.Element  // Errata, added
import Element.elem
-- snip --

A simple test in the scala REPL to verify this:

scala> import org.scalatest.Suite
import org.scalatest.Suite

scala> import Element.elem
<console>:8: error: not found: value Element
       import Element.elem
              ^

scala> import org.stairwaybook.layout.Element  // Errata, added
import layout.Element

scala> import Element.elem // now Element can be found
import Element.elem
Page 263 (PDF page 303):
pg 303 pdf (chapter 14)

Output of "(new ElementSpec).execute()" near the bottom of the page:

"- should throw an IAE if passed a negative width" should read:

- should throw an IAE if passed a negative width *** FAILED ***
  Expected exception java.lang.IllegalArgumentException to be thrown, but
no exception was thrown. 

Spiral.scala will compile with "def verticalBar = elem('|', -2,
sp.height)". However, the spiral will then be missing some sides. This is
actually a good example of a test that reveals a bug in the code.
Page 270 (PDF page 310):
At the bottom of the page it reads, "all arguments in the parameter list
of a case class implicitly get a val prefix, so they are maintained as
fields".

This is true, but strictly speaking it is true of any class. The
difference is that in a normal class the fields are not public.

abstract class Expr
class Var(name: String) extends Expr {
  def printName() = println(name)
}

object ScalaApp {
  def main(args : Array[String]) : Unit = {
      val v = new Var("x")
      v.printName() // prints "x"
      // println(v.name) // Error: value name is not a member of Var
  }
}
Page 271 (PDF page 311):
Add case class's copy method to index.
Page 273 (PDF page 313):
In the first paragraph of the "match compared to switch" subsection you
wrote:

"First, match is an expression in Scala, i.e., it always results in a
value."

May be it would be more accurate to precise: ".... i.e., it always
results in a value if no exception is thrown during the evaluation."

For instence the code: 

val i = 3
println(i match {
	    case 3 => 3/0
	    case _ => "other"
	  })

Will throw an exception and the match expression will not result in a
value.

Ps: great book!!
Page 285 (PDF page 325):
The running example for pattern matching is broken because it won't
simplify expressions like -(-x+0) or x*(1+0). You have to simplify
subterms first, and only then apply the patterns.
Page 289 (PDF page 329):
2nd to last paragraph

2nd to last sentence

"For Scala, the approach would not work at all, because it is possible to
store value types..." 

should perhaps be:

"For Scala, the approach would not work at all, because it is *only*
possible to store value types..."
Page 301 (PDF page 341):
"r is placed between parentheses"

should say "oper is placed between parentheses"
Page 309 (PDF page 348):
Typo in gray box (line 12): “Indeed there is such _as_ class”
Page 315 (PDF page 354):
"You will see in Section 4 how to speed it up."

We're already in Section 16.6. The reference must be wrong?
Page 327 (PDF page 366):
Last paragraph, first sentence, first part:
"For associative operations, fold left and fold right are equivalent"
should be "For commutative associative operations, fold left and fold
right are equivalent".

Counter example for the statement as it stands:
scala> ( "START" /: words) ( _ + _ )
res10: String = STARTthequickbrownfox

scala> (words :\ "START" ) ( _ + _ )
res11: String = thequickbrownfoxSTART
Page 328 (PDF page 367):
Intro: While discussing type inference for fold methods, the books gives
a forward reference, which leads to the wrong chapter.

Text: "To find out why the type inferencer goes wrong, you’ll need to
know about the types of the fold methods and how they are implemented.
More on this in Chapter 22."

Problem: However, folds are not even discussed in chapter 22, and the
issue is discussed much earlier, in section 16.10.

Fix: Please replace last sentence of the quoted text with: "More on this
in Section 16.10."
Page 349 (PDF page 387):
On the top of the page, as part of the commonly used operations for maps,
the book states:

nums.keys    Returns the keys (returns an Iteratable over ...
                                          ^
Should be: Iterable
Page 372 (PDF page 410):
at page 372 is missing at start of source 'Simulation' class the package:

current version:
 
abstract class Simulation {
  ......
}


new version:

package org.stairwaybook.simulation
abstract class Simulation {
  ......
}
Page 393 (PDF page 430):
In the second paragraph, right after the code example, it says "then if T
is a subtype of type S, this would imply that Queue[S] is a subtype of
Queue[T]" I guess it should be "then if S is a subtype of type T..."
Page 399 (PDF page 430):
chapter 19 appears to either have an error or I am compiling the code
incorrectly:
The following will not compile in Eclipse:
/** specialization of the Queue[T] trait to Int **/
class StrangeIntQueue extends Queue[Int] {
  override def enqueue(x: Int) = {
    println(math.sqrt(x))
    super.enqueue(x)      // THIS DOES NOT COMPILE
  }
}

The compiler error:
method enqueue in trait Queue is accessed from super. It may not be
abstract unless it is overridden by a member declared abstract' and
override'
Page 393 (PDF page 430):
I read the errate corrige relate this Page :
"
  Page 393 (PDF page 430):
  In the second paragraph, right after the code example, it says
  "then if T is a subtype of type S, this would imply that Queue[S] 
  is a subtype of Queue[T]" I guess it should be "then if S is a 
  subtype of type T..."
"

This correction is WRONG :
the text in book is correct because with controvariance 
   is T is a subtype of S thus ==> Queue(S) is subtype Queue(T)
Page 399 (PDF page 436):
I'm not sure but this page does not seem correct:
this is text of book: (the sign after T,W,U are intended as superscript)

abstract class Cat[-T,+U] {
   def meow[W-]( volume: T-,listener: Cat[U+, T-]-)
      :   Cat[Cat[U+, T-]- , U+]+
}   
This definition seems to contradict what is said later:
" .... In this case T is only used in negative positions and U is only
used in positive positions... "


the correct form should be:

abstract class Cat[-T,+U] {
   def meow[W-]( volume: T- ,listener: Cat[T-,U+]-)
      :   Cat[Cat[T-, U+]- , U+]+
}   

it would not hurt if the example was explained in a little more detail
Page 411 (PDF page 447):
Minor quibble. Book code gives this

  trait Abstract {
    type T
    def transform(x: T): T
    val initial: T
    var current: T
  }

and a class instantion of this

  class Concrete extends Abstract {
    type T = String
    def transform(x: String) = x + x
    val initial = "hi"
    var current = initial
  }

Note this in the trait 

    def transform(x: T): T

is given as this in the concrete instatiation

    def transform(x: String) = x + x

whereas logically (I think) it should minimise any changes to the
concrete and rely directly on the type alias, hence the above should be 

    def transform(x: T) = x + x

I've tested it and it compiles.
Page 425 (PDF page 461):
It makes sense that I cannot feed the Cow 'bessy' a new Fish, but I
cannot feed bessy new Grass either.  From the text it seems that I should
be able to.  Why else point out that bessy cannot eat Fish if it can't
eat Grass either?

scala> class Food
defined class Food

scala> abstract class Animal {
     | type SuitableFood <: Food
     | def eat(food: SuitableFood)
     | }
defined class Animal

scala> class Grass extends Food
defined class Grass

scala> class Cow extends Animal {
     | type SuitableFood = Grass
     | override def eat(food: Grass) {}
     | }
defined class Cow

scala> class Fish extends Food
defined class Fish

scala> val bessy: Animal = new Cow
bessy: Animal = Cow@4bd767

scala> bessy eat (new Fish)
<console>:12: error: type mismatch;
 found   : Fish
 required: bessy.SuitableFood
       bessy eat (new Fish)
                  ^

scala> bessy eat (new Grass)
<console>:11: error: type mismatch;
 found   : Grass
 required: bessy.SuitableFood
       bessy eat (new Grass)
                  ^
Page 438 (PDF page 474):
The decimals function gives a StackOverflowError for numbers between 2
and 9:

scala> def decimals(n: Long): Int = 
     | if (n == 1) 0 else 1 + decimals(n / 10)
decimals: (n: Long)Int

scala> decimals(100)
res4: Int = 2

scala> decimals(101)
res5: Int = 2

scala> decimals(1)  
res6: Int = 0

scala> decimals(5)
java.lang.StackOverflowError
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
	at .decimals(<console>:6)
Page 444 (PDF page 480):
In the sentence 

> The fact that this listener is an ActionListener, the fact that the
> callback method is named actionPerformed, and the fact that the 
> argument is an ActionListener are all implied for any argument to 
> addActionListener.

I wondered whether "the argument" should refer to the argument
of the callback method, so that its implied type would be
"ActionEvent" instead of ActionListener.

[Yes, that was a typo. Fixed.]
Page 444 (PDF page 480):
"the fact that the argument is an ActionListener"

should be

"the fact that the argument is an ActionEvent"
Page 469 (PDF page 505):
The source code for object Nil (listing 22.1) and case class :: use the
override modifier for isEmpty but not for head and tail.

According to section 10.8 the override modifier is mandatory in Scala and
chapter 22.1 introduced isEmpty, head and tails as abstract methods in
class List.
Page 476 (PDF page 512):
The package for the ListBuffer class should be scala.collection.mutable
instead of scala.collection.immutable
Page 477 (PDF page 513):
On page 477, in the first line of body of the method '+=', we have:
if (exported) copy()

I checked the scaladoc of the class ListBuffer, but I did not any method
called 'copy()', where is it defined?
Page 486 (PDF page 521):
A nice addition to the n-queens problem would be to print all possible
solutions to the console in a nice format:
________________
|Q|_|_|_|_|_|_|_|
|_|_|_|_|Q|_|_|_|
|_|_|_|_|_|_|_|Q|
|_|_|_|_|_|Q|_|_|
|_|_|Q|_|_|_|_|_|
|_|_|_|_|_|_|Q|_|
|_|Q|_|_|_|_|_|_|
|_|_|_|Q|_|_|_|_|
________________
|Q|_|_|_|_|_|_|_|
|_|_|_|_|_|Q|_|_|
|_|_|_|_|_|_|_|Q|
|_|_|Q|_|_|_|_|_|
|_|_|_|_|_|_|Q|_|
|_|_|_|Q|_|_|_|_|
|_|Q|_|_|_|_|_|_|
|_|_|_|_|Q|_|_|_|
...

// This could probably be written differently, but nevertheless, here is
the code:

def printSolutions(tbls: List[List[(Int, Int)]]) = {
  def printSolution(tbl: List[(Int, Int)]) = {
    val len = tbl.head._1  // since it's upside down
    println("_" * (len * 2))
    for {
      dim <- tbl.reverse
      col <- 1 to len      // we put something in every cell
      pipe = if (col == 1) "|" else ""
      cell = if (col == dim._2) "Q|" else "_|"
      nl = if (col == len) "\n" else ""
    } print(pipe + cell + nl)
  }
  for (t <- tbls) printSolution(t)
}
Page 505 (PDF page 540):
The description of copyToArray should say "Copies at most len elements of
xs to arr," instead of "copies at most len elements of arr." It should
also specify whether the start index is for the array or for the
collection being copied from.
Page 509 (PDF page 544):
Table that summarizes operations of Iterable trait:

xs.zipWithIndex - An iterable of pairs of elements from xs with
their indicies (should've spelled "indices")
Page 514 (PDF page 549):
Since the expression is written as "xs(i) = x" the following sentence
"Changes the element of xs at index i to y." should be "Changes the
element of xs at index i to x.".
Page 521 (PDF page 556):
Missing preposition "in" in the first sentence of the "Sorted sets"
chapter:

A SortedSet is a set where, no matter what order elements 
                                      ^
were added to the set, the elements are traversed in sorted order.
Page 527 (PDF page 562):
The first sentence on the page contains one extra word "have":

... but it would have have taken more code to do so.
                      ^
Page 515 (PDF page 567):
"Because if this" -> "Because of this"

[Fixed.]
Page 541 (PDF page 576):
It's - > its
Page 542 (PDF page 577):
In the explanation of putIfAbsent function, key/value binding should be
"k -> v" not "k -> m".
Page 552 (PDF page 587):
In the last paragraph of Equality subsection, the array name should be
buf, not xs:
...because the hash code of the array *xs* has changed... -> ...because
the hash code of the array "buf" has changed...
...than the one in which *xs* was stored. -> ...than the one in which
"buf" was stored.
Page 554 (PDF page 589):
In the listing that shows view operations one by one, it is listed:

val vv = v.view
vv: scala.collection.SeqView[Int,Vector[Int]] =
SeqView(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

But, in the interpreter, the same expression gives lazy result:

val vv = v.view
vv: scala.collection.SeqView[Int,Vector[Int]] = 
SeqView(...)
Page 539 (PDF page 591):
"..and do not have a ClassManifest to provide it at run-time."

The 'it' seems too much, and I cannot figure out where it would point.

-> "..a ClassManifest to provide at run-time."

[Agreed. I changed "it" to "the element type". (Also we changed
ClassManifest to ClassTag.)]
Page 543 (PDF page 595):
"Scala arrays offer much more (than) their Java analogues." 

"than" is missing.

[Fixed.]
Page 564 (PDF page 599):
The 'start' arguments to Iterator's addString and mkString are typeset in
the books regular serifed font and should instead be monospaced.
Page 566 (PDF page 601):
Third paragraph, 6th line: "...or whether it is *an* trait such as..."
Page 571 (PDF page 606):
"You've now seen how to use Scala's collection in great detail.":
"collection" -> "collections" or "collection" -> "collection library"
Page 575 (PDF page 609):
In Listing 25.2, class TraversableLike should be trait TraversableLike.

[Fixed.]
Page 578 (PDF page 612):
In the code listing 25.3 it can be read:
"def map[B, That](p: Elem => B)(implicit bf: CanBuildFrom[B, That,
This]): That" since CanBuildFrom definition is "CanBuildFrom[-From,
-Elem, +To]" I expected to read "...(implicit bf: CanBuildFrom[This, B,
That]): That" so I downloaded Scala's source code and found the
definition was wrongly typed in the book. On the other hand, the function
parameter name is "p" whereas it is referred as "f" below.
Page 578 (PDF page 612):
In Listing 25.3, the signature of map names the function to apply
"(p: Elem => B)", but it is then referred to as "f" in the body.

Obviously, the signature should be "... (f : Elem => B) ..."

(Personally, I would like f : A => B even better, but thats for
didactic purposes, I think).

[I concur. I changed p to f. Left Elem and changed A to Elem later. A is
what it is called in reality. We called it Elem in the book to help
readers keep track of which type was the element type.]
Page 578 (PDF page 612):
In Listing 25.3, the signature of the map method is wrong. Type
CanBuildFrom[B, That, This] should be CanBuildFrom[This, B, That] instead.
Page 578 (PDF page 612):
Concerning my first erratum:

It really should be "f : A => B" rather than "f : Elem => B", because
the first version re-occurs on page 587, so "f : A => B" would
be consistent, where "f : Elem => B" is not.

[I changed A to Elem here for consistency.]
Page 562 (PDF page 614):
For "it take n":

"An iterator returning of the first n..."
->
"An iterator returning the first n..."

[Fixed.]
Page 580 (PDF page 614):
The four bases of RNA are in fact AUCG, not AUTG, where 'C' stands for
'cytosine'. 'T' and 'U' are two versions (DNA vs RNA) of the same base.
Page 583 (PDF page 617):
Missing "override" in the "take" method implementation (bottom of the
page):

def take(count: Int): RNA1 = RNA1.fromSeq(super.take(count))
Page 565 (PDF page 617):
Add Vector to the index.

[Done]
Page 581 (PDF page 633):
In Listing 25.6, I think "groups" in the definition of the class RNA1
should be private:

final class RNA1 private (private var groups: Array[Int], val length:
Int) ...

Otherwise clients can mutate the contents very easily, e.g.

rna1.groups(0) = 0
Page 590 (PDF page 642):
"..a Patricia trie storing the three strings "abc", "abd", "al", "all",
"xy" would.."

That's five strings, but simply remove "three".

[Math to the rescue. I added two to the "three" and changed it to "five".]
Page 595 (PDF page 647):
In Listing 25.11, the definition of PrefixMap contains a superfluous
"extends" clause. It doesn't do any harm, as the code compiles and runs
fine with or without it. Still it has no purpose there, just makes the
code more complex and confusing.

[Fixed.]
Page 619 (PDF page 653):
2nd line from the bottom: replace "a warning" with "an error".

See
https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_8_1_final/src//l
ibrary/scala/annotation/tailrec.scala#L13

"... the compiler will issue an error if the method cannot be optimized
into a loop."
Page 622 (PDF page 656):
"Further, the contents of any two matching tags must itself be valid
XML.": "contents" -> "content"
Page 630 (PDF page 664):
The book states that when
  scala.xml.XML.save("therm1.xml", node)

is called, that the output file, "therm1.xml", will have header:
  <?xml version='1.0' encoding='UTF-8'?>

But when I do that, in the same way the book describes, there is no xml
header, just pure XML inside the therm1.xml.
Page 646 (PDF page 680):
In a simple program that chooses a database at runtime, even though we
choose a database based on the input parameter, we later nonchalantly 
discard that choice and hard wire to the "SimpleDatabase":

object GotApples {
  def main(args: Array[String]) {
    val db: Database =
      if(args(0) == "student")
        StudentDatabase
      else
        SimpleDatabase

    object browser extends Browser {
      val database = db
    }

    val apple = SimpleDatabase.foodNamed("Apple").get
                ^
    for (recipe <- browser.recipesUsing(apple))
      println(recipe)
  }
}

The marked line should be:
val apple = db.foodNamed("Apple").get
Page 654 (PDF page 687):
The following example is indeed not perfect.  It's single parameter
should be named "that" and not "other" because it is referred to as
"that" in most of the body.

// A better definition, but still not perfect
override def equals(other: Any) = other match {
  case that: Point => ...
}
Page 664 (PDF page 697):
Listing 30.2
------------------
case that: ColoredPoint =>
  (that canEqual this) && 
   super.equals(that) && ...
------------------

The "that canEqual this" part is redundant, because the same check is
done inside "super.equals(that)" already.
Page 672 (PDF page 705):
The sentence "The only exception to this requirement is for final classes
that redefine the equals method inherited from AnyRef." seems
contradictory to the initial sentence of rule #1. 

Sorry if I have misunderstood the rule.
Page 680 (PDF page 713):
The first paragraph (the one starting with "To contrast ...") seems to be
wrong. It states that if both a class and its companion object are
defined, no static forwarding methods to the companion object would be
defined in the class and that Java code will have to access the companion
object via the MODULE$ instance. I wrote a simple code example and by
using javap I saw that actually those static forwarding methods are
defined. 
I apologize if I actually misunderstood the fragment.
Page 689 (PDF page 722):
You are missing a "do" in second paragraph of 31.5.  "All you have to is
put the Java source files on the command line as if they were Scala
files" should be "All you have to do is ..."
Page 694 (PDF page 727):
What is the purpose of 'Thread.sleep(1000)' in the snippet illustrating a
utility method 'actor'?

scala> val seriousActor2 = actor {
         for (i <- 1 to 5)
           println("That is the question.")
         Thread.sleep(1000)
       }

The code indeed prints out the string 5 times, but it happens all at
once, followed by, rather unnoticeable, 1s pause.
Page 697 (PDF page 730):
Missing "to" in the last sentence of the page:

  "If you want your program be as efficient as possible, ..."
Page 698 (PDF page 731):
Highlighted section, in the middle of the page:

  "... programs will need at least a few receive’s, but you ..."
                                                ^
That should've been ordinary plural, "receives".
Page 707 (PDF page 740):
On Listing 32.6, comment on getIp refers to Listing 30.3 but should
probably refer to Listing 32.3 instead.

(30 seems to have been the chapter number for actors in 1st edition)
Page 689 (PDF page 741):
"All you have to (do) is put the Java source.."

"do" is missing

[Fixed.]
Page 747 (PDF page 779):
I wonder if the type of the alternation function is wrong.  I tried
something similar and the compiler reported that the covariant type
parameter T is used in a contravariant position.  I tried
  def | [U >: T]( q: => Parser[U]) = new Parser[U] ...
Page 757 (PDF page 788):
Not really a bug/error but a feature request...

The chapter starts with the following code:

import scala.swing._

which indicates that swing is part of the standard Scala installation. 
Even thought it's part of the core api, I had to hunt down the
dependencies in order to be able to import the library.  The following
line needed to be added to my build.sbt file:

libraryDependencies += "org.scala-lang" % "scala-swing" % "2.11.0-M7"

It would be helpful to give an indication in the book that the user is
responsible for tracking down this dependency.
Page 758 (PDF page 789):
'SimpleGuiApplication' is deprecated.
For a book with the newest changes, this example should better use
'SimpleSwingApplication'.
Page 774 (PDF page 805):
Trying to create array of arrays in a way the book suggests:

  val cells = new Array[Array[Cell]](height, width)

yields compiler error:

  too many arguments for constructor Array: (_length:
Int)Array[Array[Model.this.Cell]]

So I used:

  val cells = Array.ofDim[Cell](height, width)
Page 783 (PDF page 814):
listing 35.7 :

case Coord(row, column) =>
cells(row)(column).value <-----

Copyright © 2024 Artima, Inc. All rights reserved.