By Developers, For Developers

Historical errata for Programming Clojure

PDF PgPaper PgTypeDescriptionFixed onComments
11TYPO

bullet point 2 under “1.2 Clojure Coding Quick Start”, towards the bottom says, “While you are working through the book, use the version of Clojure tied the book’s sample code.”

Suggest “…use the version of Clojure tied to the book’s sample code.”

Yes, I know it’s minor, but figured I’d pass it along :)

2011-09-24
11TYPO

In the bullet point describing Leiningen, the sentence : “While you are working through the book, use the version of Clojure tied the book’s sample code.” doesn’t make sense grammatically. Perhaps you meant “… use the version of Clojure tied to the book’s sample code.”

2011-09-24
11ERROR

project.clj is missing from the github repository stuarthalloway/programming-clojure, and therefore “lein deps” doesn’t work. The README for the repository suggest that this might not be necessary? From the README, “All the necessary libraries are already installed.”

2011-10-18The repo on github has not been updated for this edition quite yet. It will be soon though.
17ERROR

Using the book code downloaded from the Pragmatic site, “lein test” fails with:

Exception in thread “main” java.lang.RuntimeException: No such var: c/message, compiling:(examples/test/chat.clj:9)

2011-10-18Thanks for pointing this out. These will be fixed up for the next beta cut.
19SUGGEST

In the output for (doc str) the word empty is highlighted like it is referring to a function in a code context, but it isn’t referring to a function (not even sure if str being highlighted in that output makes sense?).

2011-09-24
43ERROR

The evaluation of “(import ’(java.io InputStream File))” isn’t nil as in the book at the end of page 43, but is the last class imported, “java.io.File” (perhaps this is new to 1.3?)

2011-09-24
42SUGGEST

Found another instance of a “word” being highlighted as if it were a function when it isn’t being referenced as one in the require form just prior to the defn for ellipsize. str in the :as clause is highlighted, but I don’t think it should be. It’s subtle, but could be confusing. Might be worth doing a search for all instances of Clojure functions and confirm that they are actually being referred to as functions when highlighted as such?

This is a case where str is a function in clojure.core and the clojure mode highlighting is picking that up. I'll see if they can add a case for this in the syntax highlighter.
44OK

The paragraph starting “The simple form of require shown earlier…” later says “This can be confusing, because it does not make explicit which names are being referred to.” It’s ambiguous as to whether using fully qualified function names are better than using :as or if there is another way to require exactly only the functions needed (even just a hint that this might be covered later).

2011-12-16
44OK

Might be worth reminding readers, after using (in-ns ’myapp) that they may want to switch back into ’user sometime before the reference to “(find-doc ”ns-“)”.

Tripped me up, but I knew enough to figure it out. I suspect that someone learning for the very first time might miss that…

2011-12-16
52OK

While comparing the imperative and functional versions of the “indexOfAny” function it would be insightful to discuss the efficiency too. It is easy to see that the imperative version returns as soon as a match if found (it doesn’t traverse the whole string unless necessary). On the contrary it is not clear how much work the functional version ends up doing (how much the laziness of collections helps). The text left me wondering if there is a price being paid for all the good properties of the functional version.

2011-12-16
17OK

I can neither require ‘clojure.java.io’ nor ‘examples.introduction’

FileNotFoundException Could not locate examples/instroduction’__init.class or examples/instroduction’.clj on classpath: clojure.lang.RT.load (RT.java:430)

Robert

2011-10-19It looks like you did not use lein deps to grab the dependencies or lein deps to start your repl. clojure.java.io is part of Clojure in the version used for this edition (1.3). examples.introduction is something that will have to be added to the classpath when booting a repl. Leiningen takes care of all of these things.
AllSUGGEST

My ebook reader on android (aldiko) can’t import the epub version into my library, because some information seems to be set like in the first edition.

119TYPO

Formatting problem (words running together):

“…take a single parameteran
instance of the data type itselfand return…”

2011-10-19
973SUGGEST

(page number is from iphone ibooks) In section 9.1, at the end of the motivation section for using a multimethod for println, the text reads “The solution, of course, is multimethods.”. Couldn’t the solution in this case also be protocols?

2011-09-27Yes, that is correct. This will be clarified by the next beta release.
1253OK

This is purely a suggestion as you might have a reason for not doing it this way, but would it be possible to use a form similar to that shown in Joy of Clojure

(+ 2 2)
;-> 4
or
;;-> 4

for code examples? I ask because then the people can just copy and paste examples into the repl and try them out/modify them.

2011-12-16
130OK

