The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".
The following errata were submitted by our customers and approved as valid errors by the author or editor.
Version |
Location |
Description |
Submitted By |
Date submitted |
Date corrected |
Printed |
Page x
ToC for Chapter 8 |
The subsection "Implicit Function Parameters" should be a subsection of "Implicits", not at the same level as "Implicits".
Note from the Author or Editor: The formatting should be changed in subsequent printings and editions
|
Dean Wampler |
Jun 13, 2010 |
|
Printed |
Page p59
1st example |
Here is the scala code in the example:
scala> val configFile = new java.io.File("~/.myapprc")
This code passes "~/.myapprc" as the argument but java.io.File API's starts searching from the current directory, but not the home. This is because java.io.File doesn't handle "~" as in the UNIX shells.
Note from the Author or Editor: Indeed, this doesn't quite work. For the example, it would be sufficient to change "~/.myapprc" to ".myappconfig". (Changing "rc" to "config" might be clearer for non-*nix readers).
|
Anonymous |
Sep 12, 2010 |
|
Printed |
Page 13
sanjay.dasgupta@gmail.com |
The last paragraph of page-13 implies that function literals too may (like methods) use the return keyword, and also have return statements.
This is not strictly correct. Only explicitly named functions (methods) may use a return (JLS section 6.20).
Note from the Author or Editor: I didn't know this, but it's true.
|
Sanjay Dasgupta |
Sep 05, 2011 |
|
Printed |
Page 20
6 |
When running shapes-actor-script.scala in 2.8.0 I see no output at all. If I run the program many times, I occasionally see the first line of output printed (Circle.draw...) but nothing more.
This appears to be because the REPL completes the script and exits before the Actor is completed its work.
As a quick-and-dirty fix to this I added the following to the end of shapes-actor-script.scala:
Thread.sleep(1000)
Note from the Author or Editor: UPDATE 3/23/2011: It appears this problem can occur because System.out (i.e., stdout) is not flushed by default when calling println, at least on some platforms and some versions of Scala or the underlying Java libraries. To fix the problem, add the following line to the end of the driver script, shapes-actor-script.scala:
System.out.flush
I can't reproduce the problem, but it's also not easy to run this script in isolation, because you have to compile a few other files first. Try this, which works with Scala 2.7.7, Scala 2.8.0, and Scala 2.8.1 (2.7.7 was used when the book was written).
cd <where_you_put_the_examples>/chapters/code-examples/IntroducingScala
scalac shapes.scala shapes-actor.scala
scala -cp . shapes-actor-script.scala
You should see the following output:
java.class.path: /Library/tools/scala/scala-2.8.1.final/lib/jline.jar:/Library/tools/scala/scala-2.8.1.final/lib/scala-compiler.jar:/Library/tools/scala/scala-2.8.1.final/lib/scala-dbc.jar:/Library/tools/scala/scala-2.8.1.final/lib/scala-library.jar:/Library/tools/scala/scala-2.8.1.final/lib/scala-swing.jar:/Library/tools/scala/scala-2.8.1.final/lib/scalacl-0.2.Beta8-shaded.jar:/Library/tools/scala/scala-2.8.1.final/lib/scalap.jar
CLASSPATH: :/Library/tools/java/junit4.5/junit.jar:.
Circle.draw: Circle(Point(0.0,0.0),1.0)
Rectangle.draw: Rectangle(Point(0.0,0.0),2.0,5.0)
Triangle.draw: Triangle(Point(0.0,0.0),Point(1.0,0.0),Point(0.0,1.0))
Error: Unknown message! 3.14159
exiting...
|
Joe Littlejohn |
Mar 20, 2011 |
|
Printed |
Page 25
Last paragraph (after the title "Method Declarations") |
In the line quoted below, the method-name itself is missing:
"Method definitions start with the def keyword, followed
by optional argument lists, a colon character ... "
It should probably have read as follows:
"Method definitions start with the def keyword, followed
by the method-name, optional argument lists, a colon character ... "
Note from the Author or Editor: Ah yes, we left out the most important part of the method definition! Thanks for pointing this out.
|
Sanjay Dasgupta |
Jan 06, 2010 |
|
PDF |
Page 27
// code-examples/TypeLessDoMore/user-profile-v28-script.scala |
In executing the script "user-profile-v28-script.scala" in the following manner: scala -cp . user-profile-v28-script.scala, the Class instance is printed out, not the values of location, age, webSite.
I added: override def toString: String = { "Location [" + location + "] age [" + age + "] webSite [" + webSite + "]") to the class OptionalUserProfileInfo.
Note from the Author or Editor: Yes, the output isn't very helpful, but the easier solution is to add the "case" keyword before the class definition. It will give you a nice toString method.
|
Anonymous |
Jul 30, 2011 |
|
|
30
first code example on the page |
"import java.util.Map" can be removed as it isn't used anymore making the code even more concise.
Note from the Author or Editor: Correct.
|
Anonymous |
Jul 13, 2010 |
|
Printed |
Page 32
"method-broad-inference-return-script.scala" example |
The comment that begins with // ERROR: contains text from the previous example. This line should read "//ERROR: Won't compile: List[Nothing] return type inferred for makeList"
|
Dean Wampler |
Sep 28, 2009 |
|
|
33
In the string-util-client.scala example at the bottom of the page |
You use the "args foreach" notation which is confusing as you haven't explained or introduced this infix notation before in the book.
I only realized this when reading the note at the top of page 38 which uses the term "operator notation" without linking to its definition.
Note from the Author or Editor: Hmm. Must have let that sneak through. Thanks for the catch.
|
Anonymous |
Jul 13, 2010 |
|
Printed |
Page 35
1st paragraph |
"The solution is to parameterize the initial map declaration ..."
should probably read
"The solution is to specify the type parameters on the initial map declaration..."
Note from the Author or Editor: While the original wording is fine, the suggested rewording is a little clearer.
|
OKAMOTO Kazumi |
Dec 30, 2009 |
|
Printed |
Page 36
warning |
"sign before the opening parenthesis for the method body,..."
should probably read
"sign before the opening curly bracket for the method body,..."
Note from the Author or Editor: Yes, this is correct. Thanks. We use "curly brace" rather than "curly bracket" in the text.
|
Kazumi Okamoto |
Dec 30, 2009 |
|
Printed |
Page 43
Fourth paragraph, second line |
Quoting, "thanks to Scala's static typing, you can't make the mistake of attempting to call a method on a value that might actually be null".
One most certainly can try to make such a call without the compiler complaining about it. This should have said "None" instead of "null".
I assume it was a typo, but the actual effect, for those not familiar with the language, is possibly misguiding them about null safety in Scala.
Note from the Author or Editor: The sentence wording is confusing. Better wording for the whole paragraph is the following.
"Also, thanks to Scala's static typing, you can't make the mistake of "forgetting" that an Option is returned and attempting to call a method supported by the type of the value inside the Option (if there is a value). In Java, when a method returns a value, it's easy to forget to check for null before calling a method on the value. When a Scala method returns Option, the type checking done by the compiler forces you to extract the value from the Option first before calling a method on it. That "reminds" you to check if the Option is actually None. So, the use of Option strongly encourages more resilient programming."
|
Daniel Capo Sobral |
Oct 23, 2009 |
|
Printed |
Page 43
1st paragraph |
In the first paragraph:
"This method returns either the value in the Option, if it is a Some instance, or it returns the second argument we passed to getOrElse, if it is a None instance."
But the sample code passed one argument to getOrElse method.
What is "the second argument" expressed with this sentence?
Note from the Author or Editor: The sentence should say "..., or it returns the argument we passed to getOrElse, ..."
There is only one argument. Thanks for the catch.
|
Anonymous |
Sep 06, 2010 |
|
PDF, Mobi |
Page 43
5th paragraph, second to last sentence |
The book says "Tony Hoare, who invented the null reference in 1965 while working on an object-oriented language called ALGOL W"; ALGOL W was not an object-oriented language and it predated Simula, the first object-oriented language.
Note from the Author or Editor: Hmm. It was dumb to include the phrase "object-oriented".
|
David Starner |
Aug 29, 2013 |
|
Printed |
Page 51
In last column (under "See ...") of reserved words table for reserved word "<%" |
The location reference is not accurate, and should have been:
"Views and View Bounds" on page 264
Note from the Author or Editor: Technically, the reference is to the enclosing section, but this suggestion does narrow the reference down to the actual subsection, so we should change it. Thanks for the suggestion.
|
Sanjay Dasgupta |
Jan 06, 2010 |
|
Printed |
Page 51
In last column (under "See ...") of reserved words table for reserved word "#" |
The location reference is not accurate, and should have been:
"Type Projections" on page 279
Note from the Author or Editor: Good catch. Thanks for pointing this out.
|
Sanjay Dasgupta |
Jan 06, 2010 |
|
|
57
Paragraph after the first example |
"The second expression is equivalent to list.::(a)" is wrong. The a needs to be quoted: list.::('a')
Note from the Author or Editor: Yes, the quotes around "a" got dropped in the production of the book.
|
Lars Francke |
Jul 14, 2010 |
|
Printed |
Page 62
2nd paragraph |
"The only difference that a do-while checks to see if ..."
should probably read
"The only difference is that a do-while checks to see if ..."
Note from the Author or Editor: The missing "is" is required.
|
malcolm.gorman |
Oct 12, 2009 |
|
Printed |
Page 62
2nd paragraph from the bottom |
The example should read
for (i <- 1 until 10)
Note from the Author or Editor: Good catch. Thanks!
For subsequent editions and printings, change the "0" to "1" in the 2nd to last paragraph. The example earlier on the page (the "do-while-script.scala") is correct.
|
Konstantin L?ufer |
Feb 03, 2010 |
|
Printed |
Page 62
Last paragraph |
"This should paint a clearer picture of how Scala's internal libraries compose to form easy-to-use language constructs."
should probably read
"This should paint a clearer picture of how Scala's internal libraries are composed to form easy-to-use language constructs."
Note from the Author or Editor: Yes, I like this suggested wording better.
Correction: I thought some more about what this text is actually intended to mean and the original wording is correct, if not completely clear. The meaning is that you can compose behavior easily using Scala library and language constructs. That is, they are good "building blocks". I suggest this rewording:
"This should paint a clearer picture of how Scala allows you to compose behavior from easy-to-use language constructs and internal libraries."
|
Anonymous |
Oct 07, 2010 |
|
|
66
In the match-list-script example |
I guess you wanted to print out the List so
format("%s ", head)
will have to be changed to something like
printf("%s ", head)
Note from the Author or Editor: This is an API change between Scala v2.7.X and Scala v2.8.0. Previously, format printed the output to stdout. Now, it returns a string.
Future book revisions should use printf, as suggested.
|
Lars Francke |
Jul 14, 2010 |
|
PDF |
Page 72
enumeration-script.scala |
Under version 2.8.0.Beta1-prerelease, there are deprecation warnings with the source code.
The following runs without warning:
// code-examples/Rounding/enumeration-script.scala
object Breed extends Enumeration {
val doberman = Value("Doberman Pinscher")
val yorkie = Value("Yorkshire Terrier")
val scottie = Value("Scottish Terrier")
val dane = Value("Great Dane")
val portie = Value("Portuguese Water Dog")
}
// print a list of breeds and their IDs
println("ID\tBreed")
for (breed <- Breed.values) println(breed.id + "\t" + breed)
// print a list of Terrier breeds
println("\nJust Terriers:")
Breed.values.filter(_.toString.endsWith("Terrier")).foreach(println)
Note from the Author or Editor: Yes, apparently this is an API change in 2.8. If you run the script with "scala -deprecation ...", you'll see the warnings in more detail (I wish this flag was on by default). You have to use "for (breed <- Breed.values)" instead of "for (breed <- Breed)" and similarly, "Breed.values.filter" instead of "Breed.filter" to eliminate the warnings. However, the values method isn't available in 2.7.X.
|
Xiao Yang |
Feb 12, 2010 |
|
Printed |
Page 73
The lines of output just above the last paragraph |
The book is very helpful in pointing out differences between 2.7.x and 2.8, but an interesting difference here seems to have been missed.
The output from the Enumeration example while using 2.8.0 (Beta1-RC6) is as follows:
Mon
Tue
Wed
Thu
Fri
What's interesting (in the source of the Enumeration class of course) is how the Scala library gets hold of the names of the vals.
Note from the Author or Editor: Thanks for pointing this out. I wasn't aware of this difference, but I like it ;) For the book, I think that changing
"Running this script with scala yields the following output:"
to
"Running this script with scala yields the following output (v2.7):"
is probably sufficient. A second edition could expand on the different output.
|
Sanjay Dasgupta |
Jan 06, 2010 |
|
PDF |
Page 80
Last code example |
"ButtonCountObserverSpec" should probably read "ButtonObserverSpec".
It is written, "ButtonObserverSpec" in the downloaded code.
Note from the Author or Editor: Correct, the references in the text (not the code listing) should say ButtonObserverSpec.
|
Anonymous |
Aug 13, 2010 |
|
Printed |
Page 90
2nd paragraph |
The description of overloading can be interpreted to mean that functions whose only difference is in the type of the returned value can be overloaded.
Note from the Author or Editor: Thanks for pointing this out. Yes, the paragraph could be interpreted that way, which is wrong. It would be good to add an extra sentence, perhaps in parentheses, like this:
"(If the return types are different, the list of parameters must also be different.)"
Also, the word "type" should be dropped in the phrase "The signature includes the *type* name, ..."
|
Sanjay Dasgupta |
Jan 07, 2010 |
|
Printed |
Page 90
2nd paragraph |
"The signature includes the type name, the list of parameters with types, and the method's return value."
It should probably have read as:
"The signature includes the type name, the list of parameters with types, and the method's return type."
Note from the Author or Editor: Yes, the last word should be "type".
|
Anonymous |
Aug 30, 2010 |
|
PDF, ePub |
Page 94
2nd code sample |
Subject: correction to Ch3 examples in "Programming Scala" by D. Wampler, A. Payne
Hi,
I write to let you know the syntax of Scala has changed, where the sample
code in the book has a line for printing a formatted string as,
format("%s is overpaid.\n", p)
instead, that should be,
print("%s is overpaid.\n".format(p))
Hope this helps.
Best,
Van Ly
ref:_00D708xG6._50070W2iGg:ref
Note from the Author or Editor: Yes, this is the new syntax.
|
Van Ly |
Sep 17, 2013 |
|
Printed |
Page 126
4th paragraph from the bottom |
"We mentioned companion objects briefly in Chapter 1, and we discussed
the Pair example from the Scala library in Chapter 2."
I guess "Pair" should be "Tuple". There was no Pair in Chapter2,
except the usage in the sample code during the discussion about the
Tuple .
Note from the Author or Editor: Yes, we didn't really "discuss" Pair in chapter two, just showed it as an alternative was of defining a Tuple2. I would rephrase " and we discussed the Pair example from the Scala library in Chapter 2" as "and in Chapter 2, we briefly mentioned Pair as an alternative name for a tuple with two elements."
|
Anonymous |
Mar 24, 2011 |
|
Printed |
Page 126
3rd paragraph from the bottom |
"First, recall that if a class (or a type referring to a class) and an
object are declared in the same file, in the same package, and with
the same name, they are called a companion class (or companion type)
and a companion object, respectively."
I guess "recall that if a class" should probably be "call a class". I
found this paragraph to be confusing because you "recall" the
companion class (or object) without having explained about it before.
Though you have referred to the name by examples, there was no
definition ever.
Note from the Author or Editor: I found the reference to companion objects on page 19, but it doesn't really explain what they are. So, the text on 126 should not use the misleading word "recall". It would be better for this sentence to begin: "First, if a class (or a type referring to a class) and..."
|
Anonymous |
Mar 24, 2011 |
|
|
127
widget.scala example |
The "Widget" in the regular expressions should start with a lower case "w" to be consistent with the toString method from the Widget class.
Note from the Author or Editor: Yes, lowercase "w" would be better.
|
Lars Francke |
Jul 16, 2010 |
|
Printed |
Page 132
3rd paragraph from the bottom, above the code excerpt. |
Methods "apply/unapplySeq" are defined in the companion object.
The book says it's from the List *class* as follows.
In this case, you define apply and unapplySeq ("unapply sequence") methods. Here are those methods from Scala's own List class:
Note from the Author or Editor: Yes, this was imprecise language. The sentence "Here are those methods from Scala's own List class:" should be
"Here are those methods from companion object of Scala's own List class:"
|
Goh Morihara |
Oct 20, 2010 |
|
|
147
5th paragraph |
I found this paragraph to be confusing because you "introduced" the variable "x" without ever having referred to it before. I guess all it takes is to remove the sentence: "Internally, x will be a subtype of Array[X]." as the rest of the paragraph is sufficient and can stand on its own.
Note from the Author or Editor: Yea, better wording might be "For a variable argument list of type X*, it will be converted to Array[X]."
|
Lars Francke |
Jul 17, 2010 |
|
PDF, ePub |
Page 150
The example code on the top of the page |
The example code should be implicit-conversions-resolution2.sc instead of implicit-conversions-resolution.sc. The difference between two example is:
implicit def overridingConversion(s: String): Foo = Foo("Boo: "+s)
Note from the Author or Editor: Please upgrade to the latest edition.
|
Anonymous |
Nov 07, 2015 |
|
Printed |
Page 151
top of the page |
"List[+]" should be "List[+A]".
Note from the Author or Editor: Correct, it should say +A.
|
jjinux |
Aug 21, 2010 |
|
|
177
The flatMap example |
The syntax you use for the flatMap example hasn't been explained before (and not sure if it is explained later). After asking on the IRC channel I have been told that it is a "Pattern Matching Anonymous Function". I was confused by the fact of something that looks like a function but has just a bunch of case statements without a "match".
Note from the Author or Editor: Hmm. This should be explained. We cover PartialFunctions elsewhere in the book, but the reader wouldn't know that. In future versions of the book, we should add the following paragraph after the code example:
FlatMap takes a function. We passed a special kind, called a PartialFunction. When the compiler sees the pattern matching statements inside the curly braces, as written here, it knows we are defining a PartialFunction literal. The compiler generates code that wraps this PartialFunction literal with the equivalent of "arg => arg match { /* what we wrote inside the {} */ }". This idiom is so common that Scala allows us to drop the "arg => arg match" boilerplate, in this case.
|
Lars Francke |
Jul 18, 2010 |
|
|
180
The iterable extract |
While it is a code extract I think a note would be good about the two parameter lists for all of those methods. I later found out that they have to do with currying (I believe) but it is very confusing at the time.
(btw. the trait extract on page 179 is not colored)
Note from the Author or Editor: Good point. We discuss currying a few sections later. We should add the following paragraph after the code sample.
Note that some of the methods, like foldLeft, have two argument lists! In the case of foldLeft, each of the two argument lists takes one argument. We'll discuss this in more detail shortly in the section on "Currying". For now, note that this feature is almost the same as having one argument list with several arguments, but it makes the code that calls these methods a little cleaner, as in the foldLeft example on the previous page, because we don't have to put the multi-line function literal inside the argument list with the first argument.
|
Lars Francke |
Jul 18, 2010 |
|
Printed |
Page 183
Paragraphs under "Partial Functions" |
Some of the text blurs the distinction between a "partial function" (presumably meaning instances of scala.PartialFunction) and a "partially applied function". The opening sentences of the first two paragraphs are particularly confusing.
The Glossary's entries for the two terms (on page 401) however do clarify the difference.
Note from the Author or Editor: Yes, we did not make the distinction clear between these two concepts.
|
Sanjay Dasgupta |
Aug 31, 2010 |
|
Printed |
Page 196
example actor-mailbox-script.scala |
The output on my box looks completely (and consistently) different:
I've got 6 messages in my mailbox.
I've got 5 messages in my mailbox.
I've got 4 messages in my mailbox.
The reason is quite clear, and due to the essentially asynchronous behaviour of Actors: The main thread of the script (i.e., all those lines sending the messages to countActor) happen to be executed before the thread in which the Actor loop runs ever gets going. So the 3 "how many?" messages are processed by the actor only after all of the 7 messages have queued up. (YMMV.)
I did get the output as per the book only after I introduced a little sleep() after sending each message. On my machine, 5 ms were enough to give the Actor a chance to get his act together.
No big problem here -- that's just how asynchronous life in a threaded world is! Only it might be clearer if the explanatory text did not create the impression (at least, for the unwary reader) that the output would necessary look like shown in the book. Note, in particular, that on my box the statement "the first and second lines of output are identical" does not hold. With this, also the rest of the paragraph will not become obvious from the example (although the facts are, of course, correct pe se.)
Note from the Author or Editor: I agree that we should add a sentence explaining that the output may vary from system to system and from run to run. The authors assumed a familiarity with the probabilistic nature of concurrent systems that may not be consistent amongst readers.
Thanks for the feedback.
|
Gisbert |
Jan 06, 2010 |
|
Printed |
Page 196
example actor-mailbox-script.scala |
Regarding the receipt of messages in different order (putting aside the 5 ms sleeps) and Gisbert's errata submitted:
- at the beginning of chapter 9 ("Actors in Abstract")is this statement:
"though some Actor implementations (such as Scala?s) queue messages in order."
Gisbert's output of compiled code contradicts this. (It would be helpful to ask every errata submitter which version of scala and JDK they're testing on, tho I'm not sure if JDK version makes a qualitative difference in output, rather than in benchmark times.)
- erlang provides a guarantee that messages sent from one process to another single process are received in the order sent. This is the only guarantee regarding send/receive timing that erlang BEAM provides (i.e. there is no guarantee as to timing of receipt when multiple processes send messages to one receiving process, or one process sends messages to multiple receiving processes). This may condition some people's expectations on how messages are ordered in scala, since erlang is kind of the "incumbent" message-passing model.
- If you can make a statement that scala provides no guarantees that messages are received in order sent, something like that, that's an important datapoint, i think.
(BTW, the book is superb. Congrats on that)
Note from the Author or Editor: There are bugs in this code that we'll need to revise in a subsequent printing.
|
Gene Tani |
Feb 23, 2010 |
|
Printed |
Page 198
The example "class Barber" code |
The "self." qualification for "mailboxSize" isn't accepted by the 2.8.0 compiler. Probably a 2.7 to 2.8 version change impact?
Note from the Author or Editor: This is due to an API change in 2.8 that happened right about the time we finished writing the book :^/ The mailboxSize method was made protected, scoped to the actors package, causing a spirited discussion on the scala-user mailing list (http://old.nabble.com/Actors-in-2.8-td25064760.html)
In this case, the simple solution is to delete the "self." in front of the method call. This works because the mailboxSize method is still public on the actor *object* and it returns the size of the "current" actor, which is what we need. This change works for both 2.7.7 and 2.8.0-latest.
|
Sanjay Dasgupta |
Feb 09, 2010 |
|
Printed |
Page 198
half-way down the page |
I'm not convinced that you can let the barber be the one that turns
customers away. If the barber is cutting a customer's hair, and 100 customers come, a bunch of them should leave before the barber is done cutting the customer's hair.
Note from the Author or Editor: Yes, this would be a good alternative approach.
|
jjinux |
Aug 21, 2010 |
|
|
202
You can send a message to an Actor with the ! ! method; a variant of this method allows you to pass along a partial function that is applied to the future value." |
I believe the !! is a typo and it should just be !. I through it was weird that you glossed over a new operator without explanation, but then couldn't find it anywhere in the scala api docs.
Note from the Author or Editor: The wording is not clear in this paragraph. There really is a !! method that returns a Future object that can be queried for the reply, as described in the text. The sentence should be reworded to say:
"If you send a message to an Actor with the !! method, rather than the ! method, it will return a future. A variant of this method allows you ...".
|
Grant Olson |
Sep 12, 2010 |
|
|
203
by-block-script.scala |
I don't think the code is correct. I believe it just prints the line in its constructor.
The correct way seems to be:
new Thread { override def run = { println("this will run in a new thread") } }.start
This can be seen by checking currentThread.getId or getState of the Threads.
Note from the Author or Editor: Ah, this is correct. As written in the book, it really doesn't run the print statements in a separate thread. His suggested change is correct.
|
Lars Francke |
Jul 19, 2010 |
|
Printed |
Page 222
"payroll-dsl-script.scala" example at bottom of the page |
The line "import payroll.dsl.rules_" should have a period between "rules" and "_".
|
Dean Wampler |
Sep 28, 2009 |
|
Printed |
Page 227
last paragraph |
The last paragraph of page 227 reads "The minus_deductions_for does the important work. It invokes the function literal with the individual rules and then returns the completed Paycheck instance, which is ultimately what rules.apply returns".
However, the end of the paragraph should read "..., which is ultimately what PayrollBuilderRules.apply returns".
Motivation:
The minus_deductions_for method is invoked as a consequence of the PayrollBuilderRules.apply method being invoked, not as a consequence of the rules.apply method being invoked. Thus, the Paycheck returned by the minus_deductions_for method is ultimately returned by PayrollBuilderRules.apply, not by rules.apply. The rules.apply method just returns the PayrollBuilderRules instance, which wraps the entire function literal.
Note from the Author or Editor: correct.
|
Mikko ?stlund |
Aug 29, 2011 |
|
Printed |
Page 230
above "About Parser Combinators" |
"[BNF]" should probably be changed to "[EBNF]"
|
Anonymous |
Oct 09, 2011 |
|
Printed |
Page 239
Last line of paragraph 3 |
In the line "returns the string ... We're done!", the parser output should have been "(("Buck Trends"~(2~weeks))~List())".
The correct output is shown near the top of the preceding page (#238). But the 7th line from the bottom (on page 238 itself) also has the same typo.
Note from the Author or Editor: Yes, this appears to be a formatting error that occurred when generating the PDF from our original text. So the line with "... We're done!" should have (("Buck Trends"~(2~weeks))~List()). And the same (...) expression should appear at the end of the 3rd paragraph from the bottom of page 238.
|
Sanjay Dasgupta |
Feb 10, 2010 |
|
Printed |
Page 250
Last example: "manifest-script.scala" |
The output of the script should be shown after the script, so the discussion in the subsequent paragraphs makes more sense without expecting the user to run the script beforehand. The following text should appear after the example and before the next paragraph, which begins: "WhichList tries to determine the type of list passed in...":
This script prints the following output:
List[Int]
List[Double]
List[String]
List[???]
List[???]
List[???]
|
Dean Wampler |
Sep 28, 2009 |
|
PDF |
Page 250
Manifests |
Your manifest example left me questioning the accuracy of the example.
First off the case statement should be case "Int", case "Double", instead of case "int", and case "double". Looks as if there is an errata on that already.
So in the example, I made the correction, and I also included Any type to help me understand.
import scala.reflect.Manifest
object WhichList {
def apply[B](value: List[B])(implicit m: Manifest[B]) =
m.toString match {
case "Int" => println("List[Int]")
case "Double" => println("List[Double]")
case "java.lang.String" => println("List[String]")
case "Any" => println("List[Any]")
case _ => println("List[???]")
}
}
WhichList(List(1, 2, 3))
WhichList(List(1.1, 2.2, 3.3))
WhichList(List("one", "two", "three"))
List(List(1, 2, 3), List(1.1, 2.2, 3.3),
List("one", "two", "three")) foreach {
WhichList(_)
}
I ran the example and I got:
List[Int]
List[Double]
List[String]
List[Any]
List[Any]
List[Any]
I believe that the List[Any] was produced not because the manifest couldn't determine that the type, but because a list of a list of Ints, Doubles and Strings is a list of Any. So added more to the test:
List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) foreach {
WhichList(_)
}
and this displayed correctly:
List[Int]
List[Int]
List[Int]
So as far as: "Notice that it works when the list is
constructed inside the call to WhichList.apply. It does not work when a previously constructed list is passed to WhichList.apply."
I humbly see no evidence of that, using that example.
Note from the Author or Editor: As the description in the book said, the Manifest feature was experimental in v2.7.X and it was changed in v2.8. The different behavior you point out reflects those changes.
1) The 'case "int"' should now be 'case "Int"' and the 'case "double"' should be 'case "Double"'.
2) You've found an interesting case for the List of List example. In 2.7, even when using List[List[Int]], WhichList can't correctly determine the "Int", but as you discovered, it does work in 2.8. It appears that the mixed list we show was inferred as List[List[Any]] in 2.8.
I'm not sure if the improved handling of List[List[X]] is due to improvements in the Manifest mechanism or type inference.
|
Daniel Hinojosa |
Mar 07, 2011 |
|
|
262
2nd paragraph |
"AbbrevList (...) is an abstract trait" -> it is an abstract class.
Note from the Author or Editor: Correct, it should be "class", not "trait"
|
Lars Francke |
Jul 24, 2010 |
|
Printed |
Page 262
8/10ths down the page |
"AbbrevList (the analog of List) is an abstract trait..." Actually,
it's an abstract class.
Note from the Author or Editor: Correct. It should say "abstract class".
|
jjinux |
Aug 21, 2010 |
|
Printed |
Page 265
The example code |
I'm a little confused here ... but believe that the "view" feature is not actually used by the example code. Careful examination of the code (together with some strategic tracing) seems to indicate that the conversion from A to Node[A] happens as a vanilla implicit conversion (as on page-186) when the A-typed parameters are evaluated at the function (or constructor) call locations.
In fact, the code runs perfectly well even when the views are commented out of the LinkedList definition:
case class LinkedList[A /*<% Node[A]*/](val head: Node[A]) {
def ::[B >: A /*<% Node[B]*/](x: Node[B]) =
LinkedList(bounds.::(x.payload, head))
override def toString = head.toString
}
I've tried to change LinkedList to force use of views, but the result is rather ugly:
case class LinkedList[A <% Node[A]](h: A, t: Node[A]) {
var head: Node[A] = if (t eq NilNode) h else bounds.::(h, t)
def ::[B >: A <% Node[B]](x: B): LinkedList[B] = LinkedList(x, this.head)
override def toString = head.toString
}
The view (any2Node) is invoked on the second line where "h" (an A) is assigned to "head" (a Node[A]) in the true branch of the if statement.
The code uses an auxiliary constructor, but since a corresponding apply() is not automatically generated in the case class's companion object, the first line of the client code must be changed (to explicitly invoke the auxiliary constructor):
val list1 = LinkedList(1, NilNode)
In my test code I also moved the view ("implicit def any2Node ...") from just above the definition of LinkedList to just above the client code ("val list1 = LinkedList(1 ..."). The move somehow makes the feature's magic look more believable!
Note from the Author or Editor: You're right, the example is bad, because it doesn't actually require view bounds to work. There are two reasons: 1) the body of LinkedList never uses a "bare" instance of A or B, only Node[A] and Node[B], so an implicit converter is actually not necessary. (It is necessary in the examples that use LinkedList.) 2) By declaring the implicit method any2Node before the definition of LinkedList, we would never need the view bound anyway, because that method would always get used as needed.
What the example should do is compile LinkedList in a separate file with NO implicit conversion in scope AND it should change the argument list for the "::" method to "(x: B)" (rather than "(x: Node[B])". Finally, the remaining driver script should still define the implicit method and use LinkedList as shown. If these changes are made, the example works. However, if you now remove the view bounds in LinkedList, then it will not compile, because of the "bare" x:B argument to the :: method.
View bounds are just a shorthand way of specifying that a method or primary class constructor has a second argument list with an implicit converter argument. The example doesn't show this.
To summarize, the LinkedList definition in "view-bounds-script.scala" should be moved to "node.scala" and the argument to LinkedList.:: should be changed to "(x: B)". The wording surrounding the examples should also be changed. Here is the complete change, starting with the last paragraph on page 264:
To make this more concrete, let?s use view bounds to implement a LinkedList class that uses Nodes, where each Node has a payload and a reference to the next Node in the list. Here is a hierarchy of Nodes, followed by the LinkedList class.
// code-examples/TypeSystem/bounds/node.scala
package bounds
abstract trait Node[+A] {
def payload: A
def next: Node[A]
}
case class ::[+A](val payload: A, val next: Node[A]) extends Node[A] {
override def toString =
String.format("(%s :: %s)", payload.toString, next.toString)
}
object NilNode extends Node[Nothing] {
def payload = throw new NoSuchElementException("No payload in NilNode")
def next = throw new NoSuchElementException("No next in NilNode")
override def toString = "*"
}
case class LinkedList[A <% Node[A]](val head: Node[A]) {
def ::[B >: A <% Node[B]](x: B): LinkedList[B] =
LinkedList(bounds.::(x.payload, head)) // using x as a Node[B]
override def toString = head.toString
}
This type hierarchy is modeled after ... (unchanged paragraph).
The following script uses LinkedList with Nodes.
// code-examples/TypeSystem/bounds/view-bounds-script.scala
import bounds._
implicit def any2Node[A](x: A): Node[A] = bounds.::[A](x, NilNode)
val list1 = LinkedList(1)
val list2 = 2 :: list1
val list3 = 3 :: list2
val list4 = "FOUR!" :: list3
println(list1)
println(list2)
println(list3)
println(list4)
|
Sanjay Dasgupta |
Feb 03, 2010 |
|
Printed |
Page 265
The example code |
This is just an update to my previous post on the same issue. The following part of that post ...
"The code uses an auxiliary constructor, but since a corresponding apply() is not automatically generated in the case class's companion object, the first line of the client code must be changed (to explicitly invoke the auxiliary constructor): "
... was written before a last change I made to the code of LinkedList, so is no longer applicable. However, the first line of the client code does have to be changed as described.
Note from the Author or Editor: I'll reply to his first post.
|
Sanjay Dasgupta |
Feb 03, 2010 |
|
Printed |
Page 266
Middle paragraph: "The type parameter means ..." |
The paragraph is (eliding some parts):
The type parameter means ``B is lower bounded ... view bound of B <% Node[B]. As we saw...
The ``B should be an opening double quote, followed by B and the sentence should end with the close double quote:
The type parameter means "B is lower bounded ... view bound of B <% Node[B]." As we saw...
|
Dean Wampler |
Feb 03, 2010 |
|
Printed |
Page 268
Paragraph in the middle that begins "We can also use type bounds..." |
This paragraph refers to an example later in the chapter as if it already appeared at some earlier point in the chapter. The paragraph should read as follows:
We can also use type bounds when we declare or refine the declaration of abstract types. We will see a simple example later in this chapter in "Type Projections" on page 279 where we have a declaration type t <: AnyRef. That is, t has an upper type bound (superclass) of AnyRef. AnyVal types aren't allowed.
|
Dean Wampler |
Sep 28, 2009 |
|
Printed |
Page 270
First paragraph |
The phrase "abstract types can be declared abstract or concrete" should b "member types can be declared abstract or concrete".
Note from the Author or Editor: Use the word "member" instead of "abstract", as suggested.
|
Dean Wampler |
Jun 13, 2010 |
|
Printed |
Page 270
Fifth paragraph |
The phrase "You can use abstract types as method arguments and return values within a function" is not precise enough. It should say "You can use abstract types as the types of method arguments and the return values of functions."
Note from the Author or Editor: The suggested rewording should be used in future editions.
|
Dean Wampler |
Jun 13, 2010 |
|
|
276
1st paragraph |
I believe the "extends" is wrong in the example and it should be a "with" as correctly used in the code example later
Note from the Author or Editor: Yes, in this case, "with" should be used instead of "extends".
|
Lars Francke |
Jul 27, 2010 |
|
Printed |
Page 276
Compound Types sample code |
Compound Types sample codes doesn't work because T1 and T2 aren't defined.
scala > val x = new T1 with T2 {
type z = String
val v: z = "Z"
}
I think that T1 and T2 need to be defined before the first line like this:
scala > trait T1;
defined trait T1
scala > trait T2;
defined trait T2
scala > val x = new T1 with T2 {
....
Note from the Author or Editor: Yes, the example is missing those two lines. So, as printed, it should start as follows (suppressing blank lines):
scala> trait T1
defined trait T1
scala> traitT2
defined trait T2
scala > val x = new T1 with T2 {
...
|
Anonymous |
Nov 07, 2010 |
|
Printed |
Page 280
Section on "self-type annotations" |
The sentence "In fact, you could say this =>, but it would be
completely redundant." is misleading in the context in which it appears. If you used "this" as the name for the self-type annotation, then you would not be able to reference the outer scope with it, because it would be shadowed by C3's implicit definition of "this". Hence, the sentence only makes sense in the context where you aren't using the annotation to define a scope so you can reference it in a nested scope.
Note from the Author or Editor: We should drop the last sentence in subsequent editions.
|
Dean Wampler |
Jun 13, 2010 |
|
Printed |
Page 281
Code near the bottom of the page |
Shouldn't the first "with" in the following line of code be "extends" instead?
trait App with Persistence with Midtier with UI {
Note from the Author or Editor: Yes, the first "with" should be "extends". Thanks for the catch.
|
Sanjay Dasgupta |
Feb 06, 2010 |
|
Printed |
Page 284
3rd paragraph from the bottom |
Remove the phrase "on the JVM" from the first sentence, which begins: "If you compile this with the -unchecked flag on the JVM, you'll get warnings..."
|
Dean Wampler |
Sep 28, 2009 |
|
Printed |
Page 295
Table13-2 description of transient |
"Marks a method as transient."
should probably be
"Maks a field as transient."
Note from the Author or Editor: Correctl it should be "Marks a field as transient".
|
Anonymous |
Nov 07, 2010 |
|
Printed |
Page 295
Table 13-2, uncheckedStable |
I think that uncheckedStable annotation isn't related to @volatile annotation.
Scaladoc describes this annotation like this:
When applied a value declaration or definition, it allows the defined value to appear in a path, even if its type is volatile.
Note from the Author or Editor: Yes. I'm not sure how this error got there ;) The correct text should drop the parenthetical remark: "(i.e., annotated with @volatile)".
|
Anonymous |
Nov 12, 2010 |
|
Printed |
Page 298
The example code |
Is this a version problem? I can't get the FilePrinter example to produce the output shown on page 299 unless the following line is wrapped in a "println":
format("%3d: %s\n", reader.getLineNumber, line)
Note from the Author or Editor: Ah, yes. They changed the behavior between Scala 2.7.X and Scala 2.8, which you must be using. In 2.7, the format method is defined in Predef to call Console.format, which writes to stdout. In 2.8, it calls a format method on a String support class (StringOps), which returns a formatted string. The best fix that works with both versions of scala is to change "format" to "printf".
|
Sanjay Dasgupta |
Feb 06, 2010 |
|
Printed |
Page 303
Entire page |
A new feature in version 2.8 appears to render this discussion superfluous. An enumerated Value in 2.8 can deduce its name from the name of the val it is assigned to. So the redundant naming (as in "val Head = Value("Head")") may no longer be needed.
Note from the Author or Editor: Yes, this is true (and a welcome improvement in v2.8). There is also one other difference; in 2.7.X, the last line of the script "println(HttpMethod) prints out a nice list of the defined values. In v2.8, it just calls the equivalent AnyRef.toString, which just prints the type name and memory address.
For future editions, we can say that the arguments to Value in the http-enum2-script.scala (e.g., "val Head = Value("Head")") can be omitted in Scala 2.8. Also, the last of the script, "println( HttpMethod )" does not print a list of values in Scala 2.8, so it is not a useful thing to do.
|
Sanjay Dasgupta |
Feb 06, 2010 |
|
Printed |
Page 334
8/10ths down the page |
It says "JNDI" and "JDNI". One of those is a typo ;)
Note from the Author or Editor: OOPS! Should be "JNDI"
|
jjinux |
Aug 21, 2010 |
|
Printed |
Page 342
4th paragraph |
"Ensuring has one overloaded method, ensure." should probably read "Ensuring has one overloaded method, ensuring".
It is described in Scaladoc.
Note from the Author or Editor: Thanks, the correct word is "ensuring", not "ensure".
|
Anonymous |
Nov 12, 2010 |
|
Printed |
Page 346
the bottom Paragraph |
The script file name is written as "upper.scala" in the invocation command "scala upper.scala ...", but the actual file name is "upper-script.scala".
Note from the Author or Editor: Thanks for the catch!
|
Yukinori NAKATA |
Dec 17, 2009 |
|
Printed |
Page 349
bottom |
example-script.scala:3: error: expected class or object definition
def printMessage(msg: Message) = {
^
example-script.scala:7: error: expected class or object definition
printMessage(new Message("Must compile this script with scalac -Xscript <name>!"))
^
two errors found
-------
The compilation errors should occur in line 5 and 9.
Maybe this output might have been captured with the code before adding "// code-examples/..." filename comment.
Note from the Author or Editor: Thanks. Your theory about why the numbers are wrong is correct ;)
|
Yukinori NAKATA |
Jan 13, 2010 |
|
Printed |
Page 351
Last paragraph |
"The Mac and Linux distributions also include a man page."
It appears that the Linux distribution of the JAD tool no longer includes a man page. The Mac version still includes a man page.
Note from the Author or Editor: We should just drop that sentence in subsequent editions.
|
Dean Wampler |
Jun 13, 2010 |
|
Printed |
Page 360
4th paragraph from the bottom |
"Instead, you have invoke the Other..."
should probably read
"Instead, you have to invoke the Other..."
Note from the Author or Editor: Thanks for finding this typo!
|
Yukinori NAKATA |
Dec 23, 2009 |
|
Printed |
Page 365
1st paragraph of "Scala Check" subsection |
"ScalaCheck ([ScalaCheckTool] is a Scala port of the innovative Haskell QuickCheck ([QuickCheck]) tool that supports..."
should probably read
"ScalaCheck ([ScalaCheckTool]) is a Scala port of the innovative Haskell QuickCheck ([QuickCheck]) tool that supports..."
i.e. The closing parensis for "([ScalaCheckTool]" is missing.
Note from the Author or Editor: Thanks for pointing out this typo.
|
Yukinori NAKATA |
Dec 27, 2009 |
|
Printed |
Page 365
bottom |
I wonder if "i * .1" should be "i * 1.".
It definitely doesn't match 366.4: "The toD function just converts an Int to a Double by dividing by 0.1" as mentioned by another reader.
Note from the Author or Editor: The text should say "The toD function just converts an Int to a Double by multiplying by 0.1"
|
jjinux |
Aug 21, 2010 |
|
Printed |
Page 366
1st paragraph under the example code |
"The toD function just converts an Int to a Double by dividing by 0.1."
should probably read
"The toD function just converts an Int to a Double by multiplying by 0.1.",
as the corresponding code is "def toD(i: Int) = i * .1".
Note from the Author or Editor: Doh! Yes, it's multiplication.
|
Yukinori NAKATA |
Dec 27, 2009 |
|
Printed |
Page 366
2nd paragraph from the bottom |
"Two more [_Fc_]specify[_/Fc_] classes assert that..."
should probably read
"Two more [_Fc_]specify[_/Fc_] clauses assert that..."
as they are not classes but clauses.
Note from the Author or Editor: Yes, this is correct. Thanks!
|
Yukinori NAKATA |
Dec 28, 2009 |
|
Printed |
Page 382
last line of this page and first line of the next |
Is the last line of p. 382 and the first line of p. 383 a formatting error? It seems like half the URL is duplicated.
Note from the Author or Editor: Actually, it looks correct to me. It would have been nice if the <beans> tag wasn't split across too pages.
|
jjinux |
Aug 21, 2010 |
|
Printed |
Page 383
3rd paragraph under the example XML |
"The constructor tag specifies that ..."
should probably read
"The constructor-arg tag specifies that ..."
as the example XML contains constructor-arg tag and works fine.
Note from the Author or Editor: Good catch. Thanks!
|
Yukinori NAKATA |
Jan 01, 2010 |
|
Printed |
Page 385
last paragraph of subsection "Hadoop" |
"... SMR (see [SMRa] and ([SMRb])."
should probably read
"... SMR (see [SMRa] and [SMRb])."
as an extra open parenthesis exists before [SMRb].
Note from the Author or Editor: Yes, thanks for the catch.
|
Yukinori NAKATA |
Jan 02, 2010 |
|
Printed |
Page 395
last paragraph in Context-Free Grammer |
"That is, each nonterminal can appear by itself on the lefthand side of the production the specifies it"
should be
"That is, each nonterminal can appear by itself on the lefthand side of the production that the specifies it"
Note from the Author or Editor: Correct, replace the last "the" with "that":
"... of the production that specifies it"
|
Anonymous |
Oct 25, 2010 |
|
Printed |
Page 396
The term "Covariance or Covariant" |
I think the explanation of "Covarience or Covariant" is little bit confusing and the focus of explanation is changing time to time.
It starts the statement "In the context of the variance behavior of parameterized types under inheritance" that implies an explanation of a semantic of the term, but it actually explains a syntax or a notation "... T[+A], then + is the variance annotation, and ...."
And then, at last it mentions the key concept "a type T[B] is a subtype of T[A] if B is a subtype of A".
I think the form of a easy understandable explanation is like following.
Covariance or Covariant
(What is "Covariance or Covariant"?)
(How can we write it?)
How do you think aboout it?
Note from the Author or Editor: I'll attempt to improve the wording in the next edition we write.
|
Yukinori NAKATA |
Mar 26, 2011 |
|
Printed |
Page 398
the term, Function Type |
"FunctionN[-T1, T2, ..., TN, +R]" should be "FunctionN[-T1, -T2, ..., -TN, +R]", as not only T1 but all arguments need contravariance.
For example, the definition for N = 11 is following.
trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R]
Note from the Author or Editor: Great catch. As described in the bug report, all the "T" types need a minus sign in front of them.
|
Yukinori NAKATA |
Dec 11, 2010 |
|
Printed |
Page 399
the discription of the term "Mailbox" |
The font style of "Actor model of concurrency" is italic except the first "A". Probably all of these characters might be in italic.
Note from the Author or Editor: Yes, it appears the "A" isn't italicized. Thanks for pointing this out.
|
Yukinori NAKATA |
Jan 04, 2010 |
|
Printed |
Page 400
the description of the term "Object" |
"except for the lack of constructor parameters and auxiliary parameters"
should probably read
"except for the lack of constructor parameters and auxiliary constructors",
as it might mean that the object has no constructors, and the term "auxiliary parameters" does not occur anywhere else.
Note from the Author or Editor: Doh! Yes, it should be "constructors", not "parameters". Thanks for the catch.
|
Yukinori NAKATA |
Jan 05, 2010 |
|
Printed |
Page 404
description of "Tuple" |
"Tuple are represented by TupleN class, for N between 2 and 22, inclusive."
should be
"Tuple are represented by TupleN class, for N between 1 and 22, inclusive."
Note from the Author or Editor: Yes, the number should 1, not 2.
|
OKAMOTO Kazumi |
Feb 09, 2011 |
|