Errata

Functional Thinking

Errata for Functional Thinking

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
4
chapter 4, Memoization

"In Example 4-1, I create a hash named sumCache as part of the class initialization."

"now I’m measuring how fast I can read from a hash."

"hash" should be "cache" in both cases.

xianghui dong  Aug 16, 2017 
4.8
Example 4.8

I am reading this book using Safari online so I cannot provide a page number.
The problem is with the clojure snippet:

The code

...
(let [alpha (into #{} (concat (map char (range (int \A) (inc (int \Z))))
(map char (range (int \A) (inc (int \Z))))))
...

Should instead be

(let [alpha (into #{} (concat (map char (range (int \a) (inc (int \z))))
(map char (range (int \A) (inc (int \Z))))))

When I saw the code snippet - I wondered a lot on why we should really concatenate the same range (\A..\Z) into a set.

I realised this could be a typo - and changed as given - now the clojure snippet output matches with the groovy one

user> (rot13 "homer")
"ubzre"

Atul S Khot  Mar 21, 2017 
PDF Page 13
Example 2-3

The Scala example for processing and joining words uses:

.reduce(_ + "," + _)

This would be better as:

.mkString(",")

This would be in keeping with the use of "Collectors.joining" in the Java 8 example and "join" in the Groovy example. Or else these other examples should use the equivalent reduce methods, perhaps with a sidebar indicating that many common reduce tasks have shortcuts (such as joining, sum, max, etc). This would keep these examples consistent.

Mark Bush  Mar 07, 2015 
PDF Page 18
2nd paragraph

The term "higher-order function" is used incorrectly here and in many other places in the book.

It is used to describe a lambda or anonymous function, however a higher-order function is one that either takes another function as an argument or returns one. Thus "map", "filter", "reduce", etc are higher-order functions (they take functions as arguments), but the functions you pass in (to "customize"(sic) them) are not.

Mark Bush  Mar 07, 2015 
Printed Page 30
Example 2-20

Example 2-20 is missing a closing brace.

Jaewan Kim  Jun 29, 2015 
Printed Page 30
1st Paragraph

Paragraph states that "For example, right folds can operate on infinite lists whereas left folds cannot." Right folds cannot operate on infinite lists because they accumulate starting from the right. Which is why foldright using cons with empty list is the identity function. (https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29#Folds_as_structural_transformations)

Robert Chrzanowski  Feb 06, 2016 
PDF Page 35
paragraphs 3-4

The section describes flatMap() as flattening the list it is applied to and operating on nested lists. This is not the case. It flattens the result of the map.

The thing it operates on is an ordinary list and doesn't care if the elements are lists or scalars. The function it applies produces a list for each item instead of a single item. A normal map would result in a nested list. A flatmap results in a flattened list.

That is, the code:

myList.flatMap(f)

is equivalent to:

myList.map(f).flatten()

Flatmap is used when the function you want to apply is one to many and you want all of the "many" interpolated in the final collection.

Flatten is reducing using concatenation.

Mark Bush  Mar 07, 2015 
PDF Page 36
Fold/Reduce section

The Fold/Reduce section makes a lot of use of "List.range(1, 10)". Since the List produced is not important, the equivalent could be written "(1 until 10)" which is also non-inclusive and is more consistent with the use of "(1..10)" in the Groovy examples.

Mark Bush  Mar 07, 2015 
PDF Page 36
Last 2 lines

The example should read:

List.range(1, 10).reduceLeft(_ + _)

There should be no "(0)" argument to reduceLeft...

Mark Bush  Mar 07, 2015 
PDF Page 37
2nd paragraph 2nd sentence

The reduceRight() function reduces the direction of operations
should read
The reduceRight() function reverses the direction of operations

Jaewan Kim  Jul 11, 2015 
PDF Page 45
1st paragraph

If you curry only the first argument, the return value of process(x) is a
function that accepts a single argument that in turn accepts a single argument.

This sentence sounds like the function returned by currying process(x, y, z) with just x is a function that accepts a single argument y and that argument y is a function that accepts a single argument. I think what's meant here is

If you curry only the first argument, the return value of process(x) is a
function that accepts a single argument (namely y) and returns a function that again accepts a single argument (namely z).

WIeland Hoffmann  Feb 06, 2015 
PDF Page 49
Example 3-13

In the first line

List(1, 3, 5, "seven") map { case i: Int ? i + 1 }

it should be an arrow instead of a question mark:

List(1, 3, 5, "seven") map { case i: Int => i + 1 }

Marco Ehrentreich  Jul 22, 2014 
Printed Page 57
2nd paragraph

I doubt that the runtime will swap map and filter operations, at least I would consider such behaviour incorrect if the lambdas don't get examined. The map operation can easily interfere with the filter predicate. Consider a modified example:

public String cleanNames( List<String> names ) {
if (names == null) return "";
return names
.stream()
.map( e -> "$" + e )
.filter( n -> n.length() > 2 )
.collect( Collectors.joining( "," ) );
}

If you swap map and filter, you break the filter (it would have to be changed to .filter( n -> n.length() > 1 ) to get the same result). This is despite the fact that the lambdas don't have side effects.

Hartmut Schäfer  Mar 14, 2017 
Printed Page 69
Example 4-9

As I understand Scala's mutable.Map.getOrElseUpdate() from the docs, this is not a macro but a function. In this case I would expect f(x) to get computed before getOrElseUpdate() is invoked, making the entire caching useless.

As I don't know Scala, I'm not sure if there isn't a clever language mechanism like lazy evaluation preventing computation of f(x) until the value is really needed inside getOrElseUpdate(). If there is, a comment on this in the discussion of the example would be helpful. Otherwise the fundamental difference between Scala and, e.g. Java upon execution of

cache.getOrElseUpdate( x, f( x ) )

and the implications of that could easily skip the attention of the reader.

Hartmut Schäfer  Mar 16, 2017 
PDF Page 79
4rd paragraph, after example 4-19

In 3rd paragrapf, after example 4-19, there is an observation about code of example 4-18, that says:

"Last, I use the take() method to force evaluation of only the first two elements."

But, the code execute the method head(), that execute 'list.call()', at this moment, are not all the elements being evaluated?

If yes, by call take(2) should evaluate all elements of the list instead the first two?

Maurício Mussatto Scopel  Feb 09, 2017 
PDF Page 145
Paragraph 3

The description of "orthogonal" suggests that lines at right angles don't meet, however they do if they are in the same plane. They meet at a single point.

Mark Bush  Mar 09, 2015 
PDF Page 151
Paragraph 2

Missing full stop between "styles" and "Fortunately".

Mark Bush  Mar 09, 2015 
Mobi Page 786
Provided Kindle location as page number

Hi.

In example 2-10, should _cache be static? Otherwise, shouldn’t it just be an int?

Best,
Oliver

Oliver BIer  Jan 29, 2018