user=> (assoc (Note. :D# 4 1/2) :pitch :Db :duration 1/4)
#:user.Note{:pitch :Db, :octave 4, :duration 1/2}

The assoc should have changed the duration in the result to 1/4.

2011-12-16
132OK

In the ‘play’ method, notes appear to continue to play even when successive notes are sent to the channel. This can be more easily heard if one uses a Midi instrument with a long decay time: the notes seems to “pile up” on one another until the sound becomes a noisy mess. The following implementation of the ‘play’ method sends a noteOff message after the sleeping thread wakes up. This seems to result in a cleaner play.

(play [this tempo midi-channel]
(let [ velocity (or (:velocity this) 64)
keynum (key-number this) ]
(.noteOn midi-channel keynum velocity)
(Thread/sleep (to-msec this tempo))
(.noteOff midi-channel keynum)))

2011-12-16
114TYPO

The last sentence of the chapter refers forward to a “next chapter” which has is no longer the “next chapter” in the new edition of the book. Instead, the sentence should refer forward to Chapter 6.

2011-10-18
116TYPO

“our versions of spit and slurp, called gulp and expectorate, respectively,”

should instead be

“our versions of spit and slurp, called expectorate and gulp, respectively,”

since expectorate is a synonym for spit and gulp is a near-synonym for slurp.

2011-10-18
132OK

Footnote 4 “Notice more than one pitch maps to 1, 3, 6, 8, and 10.” is potentially confusing.

Readers who don’t know enough music theory will have no idea what C# and Db means, and will therefore not know why the pitches map onto another, and may therefore the footnote is of no help to them.

Readers who do know music theory will take it for granted that C# and Db are the same thing, and therefore the footnote is superfluous to them.

Actually, this is a weakness of the entire code example: choosing an esoteric domain such as musical notes, MIDI pitch numbers, velocities and the like has its drawbacks.

On the other hand, more commonly known domains such as Order, Account and the like have been done do death in computer books…

2011-12-16
151ERROR

I may be wrong but the rebinding

(binding [foo 42] foo)
-> 42

is only possible in Clojure 1.3 after explicitly defining

(def ^:dynamic foo 10)

and not

(def foo 10)

2011-10-18
55TYPO

Last sentence “The next chapter…” is no longer correct since this chapter is removed.

2011-10-19
60OK

First code sample is not correct. fname and lname are reversed. Correct code is:

(first {:fname “Aaron” :lname “Bedra”})
-> [:fname “Aaron”]
(rest {:fname “Aaron” :lname “Bedra”})
-> ([:lname “Bedra”])
(cons [:mname “James”] {:fname “Aaron” :lname “Bedra”})
-> ([:mname “James”] [:fname “Aaron”] [:lname “Bedra”])

2011-10-18If you take a look just a bit down the page you will find \n \n"Maps and sets have a stable traversal order, but that order depends on implementation details, and you should not rely on it" \n \nConceivably this could return in any order, and in fact, always returns for me the way the book currently demonstrates. \n
136TYPO

Section 5.7 Wrapping Up section claims that the next thing to be explored is Multimethods but these have been moved to Chapter 9.

2011-11-23
9177TYPO

Code example for Seq-ing XML at bottom of page is:

(parse (java.io.File. “examples/sequences/compositions.xml”))

However, the proper path to compositions.xml is “data/sequences/compositions.xml”

(I accidentally submitted this for the 1st ed of the book as well… apologies)

2011-11-23
262ERROR

You’ve referenced Bill Clementson’s page for setting up Clojure with Emacs, etc. There’s a note at the end of that page:

Update-2009-05-28: There have been changes made to Clojure since this post was written and much of the material in this post is now out-of-date.

so I suspect that page isn’t very useful anymore?

2011-12-11Yes, you are correct. The entire appendix is out of date. The next beta will have an up to date appendix with correct links to the current information.
200SUGGEST

Refers to closure.contrib.lazy-xml - better to refer to new contrib?

2011-12-15
171TYPO

“A thing is simple if it it not compound.”

instead, should be “A thing is simple if it is not compound.” ?

2011-11-22
30OK

In the book, it states “The hello function of the previous section is pure; that is, it has no side effects.” In some of my previous studies of functional languages (esp the little Haskell I did), it always called I/O, especially to some sort of stream, a side effect. Do you think you could include a little discussion about what does/does not constitute a side effect here, perhaps as a footnote?

2011-11-23The function you are referring to is actually a pure function. The REPL in this case is not. The result of calling the function at the REPL prints to the screen, but it is not the function itself doing this. This is worthy of a discussion, but we don't think it is necessary this early in the book
32OK

Do you think you could describe what the difference between do and dosync is for this example? The lack of “sync” with just plain do makes me think this isn’t going to be thread-safe, yet you explicitly state that it is. I realize there is a link to the other chapter here, but it’d be nice to have info here about why one example used dosync but the other does not.

2011-12-16
45OK

It might be worth mentioning that #“…” is the syntax for a regular expression just in case someone doesn’t realize that. Otherwise #“\\?$” might be confusing.

2011-12-16
49ERROR

The book states “If you call a function with an incorrect number of arguments, Clojure will throw an IllegalArgumentException.” To me it looks like the exception is an ArityException?

2011-11-23Good catch. This was left over and didn't get updated
58ERROR

The error given when you try to resolve File/separator is “-> java.lang.Exception: No such namespace: File”. The error I am getting is “CompilerException java.lang.RuntimeException: No such namespace: File, compiling:(NO_SOURCE_PATH:0) ” on Clojure 1.3.0 in the repl.

2011-11-23
59ERROR

On page 59 the PDF states: “In order to map split into the current namespace, call require on splits’s names- pace and give it the alias str:
(require ’[clojure.string :as str])
-> nil

This does not bring split into the current namespace. It still has to be referred to with str (str/split).

2011-11-23
4126OK

The code sample says this:

(class (* 1000N 1000 1000 1000 1000 1000 1000 1000))
-> clojure.lang.BigInt

but when I copy and paste I see this:

user=> (class (* 1000N 1000 1000 1000 1000 1000 1000 1000))
java.lang.NumberFormatException: Invalid number: 1000N
1000
java.lang.Exception: Unmatched delimiter: )
java.lang.Exception: Unmatched delimiter: )
1000
1000
1000
1000
1000
1000

Removing N from the first 1000 fixes it.

Thank you

2011-11-23This is because you aren't using the version of Clojure that this book is targeting. We explicitly target Clojure 1.3 and higher since 1.3 is the current version of Clojure. If you follow the instructions in the Book you can obtain the sample code and the correct version of Clojure.
4227OK

Code sample is as follows:

(println “another\
multiline\
string”)
| another
| multiline
| string
-> nil

as far as I can tell “| ” would need to be added to show output as show e.g.:

user=> (println “| another\
| multiline\
| string”)
| another
| multiline
| string
nil

2011-11-23This is just a misunderstanding of how to interpret the REPL output. Early in the book we explain how to read the book. We explain that the " | " is used for multiline return values on the REPL.
7460OK

The results of these two samples pieces of code are swapped:

(first {:fname “Aaron” :lname “Bedra”})
-> [:lname “Bedra”]

(rest {:fname “Aaron” :lname “Bedra”})
-> ([:fname “Aaron”])

2011-11-23This is not actually the case. The text following the example states: \n \n"Maps and sets have a stable traversal order, but that order depends on imple- mentation details, and you should not rely on it. Elements of a set will not necessarily come back in the order that you put them in:" \n
123109OK

In the definition on my-even? and my-odd? mutual recursive definition, you should “abs” n before dec it. Otherwise if you pass a negative number to either of them, you have get an infinite loop.

regards
mimmo

2011-12-16
225225TYPO

on thte -> on the

2011-11-23
7791TYPO

In The example below, the path is wrong.

(use ’[clojure.xml :only (parse)])
(parse (java.io.File. “examples/sequences/compositions.xml”))

Should be instead:
(use ’[clojure.xml :only (parse)])
(parse (java.io.File. “data/sequences/compositions.xml”))

2011-11-23
121107OK

aside from the same infinite-loop caused by my-even?/my-odd? if you call parity with a negative integer, parity function returns 0 or 1. I would have used false and true, instead. This way also the trick (- 1 par) inside the recur call, would be easier to be read as (not par). Am I wrong?

regards
mimmo

2011-12-16
122108ERROR

The reference to Tail Recursion is wrong, because the tail-fibo has a different definition from the from trampoline-fibo

regards
mimmo

2011-12-15
4126OK

(class (* 1000 1000 1000))
-> java.lang.Long

Result that I get:

-> Java.lang.Integer

2011-11-23This is because you aren't using the version of Clojure that this book is targeting. We explicitly target Clojure 1.3 and higher since 1.3 is the current version of Clojure. If you follow the instructions in the Book you can obtain the sample code and the correct version of Clojure.
4126OK

Book:

(class (* 1000N 1000 1000 1000 1000 1000 1000 1000))
-> clojure.lang.BigInt

I get (after removing the N after 1000, since that doesn’t work for me in Clojure 1.2):

-> Java.math.BigInteger

2011-11-23This is because you aren't using the version of Clojure that this book is targeting. We explicitly target Clojure 1.3 and higher since 1.3 is the current version of Clojure. If you follow the instructions in the Book you can obtain the sample code and the correct version of Clojure.
11OK

“While you are working through the book, use the version of Clojure tied to the book’s sample code.” - the previous edition came with Clojure and some scripts, but this edition doesn’t have that. Is this sentence obsolete?

2011-11-23The book ships with a leiningen project file which allows you to package all of the dependencies up inside the sample code. The steps for doing so are already layed out in the book.
12ERROR

“All scripts in the book should be launched from a console in the root directory of the sample code. Do not navigate into the bin directory, and do not click the scripts from a Windows environment.” - relates to the scripts provided as part of the code for the first edition.

2011-11-22
26ERROR

“Clojure’s approach to arbitrary-sized integers is simple: just don’t worry about it. Clojure will upgrade to BigInteger when you need it.” - this isn’t the case if you omit the N in the example that follows - you get an arithmetic overflow. The N suffix appears to be making the first argument a BigInt, in which case its not surprising that the multiplication is done with BigInteger.

2011-12-11This is being addressed. We are going to say something short in the exploration chapter about how to hint, and elaborate the reasoning behind Clojure's choices in the Java Down and Dirty chapter.
26TYPO

URLs in footnotes (as on this page, but there are others) are missing the ‘:’ after ‘http’. The linked URL itself is correct, i.e. the hyperlink works, but the ‘printed’ URL lacks the semicolon.

What version are you using? I don't see this in the pdf version.
31SUGGEST

At the bottom of this page, the defrecord returns user.Book. Could you explain why it isn’t user/Book, or give a forward reference to where this is explained?

2011-12-15
32OK

“Once you instantiate a Book, it behaves almost like any other map:” - whereas (:title b) returns the title, (b :title) doesn’t - user.Book cannot be cast to clojure.lang.IFn. That’s not “almost like any other map”.

2011-12-16
37OK

In the example showing a locally-scoped named function using let:

(let [indexable-word? (fn [w] (> (count w) 2))] …

why did you go back to the long form, rather than using the shorthand (> (count %) 2) ?

The reader may be left wondering if the shorthand form is only usable in certain contexts. (I felt the need to check!)

2011-12-16
1ERROR

The cover on the epub version on page 1 on the nook touch is not scaled to the visible area of the nook.

17TYPO

In the epub version on the nook touch, footnotes 3 and 4 on page 17 do not have the full url it stops after the “//”.

11ERROR

“From the root of the example code folder, run lein deps” - breaks at the moment, as the dependency [org.clojure.contrib/standalone “1.3.0-SNAPSHOT”] is not found. There is some discussion in the forum about this - it is possible for readers to work around it by commenting out that line in project.clj in the root directory:

; [org.clojure.contrib/standalone “1.3.0-SNAPSHOT”]

The tests provided with the examples then break… I don’t know where, as I work forward through the book, I’ll actually run into the need for this dependency.

This is a big stumbling block for readers.

2011-12-15The standalone contrib is being pulled out of the book. The dependency has been removed and when the final version ships, it will no longer be a dependency and its absence will no longer break anything.
39OK

“The var special form returns a var itself, not the var’s value:” - please also mention how vars can be dereferenced (like refs - we saw the use of deref and @ in an example in the Getting Started chapter).

2011-12-16
48TYPO

In the epub version on the nook touch, Table 1, the underline of “Using Numeric Types” for the link is not under that part of the text, but spans the whole part of the line that is before that text.

50TYPO

“INSERT SECTION HERE” is the text.

On page 50 of the epub version on the nook touch, the last sentence of “Using Numeric Types” section, which is right before the “Symbols” section, has “For now don’t worry about the N at the end of the first number, we’ll get to that in INSERT SECTION HERE.”

2011-11-23
125OK

page 125 in epub on nook touch. When it is talking about the Basis and Induction of the Fibonaccis, it uses the character ‘F’.
"Basis: F, the zeroth Fibonacci number, is zero. F, the first Fibonacci number, is one.

Induction: For n>1, F = F + F."

Should these F’s read as F, F’, and F’’, of F0, F1, Fn, Fn –1, and Fn-2?

2011-12-16
126OK

Page 126 of epub on nook touch. When discussing stack-consuming-fibo, the text reads, “Good so far, but there is a problem calculating larger Fibonacci numbers such as F:”. Should that ‘F’, be “1000000”, which is the parameter shown in the REPL text immediately below?

2011-12-16
157OK

Protocol definition for IOFactory. When this is being setup the make-reader/make-writer throws an IllegalArgumentException, depending on if it is the input or output stream. Would it make more sense to have two different protocols that are defined, one an IOReaderFactory and one and IOWriterFactory. Does the something like the Interface Segregation Principle match to defining Protocols, being don’t define a Protocol method, if it doesn’t support all methods on the protocol.

2011-12-16
161TYPO

Page 161 of epub on nook touch. The cryptovault.clj code formatting is off with the line wraps weird. The “… define method body here …)” is having wrapping or newline issues. It winds up displaying, with the ‘/n’ for where the line breaks, “../n. define method body here ../n.)”. It is doing that on the init-value, vault-output-stream, vault-input-stream method declarations.

78TYPO

Page 78 on epub on nook touch. Table 2. is getting cut off. the table title stops after “functional”, and the last column is “Variables”. These may be the last things in the table, but the border is not showing so I am unable to tell if there are or not.

109TYPO

Page 109 in epub on nook touch. The section title for 3.5 is cut off from rendering, and does not wrap. It shows “3.5 Calling Structure-Specific Func-”, the “tions” part is not displayed at all.

150TYPO

Page 150 in epub on nook touch. Chapter 5. The title of the chapter is cut off and not rendering the complete chapter name. It is rendering “Protocols and Data-”.

130TYPO

The Sharp is not getting rendered after the C and the flat is not getting rendered after the D. Those are non-printable characters it would seem. In the PDF it is just showing a space, and when I look at it on the nook touch, it is showing a the non-printable unfilled rectangle. It is in the sentence: “The pitch will be represented by a keyword like :C, :C#, :Db, which represent the notes C, C (C sharp), and D (D flat), respectively.”

11TYPO

• Leiningen. …


… If you alredy have

already

2011-11-29
17TYPO

but none of them are the key to thinking

change to

but none of them is the key to thinking

2011-11-29
11TYPO

Leiningen is misspelled as Leiningnen
• Leiningen. Leiningen is a tool for managing

the Clojure space. You will use Leiningnen
…………………………..

2011-12-11
51TYPO

the difference is misspelled as thedifference

What accounts for thedifference?

2011-12-11
131TYPO

between is misspelled betwen

One difference betwen records and maps is that …
……………..^

2011-12-11
141TYPO

instantiating is misspelled as instatiating

Download src/examples/chat.clj
(defrecord Message [sender text])
Now, you can create messages by instatiating the record

2011-12-11
202TYPO

painstakingly-create-array is misspelled as paintakingly-create-array

(defn painstakingly-create-array []
(let [arr (make-array String 5)]
(aset arr 0 “Painstaking”)
(aset arr 1 “to”)
(aset arr2 “fill”)
(aset arr 3" in“)
(aset arr 4 ”arrays")
arr))
(aget (paintakingly-create-array) 0)
……..^

2011-12-15
225TYPO

framework is misspelled as frameowrk and
the is misspelled as thte
in the below paragraph

Clojure’s test capabilities are lightweight and easy to use. But what if you
have a significant investment in a Java testing frameowrk? Fear not, just test
with whatever framework you already use. That’s the benefit of being on thte
JVM. To other callers, Clojure code looks like any other Java code.

2011-12-11
227TYPO

guarantees is misspelled as guarantes

The timestamp var gets the current time in a JDBC-friendly format. The let
binding guarantes that both records have the same created_at value.

2011-12-11
249TYPO

unordered is misspelled as unorderded

(defn matches
“Given a score, returns total number of exact plus
unorderded matches.”
^

2011-12-11
251TYPO

function is misspelled as funcion

The body of a defspec has access to the arguments by name, just like a normal
funcion.

2011-12-11
255TYPO

Luckily is misspelled Luckly

Let’s start by opening src/clojurebreaker/views/welcome.clj. Change the /welcome page
to just /. We need a way to put something in the session if it isn’t already
there. Luckly, noir has session/put! and session/get. Let’s use them

2011-12-11
256TYPO

Remember is misspelled as Remeber

This is everything we need to start our game. We just need to go back to our
view and wire up the code. Remeber that test.generative can also create your
game secret, so feel free to use it instead of the function above. This is just
to demonstrate another way of creating a secret.

2011-12-11
256TYPO

solution is misspelled as soltion
on the last sentence of the page.

You should see a different game soltion.

2011-12-11
257TYPO

defpartial is misspelled as defparital
In the sentence following the code.

(defpartial board []
(form-to [:post “/guess”]
(text-field “one”)
(text-field “two”)
(text-field “three”)
(text-field “four”)
(submit-button “Guess”)))
The defparital macro is quite useful here, because it is used just like a regular

2011-12-11
258TYPO

disappear is misspelled as dissapear

This will add something to the session for the
request immediately following to consume, and then it will dissapear.

2011-12-11
48ERROR

Can’t turn past page 48 on the kobo ebook reader. Crashes the reader and forces a reboot. If I go to page 100, and then attempt to go to page 50, it reboots. Using Acrobat digital editions, it’s the table on page 48 of the epub that it can’t reach.

71OK

ordinals-and-primes in section 3.3 is an example of holding the head, which makes untrue the statement that “ordinals-and-primes fits into memory just fine, because it is lazy”.

It can be avoided if both primes and ordinals-and-primes are changed to be functions that return new sequence instances, e.g:
(def ordinals-and-primes (map vector (iterate inc 1) primes))
becomes
(defn ordinals-and-primes [] (map vector (iterate inc 1) primes))
and the call would become:
(take 5 (drop 1000 (ordinals-and-primes)))

Or emphasize that the current form will use up memory, and that can be an advantage because subsequent calls have access to the pre-generated results. Both patterns, holding-the-head and memory-releasing, have valuable but different applications.

I wrote about the issue in the discussions section, with a simpler example.

2011-12-16
146OK

Perform fails for me with the error “NullPointerException clojure.lang.Numbers.ops (Numbers.java:942)”. OSX Lion running standard system version of Java and Clojure 1.3.

2011-12-16
170ERROR

The :use statement for the KeyEvents gives an error:

FileNotFoundException Could not locate clojure/contrib/import_static__init.class or clojure/contrib/import_static.clj on classpath: clojure.lang.RT.load (RT.java:430)

Using Leiningen and Clojure 1.3 on OSX Lion with Java 1.6.

2011-12-15
17TYPO

The phrase “A thing is simple if it it not compound” should read “A thing is simple if it is not compound”

2011-12-15
32OK

The following bit of code does not evaluate:
(->Book “Anathem” “Neal Stephenson”)
I get the following error:
java.lang.Exception: Unable to resolve symbol: ->Book in this context (NO_SOURCE_FILE:66)

When I type the following code:
(Book. “Anathem” “Neal Stephenson”)
Everything works fine:
#:user.Book{:title “Anathem”, :author “Neal Stephenson”}

2012-02-22This is because you are using an out of date version of Clojure. The book targets Clojure 1.3.0 and higher. The -> function was introduced in 1.3.0.
16TYPO

“Atoms (and all other Clojure referene types)” => Should be “Clojure reference types”

2012-02-12
60OK

(first {:fname “Aaron” :lname “Bedra”})
-> [:lname “Bedra”]
Should be:
-> [:fname “Aaron”]

(rest {:fname “Aaron” :lname “Bedra”})
-> ([:fname “Aaron”])
Should be:
-> ([:lname “Bedra”])

2012-02-22This has been addressed in previous comments. Either display of this is actually correct. There is no order preservation and the result could come back in the way described in the book as well as what is described here.
32OK

UPDATE: Regarding my previous erratum post, I checked the version of Clojure I am running. The version is 1.3.0. I am still getting this error after running ‘lein repl’, using Leiningen v1.6.1.1.

“The following bit of code does not evaluate:
(->Book ”Anathem" “Neal Stephenson”)
I get the following error:
java.lang.Exception: Unable to resolve symbol: ->Book in this context (NO_SOURCE_FILE:66)"

2012-02-22This means that you have not properly defined the Book record. There is an error in your program somewhere before you make that call.
159ERROR

Text says “…we can create an instance with the same
’postfix-dot’ syntax used to create Java objects” but the example does not use ‘postfix-dot’ syntax. Instead it uses some unexplained syntax which only works for Clojure 1.3.x:

user=> (def vault (->CryptoVault “vault-file” “keystore” “toomanysecrets”))

2012-02-12
44ERROR

Very minor issue, since it’s an example that returns an error anyway:

(split “Something,separated,by,commas”)

This doesn’t have the necessary regex argument.

2012-02-12
45ERROR

(find-doc “ns“)
This won’t work, since we have changed to a new namespace and haven’t required clojure.repl. It should be the following:
(clojure.repl/find-doc ”ns
”)

2012-02-12
47ERROR

(javadoc java.net.URL)
Since we’ve changed namespaces several times, this likely won’t work without being fully qualified with clojure.java:
(clojure.java/javadoc java.net.URL)

2012-02-12
69OK

at the end of the page
“As an example of how much more general the functional index-of-any is, you could use code what we just wrote to find the third occurrence of “heads” in a series of coin flips:"

the “use code what we just wrote” should probably be “use code that we just wrote”

87OK

It might help clarify the power of “for” from map in the example by showing how map differs.

user=> (map #(format “%c%d” %1 %2) “ABCDEFGH” (range 1 9))
(“A1” “B2” “C3” “D4” “E5” “F6” “G7” “H8”)
user=> (for [rank (range 1 9) file “ABCDEFGH”] (format “%c%d” file rank))

108ERROR

Not sure how significant this is, but I get different exceptions than the ones printed in the book. For example:
Statement executed: (my-even? (* 1000 1000 1000))
Exception in book: StackOverflowError clojure.lang.Util.equiv (Util.java:42)
Exception I get in REPL: StackOverflowError clojure.lang.Numbers$LongOps.equiv (Numbers.java:490)

2012-02-12
166OK

This may or may not be a technical error but even when copy-and-pasting sample code (and/or typing it manually from the book) I get the following message twice:
user=> CompilerException java.lang.RuntimeException: Unable to resolve symbol: this in this context, compiling:(NO_SOURCE_PATH:21)

120OK

“complect” (also on p 238) is a rare and unnecessary word. Perhaps “muddle” would be better?

2012-02-22Although seemingly rare, the use of complect actually has some history in the Clojure community.
144TYPO

user=> (assoc (Note. :D# 4 1/2) :pitch :Db :duration 1/4)
#:user.Note{:pitch :Db, :octave 4, :duration 1/2}

should read:
user=> (assoc (Note. :D# 4 1/2) :pitch :Db :duration 1/4)
#:user.Note{:pitch :Db, :octave 4, :duration 1/4}

2012-02-12
15OK

The hello user with memory example is incomplete and so is the associated source code. It seemed fine in the previous release (i.e. b3).

201OK

You use ::acc/Checking in the namespace corresponding to the one aliased to acc in namespace user. Besides this, I think it is confusing to use :: in namespace qualified keywords.

159ERROR

The page mentions creating an instance using the “postfix-dot” syntax, but uses a different syntax: (->CryptoVault “a” “b” “c”)

2012-02-12
166ERROR

At the end of extend-type Note, there is one close bracket too many, closing off the extend-type expression (which continues into key-number and play).

Also, at the end of the play expression, there is one close bracket missing, probably the one from to-msec.

2012-02-12
271SUGGEST

Add TextMate as an editor with the bundle: swannodette/textmate-clojure found on github

2012-02-12
159TYPO

I think
(def vault (->CryptoVault “vault-file” “keystore” “toomanysecrets”))
should be
(def vault (CryptoVault. “vault-file” “keystore” “toomanysecrets”))
because the text says “…we can create an instance with the same ’postfix-dot’ syntax used to create Java objects” immediately before that line of code.

2012-02-12
91TYPO

The URL link in footnote 2 produces a “404 Page not found” error.

2012-02-12
91ERROR

The link to Phil Bagwell’s “Ideal Hash Tree” paper footnote is now lampwww.epfl.ch/papers/idealhashtrees.pdf

2012-02-18
134ERROR

The sentence “When you call def or defn, you create a dynamic var, often called just a var.” is somewhat misleading.

A var is only dynamic if it has the :dynamic meta attribute set.

32ERROR

I also tested the code and the following does not work
(defrecord Book [title author])
(->Book “title” “author”)

I then tried the following and it worked.
(Book. “title” “author”)

96ERROR

In the tail-fibo example:

(fib 0N 1N n)))

Causes this error in lein repl:

java.lang.NumberFormatException: Invalid number: 0N
java.lang.NumberFormatException: Invalid number: 1N
java.lang.Exception: Unable to resolve symbol: n in this context (NO_SOURCE_FILE:0)
java.lang.Exception: Unmatched delimiter: )
java.lang.Exception: Unmatched delimiter: )
java.lang.Exception: Unmatched delimiter: )

Changing to:

(fib 0 1 n)))

Makes the example work though you’re not getting BigInt literals.

System: Max OSX Snow Leopard
Lein: Leiningen 1.6.2 on Java 1.6.0_29 Java HotSpot™ 64-Bit Server VM

49SUGGEST

The use of -> to represent the result of an evaluation is somewhat confusing as there is a macro that uses same symbol. So if you try searching the book to find what -> means you end up with a lot of matches.

This is most confusing at the bottom of PDF page 48/top of PDF page 49 where you instantiate a Book instance with:

(def b (->Book “Anathem” “Neal Stephenson”))

Without explaining what the -> macro does (and neither is it defined in the index) .

Hope this helps.

60TYPO

Example on page 60 where you are explaining how maps can be treated as sequences too:

(first {:fname “Aaron” :lname “Bedra”})
-> [:lname “Bedra”] // Should Be: -> [:fname “Aaron”]
(rest {:fname “Aaron” :lname “Bedra”})
-> ([:fname “Aaron”]) // Should Be: -> [:lname “Bedra”]

Looks like the results got mixed up

29SUGGEST

Where is says “To run Clojure and the code in this book, you need two things:”
I think it would be beneficial to say you need 3 things instead, with the third being a copy of the code repository for this book. I know this information is clarified shortly below where it says “See Section 6…” but when skim reading (like I was doing) it gives the appearance that section 6 is, in fact, much further down in the book as this is chapter 1 and thus the information won’t be needed until later. This caused some confusion for me later on in the book when I was trying the ”->Book” example in one of the later sections and it didn’t work because I hadn’t used leiningen to get the core dependences I needed. I believe by putting the repository for the code as a third dot point and by not referring to it as “Section 6” it would make the reader pay more attention that this process is essential to learning with the book; especially if they are skimming the first chapter as I was doing.

174160TYPO

src/examples/cryptovault.clj

(init-vault [vault]

should read

(defn init-vault [vault]

175161TYPO

The two method definitions in the code listings are missing the defn:

(vault-output-stream [vault] SHOULD READ (defn vault-output-stream [vault]

and

(vault-input-stream [vault] SHOULD READ (defn vault-input-stream [vault]

10SUGGEST

In the book it states, "…but notice that in the following code the Clojure version has both fewer dots and fewer parentheses than the Java version:

// Java
“hello”.getClass().getProtectionDomain()

; Clojure
(.. “hello” getClass getProtectionDomain)"

I count two dots in both sets of code. If there was one more function call in the example, then it would seem more accurate saying fewer dots and fewer parentheses.

96SUGGEST

Under the section Tail Recursion, in the code listing for the ‘tail-fibo’ function, the formatting rules appear to be that the bold magenta font is used for functions, special forms and macros… and normal black font for the rest. If this is the case, then the lexically bound formal parameter ‘next’ should not be in bold magenta font, as it’s confusing for the reader. Initially it makes you think it’s a function, when it’s not.

16ERROR

Link for the Github Repo in the footnote probably isn’t the up to date code. Please update it with the latest or totally remove it. Wasted an hour on it when i saw that the repo was last update “6 months ago”

150TYPO

very very minor suggestion - I think the line “Clojure’s spit and slurp I/O functions are built on two abstractions, reading and writing.” at the top of the page should read “Clojure’s slurp and spit I/O functions are built on two abstractions, reading and writing.” , as in their minds, people would tend to implicitly order the abstractions the same as the I/O functions mentioned. Overall, the section clarifies this, but it would read better if the ordering of the I/O functions was the same as the abstractions mentioned associated with them.

61ERROR

Based on the result of (doc range), ‘end’ is optional, defaulting to infinity if not provided.

The definition of ‘range’ in the pdf implies ‘end’ is a required argument.

127TYPO

Last word of the first paragraph under 5.4’s “The Unified Update Model”

“Tabler” should be “Table”

140TYPO

“Line 15 returns a vector with the snake, apple, and time”

should read

“Line 15 returns a vector with the snake, apple, and timer”

1TYPO

The ebook reader on my Android tablet shows an incorrect thumbnail, it shows “SQL Antipatterns”, i.e. images/_covers/bksqla.jpg (the 1st within that directory) instead of images/cover.jpg . Rather, rather strange!

67ERROR

I was using Clojure 1.4.0 with the book.

Clojure 1.4.0 is a newer version so it could be the Clojure 1.4.0 run-time causing the error.

For the code :-

(sort-by :grade > [{:grade 83} {:grade 90} {:grade 77}])

If this code is run from the REPL, works fine, no problem.
If however you run this code from a Clojure script, under Clojure 1.4.0 is generates an ArityException.

The interpreter just doesn’t like this code.

67SUGGEST

PLEASE IGNORE ISSUE 49300.
I MISTYPED SOME CODE.
This was me being stupid.

115TYPO

In the second paragraph, last sentence it says “…and not ask yourself…”. That should be ‘now’ instead of ‘not’.

125ERROR

I’m not sure if this is a change from 1.3 to 1.4, but I don’t see a change-note in 1.4, so …

See:

After the agent tries to update itself on a pooled thread, it will enter an exceptional state. You will discover the error when you try to dereference the agent:

@counter
-> java.lang.Exception: Agent has errors

This does not appear to be the case;

user=> (send counter (fn [_] “boo”))
#<Agent@6f93ee4 FAILED: 0>
user=> @counter
0
user=>

I get the pre-failed result. (agent-errors counter) works as advertised, though (clear-agent-errors counters) returns the value of the agent and not nil as shown in the book:

(clear-agent-errors counter)
-> nil

@counter
-> 0

Reality:

user=> (agent-errors counter)
(#<IllegalStateException java.lang.IllegalStateException: Invalid reference state>)
user=> (clear-agent-errors counter)
0
user=>

HTH!

4SUGGEST

In the description of how the Clojure function blank? works, you don’t describe what it does with an empty string. It seems obvious that if every character in the string returns true from the isWhitespace function that the entire expression would return true. But what happens when there are no characters? I would think that the isWhitespace function is never invoked. Does every? return undefined, or default to true or false if it has nothing to work on?

xxiiTYPO

A newline is needed between “… with namespace prompt” and “-> 4 …”.

9TYPO

The sentence beginning “Clojure provides a …” contains four instances of a superfluous space following an opening parenthesis, eg: “( on page 115)”.

36SUGGEST

In the section “When to Use Anonymous Functions”, I’d like to see some discussion of the benefits of named functions (eg, decomposition of code, documentation).

37SUGGEST

Change “… the var bound to …” to “… the var that is bound to …”.

30TYPO

The period (just before the colon) in “… a record with user.Book.:” seems out of place and is confusing. Please change and/or explain this.

24SUGGEST

I would change “… for the dividend.” to “… for the dividend or the divisor.”.

25TYPO

The word “Namespaces” should be hyphenated as “Name-spaces”, rather than “Names-paces”.

7SUGGEST

I would indent the lines beginning “((> x …” and “(> x …”.

42TYPO

The word “namespace” should be hyphenated as “name-space”, rather than “names-pace”.

43TYPO

In “… into a Clojure Var:”, I do not think “Var” should be in monospace font, nor that the “v” should be capitalized.

43SUGGEST

It would be useful to clarify that nextInt is a Java method, eg: “The . can call Java methods.”

45SUGGEST

I would expand “… from REPL when exploring.” to “… from the REPL when you are exploring.”

45SUGGEST

The sentence “If the first argument to if is logically false, it returns nil:” is a bit awkward and potentially confusing. How about changing “it” to “if”?

46SUGGEST

“The Swiss Army knife of flow control in Clojure is loop:” seems awkward. How about “loop is the Swiss Army knife of flow control in Clojure:”?

58SUGGEST

The discussion of traversal order in maps and sets seems out of place. It follows several examples which show (but do not explain) that the order in the definition may not be preserved.

61SUGGEST

The bullet item “Sequence predicates” could be written as “Functions that test sequences”.

64TYPO

“its argument is vowel.” should be “its argument is a vowel.”.

xxiSUGGEST

I would lighten up the grey used in the background blocks, for readability.

68SUGGEST

I would change “[according to format instructions].” to “[according to format instructions] [the] word.”

73ERROR

The format of the example output “-> [Ljava.io.File;..." does not match what I get from the REPL: "#<File[] [Ljava.io.File;…>”.

78SUGGEST

The drop/take combination also differs from subvec in that it takes different arguments and is called quite differently.

80SUGGEST

I would change “… only the keys passed in.” to “… only the pairs for the keys that were passed in.”.

92SUGGEST

In the tail-fibo code block, “next” is emboldened each time it appears. However, “next” is simply a parameter to the local function fib, not the Clojure next function. (This also occurs on p. 93 and possibly elsewhere; your formatting software may need some tweaks.)

95SUGGEST

I would add a usage example after the fibo definition, eg: “(take 5 (fibo))”.

100TYPO

There is an extra space following the first :t in “[:h :t :t …”, three times on this page.

114SUGGEST

I would change “… power into cores.” to “… power into individual processing cores.”

114SUGGEST

I think that “complect” deserves more than just a footnote. How about an explanatory block?

115SUGGEST

In the paragraph beginning “Clojure’s model for …”, the word model is used several times with varying (though related) meanings. This seems needlessly confusing.

116SUGGEST

It might be useful to show that the prior value persists after a ref-set call. For example, “(def snap current-track)” before the ref-set and “snap” afterwards.

127TYPO

“in the following tabler.” should be “in the following table.”

249TYPO

The “Git” heading needs to be swapped with the paragraph “This will provide …”.

262SUGGEST

Add an index entry for load-file.

177159TYPO

It’s just the absence of the final closing parenthesis:

(extend-type Note
MidiNote
(to-msec [this tempo]
(let [duration-to-bpm {1 240, 1/2 120, 1/4 60, 1/8 30, 1/16 15}]
(* 1000 (/ (duration-to-bpm (:duration this))
tempo))))

should be:

(extend-type Note
MidiNote
(to-msec [this tempo]
(let [duration-to-bpm {1 240, 1/2 120, 1/4 60, 1/8 30, 1/16 15}]
(* 1000 (/ (duration-to-bpm (:duration this))
tempo)))))

179161ERROR

Got this error with the dot syntax for a new instance:

user=> (perform (for [velocity [64 80 90 100 110 120]]
(assoc (Note. :D 3 1/2) :velocity velocity)))

CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: Note, compiling:(NO_SOURCE_PATH:12)

just changing to Record syntax and works well:

user=> (perform (for [velocity [64 80 90 100 110 120]]
(assoc (->Note :D 3 1/2) :velocity velocity)))
->nil

131SUGGEST

in manual has printed an old form for :
……
(startElement
[uri local-name q-name #^Attributes atts]
……….

the form #^….. is not found in any document (ver 1.3 or
newer)

The correct form shold be :

(startElement
[uri local-name q-name ^Attributes atts]

or would it be useful to explain the meaning of #^ il text resume the source of xml.clj

Ciao

150TYPO

in
make-writer[dst]
for URL is wrong
(->dst .getPath FileInputStream.)

correct :
(->dst .getPath FileOutputStream.)

151TYPO

in
make-writer [dst ]
for URL has an error in:
(-> dst .getPath FileInputStream.)
correct in
(-> dst .getPath FileOuputStream.)

147TYPO

in
(definterface IOFactory
has an error in:
(^java.io.BufferReader make-reader [this])
……
correct in
(^java.io.BufferedReader make-reader [this])
…..

150SUGGEST

after :

Now let’s put it all together

add the row
src/examples/io.clj
in reversed mode as in previous pages

155TYPO

in
(ns examples.cryptovault_complete
(:require [clojure.java.io :as io]
[examples.protocols.io :as proto])
…………………..
has is wrong: ‘examples.protocols.io’

the correct form is:
(ns examples.cryptovault_complete
(:require [clojure.java.io :as io]
[examples.io :as proto])
……………..

232217TYPO

There is a typo in the function: (aset arr2 “fill”)

(defn painstakingly-create-array []
(let [arr (make-array String 5)]
(aset arr 0 “Painstaking”)
(aset arr 1 “to”)
(aset arr2 “fill”)
(aset arr 3" in“)
(aset arr 4 ”arrays")
arr))

It should be:

(defn painstakingly-create-array []
(let [arr (make-array String 5)]
(aset arr 0 “Painstaking”)
(aset arr 1 “to”)
(aset arr 2 “fill”)
(aset arr 3" in“)
(aset arr 4 ”arrays")
arr))

253238TYPO

The name of the function is wrong:

(scoring-is-bound-by-number-of-pegs secret guess (game/score secret guess))

This should be:

(scoring-is-bounded-by-number-of-pegs secret guess (game/score secret guess))

30ERROR

Instantiating the record, (->Book “title” “author”), returns an error: “java.lang.Exception: Unable to resolve symbol: ->Book in this context”

Instantiating the record with (Book. “title” “author”) seems to work.

240225SUGGEST

This does not work on windows “java -cp .:pinger-0.0.1-standalone.jar pinger.core”. The classpath uses ‘;’ semi colons on windows.

xxiiOK

The second introductory REPL sample is missing a new line in

user=> (+ 2 2) ; input line with namespace prompt-> 4 ; return value

2014-05-26Duplicate of #49657
N/AERROR

.mobi version of the file does not contain index.

118TYPO

In my version of the text,`(alter ref update-fn & args…)` has the word `ref` typeset in bold purple, which makes it appear to be the Clojure `ref` function. But really you want `ref` to indicate an argument (e.g. a placeholder for the name of a ref). So, to fix, just remove the bold purple formatting.

119TYPO

My version of `(commute ref update-fn & args…)` has `ref` in bold purple. This is confusing because it makes it appear that `ref` is a ‘built-in’ Clojure function. It is clearer to make the formatting be plain. If automatic syntax highlighting is to blame, then perhaps use `ref-symbol` or `the-ref` instead of `ref`. You may want to check for additional examples of this happening — I’ve already found one other (on the previous page).

147TYPO

(definterface IOFactory
(^java.io.BufferReader make-reader [this])
(^java.io.BufferedWriter make-writer [this]))

should be :

(definterface IOFactory
(^java.io.BufferReader make-reader [])
(^java.io.BufferedWriter make-writer []))

240TYPO

First line:

- test-namespaces takes on more namespaces
should be:
- test-namespaces takes one or more namespaces

235TYPO

3rd line:

- How hard is it write a program
should be:
- How hard is it to write a program

237ERROR

Last line is:
(< 0 (matches score) (count secret)))

Should be `<=` instead of `<`, as the range for the number of matches should include the edges.

243ERROR

The command `lein plugin install lein-noir 1.2.0` no longer works. In Leiningen 2.x plugins should be specified in `project.clj` or `~/.lein/profiles.clj`

243ERROR

`lein noir new clojurebreaker`
should be
`lein new noir clojurebreaker`

10ERROR

In:

“but notice that in the
following code the Clojure version has both fewer dots and fewer parentheses
than the Java version:
// Java
”hello“.getClass().getProtectionDomain()
; Clojure
(.. ”hello" getClass getProtectionDomain)"

The Clojure version has the same amount of dots than the Java one, I see the authors’ point, but this is a not-so-well chosen example ;).

190TYPO

prose concerns my-print, code example uses my-println instead:

"
Unsurprisingly, attempts to call my-print will fail:
(my-println “foo”)
"

52TYPO

the metadata tag attached to the argument `s`
seems to make no visible difference, as :tag
merely shows the tag attached to the retval.

73SUGGEST

(import ’(java.io File))
(.listFiles (File. “.”))
-> [Ljava.io.File;@1f70f15e

The syntax (Class. foo) to invoke a java ctor
is used here for the first time, is elided
and really should have been shown back where (new Foo)
was discussed.

40SUGGEST

for destructuring forms, the ref to the `let` doc is misleading,since currently the special_forms documentation has a specific “Binding Forms (Destructuring)” section.

116ERROR

I believe the description of “atomic” transactions is wrong.
The description for atomic is actually roughly quivalent
to the “isolated” property description.
“atomic” means “all-or-nothing”, while the description
emphasizes the “all” guarantee which constitutes isolation.

128SUGGEST

the inclusion of metadata tag :dynamic in `(def:dynamic foo 10)` is distracting. it’s not explained, nor even mentioned, it’s unclear whether the inclusion or ommision of
the tag makes any practical difference.

178ERROR

There’s a distinction to be made between special forms hardcoded into the language evaluator, and macro invocation
where args are evaulated differently then normal forms.
the former are special by virtue of being part of the language , while the latter are different by virtue
of the semantics of macros. You can mimic special forms
with macros, but you can’t create new ones except
by modifying the language.

184SUGGEST

up to this point in the book, no discussion or mention
of exceptions/try/finally has been made. the comment
on “using a finally block” lacks the proper exposition.

31TYPO

Add index entry for #() anonymous-function notation

31SUGGEST

Add index entry for #“” regular-expression notation

260SUGGEST

Index entry for “extend” should also “see proxy”

57SUGGEST

Add index entry for “inner class, notation for name of”

127SUGGEST

I think maybe the top row of the table is what the sentence below the table refers to with “the unified update model is the most important way…”, while the succeeding rows are the “ancillary… optimizations”? But this is unclear. The table needs labels.

111SUGGEST

The second paragraph makes this suggestion “Rebind m and f to memoized versions of themselves, using Clojure’s memoize function”, but if I’m typing out all of the examples out of the book it doesn’t work. I can memoize, but later when I try to invoke the memoized function I get the following error: “StackOverflowError clojure.lang.AFn.applyToHelper (AFn.java:155)” … when I took a look at the example code from github I found that f/m are defined slightly differently using (defn-, which as I understand it—and I do thanks to you folks!—defines a function privately for just that namespace. Anyway, it was a bit confusing. Thanks!

184ERROR

Section 3.1 “Everything Is a Sequence”. Examples: (first {:fname “Aaron” :lname “Bedra”}) and (rest {:fname “Aaron” :lname “Bedra”}) have outputs switched, the first should be -> ([:fname “Aaron”]) and the rest -> [:lname “Bedra”].

76ERROR

Section 3.1 “Everything Is a Sequence”. Examples: (first {:fname “Aaron” :lname “Bedra”}) and (rest {:fname “Aaron” :lname “Bedra”}) have outputs switched, the first should be -> ([:fname “Aaron”]) and the rest -> [:lname “Bedra”].

217TYPO

(defn painstakingly-create-array []

(aset arr2 "fill)
————-^

162180ERROR

In section 6.6 - when calling reify on MidiNote there are a number of errors in the generator.clj implementation. All the functions defined in MidiNote that are implemented in the reify macro call, need to be called using the Java interop syntax of preceeding ‘function’ (method) calls with a dot. This is because MidiNote is imported rather than required/used so presumably it’s used in the same manner as a Java interface.
Also, as the ‘perform’ function is not part of the MidiNote protocol it needs to be fully qualified as ‘examples.datatypes.midi/perform’.

E.g.

(ns examples.generator)

; START: midinote
(import ’[examples.datatypes.midi MidiNote])
(let [min-duration 250
min-velocity 64
rand-note (reify
MidiNote
(to-msec [this tempo] (+ (rand-int 1000) min-duration))
(key-number [this] (rand-int 100))
(play [this tempo midi-channel]
(let [velocity (+ (rand-int 100) min-velocity)]
(.noteOn midi-channel (.key-number this) velocity)
(Thread/sleep (.to-msec this tempo)))))]
(examples.datatypes.midi/perform (repeat 15 rand-note)))
; END: midinote

157TYPO

C (C sharp) should be C# (C sharp)
D (D flat) should be Db (D flat)
D half note should be D# half note

9476ERROR

The parse example on page 94 refers to parse without first telling the reader they should user or import xml.

87ERROR

The second footnote contains a broken link. You can easily find the correct link by Googling.

50SUGGEST

The last sentence of “Using numeric types”:

“Notice that only one ​ BigInt ​ literal is needed and is contagious to the entire calculation.”

is true only if the “N” is put “left enough” in the computation chain:

(* 1000000N 1000000 1000000 1000000 1000000 1000000)

is ok, where:

(* 1000000 1000000 1000000 1000000 1000000 1000000N)

will rise an exception.

It’s somewhat obvious from what you wrote about left to right evaluation (though I had to try in REPL to be sure), but It sorted of “jumped out” when I was reading, so I thought it might be worth reporting.

Oh… and congratulations: great book so far! :)

205TYPO

Modify the existing my-println to add a new cond invoking the feature-specific
helper.

should be

Modify the existing my-print to add a new cond invoking the feature-specific
helper.

SafriERROR

(I’m viewing P1.0 on O’Reilly Safari, so I don’t know what page number this error is on.)

The “Recursion Revisited” section has an initial trampolining implementation of tail-fibo, saying, “You can take the code of tail-fibo and prepare it for trampolining by wrapping the recursive return case inside a function.”

The section goes on to say, “This requires adding only a single character, the #, to introduce an anonymous function” and “The only difference between this and the original version of tail-fibo is the initial # on line 7.”

Here is the relevant trampolining implementation that “Recursion Revisited” introduces:

(​defn​ trampoline-fibo [n]​
​ (​let​ [fib (​fn​ fib [f-2 f-1 current]​
​ (​let​ [f (​+​ f-2 f-1)]​
​ (​if​ (​=​ n current)​
​ f​
​ #(fib f-1 f (​inc​ current)))))] ​
​ (​cond​​
​ (​=​ n 0) 0​
​ (​=​ n 1) 1​
​ :else (fib 0N 1 2))))​

Though the text states that its implementation is similar to “the original version of tail-fibo”, in fact it is completely different. This is the original version of tail-fibo, which is from the section “How to Be Lazy”:

​(​defn​ tail-fibo [n]​
​ (​letfn​ [(fib ​
​ [current ​next​ n] ​
​ (​if​ (​zero?​ n)​
​ current ​
​ (fib ​next​ (​+​ current ​next​) (​dec​ n))))] ​
​ (fib 0N 1N n)))

You can’t get the implementation of trampoline-fibo from tail-fibo by “adding only a single character, the #”.

This isn’t a simple typo: there are no implementations of fibo that look anything like trampoline-fibo - and certainly none that can be turned into it by adding a # character.

SafriTYPO

(I’m viewing P1.0 on O’Reilly Safari, so I don’t know what page number this error is on.)

The “Including Agents in Transactions” sub-section of chapter 5.4 (“Use Agents for Asynchronous Updates”) includes the following text:

“A Clojure transaction promises only to send/sendoff an action to the agent; it does not actually perform the action under the ACI umbrella.”

The correct name for the function is `send-off` - not `sendoff`.

11SUGGEST

“Clojure version has both fewer dots and fewer parentheses than the Java version”, and the examples given are ‘“hello”.getClass().getProtectionDomain()’ in Java and ‘(.. “hello” getClass getProtectionDomain)’ in Clojure. I see the same number of dots, not fewer. Another method call maybe?
Extremely nit picky I know, sorry.

Categories: