By Developers, For Developers
PDF Pg | Paper Pg | Type | Description | Fixed on | Comments |
---|---|---|---|---|---|
15 | SUGGEST | This page demonstrates Clojure’s elegance by comparing a Java isBlank function against a Clojure blank? function. The isBlank function checks against any type of whitespace, so you might want to put more than just \\space in the test set. Maybe throw a \\tab in there for clarity. If you wanted to be overly complete I guess you could define a set with all the unicode whitespace characters. Also, the use of a multimethod there seems odd. I guess it covers the nil case (why is there a nil case?) and allows adding more classes later, but maybe this would be more representative of elegance? (defn blank? [s] (every? #{\\space \\tab} s) ) Now it handles any sequence of characters, and still works on nil. It does make the bullet point below it about multimethods need a new home though. | 2008-11-14 | ||
85 | TYPO |
| 2008-11-14 | ||
31 | TYPO | The last sentence in the first paragraph reads “Clojure then takes executes the forms.” | 2008-11-14 | ||
9 | TYPO | Grammer improvement page 9 paragraph 3: | 2008-11-14 | ||
41 | TYPO | 4th paragraph, first sentence reads “A third reason to use anonymous functions is when you dynamically | 2008-11-14 | ||
27 | TYPO | I think the Fibonacci example syntax should be: | 2008-11-14 | ||
28 | TYPO | Last paragraph before “Wrapping Up” says “Of you are having trouble…” | 2008-11-14 | ||
46 | TYPO | Fourth paragraph (minus code samples) ends with this sentence: “For this chapter, you can load reload the examples at any time:” Should “load” be removed from the sentence? | 2008-11-14 | ||
82 | TYPO | If you see the phrase “foo changes xml,” mentally substitute “foo returns a changed copy of x.” should be “… changed copy of xml” or “foo changes x” | 2008-11-14 | ||
44 | TYPO | The regex in ellipsize definition is #“\\\\s” and it should be #“\\s”. Copy pasting the code example, using clojure at v1086, doesn’t work | 2008-11-14 | ||
37 | ERROR | (symbol? :hello) should probably be (symbol? ’hello) | 2008-11-14 | ||
49 | TYPO | paragraph 3. … But you many not use it very often, as many common recursions are provided by Clojure’s sequence library… | 2008-11-14 | ||
61 | TYPO | paragraph 4 … In Java, arrays are have their own syntax, | 2008-11-14 | ||
53 | SUGGEST | Two things confused me a bit here, when I tried to define the index-of-any function in my REPL: 1) The “indexed” function is in clojure.contrib.seq-utils, not in core Clojure, so I got an exception because I hadn’t mapped that namespace. 2) The argument for chars needs to be a set. I tried to call it with a vector first, which didn’t work, of course. Things became even more confusing when I looked at the documentation for “get” in the Clojure API docs, and it only talked about maps. Maybe these things could be clarified in the text? | 2008-11-14 | ||
35 | TYPO | “Only nil? is nil, and only false is false?.” presumably should be “Only nil is nil?, …” | 2008-11-14 | ||
39 | TYPO | My guess is that the regular expression passed to re-split in the example using indexable-word? has an extra backslash. (This is also true where fn is used instead of the defn of indexable-word? on the next page.) In short, #“\\\\W+” should be replaced in at least two places with #“\\W+” | 2008-11-14 | ||
49 | SUGGEST | recur binds new values for loop’s exprs, and returns control to the top of the loop. Shouldn’t this read, “… for loop’s bindings, …”? The “exprs” in the loop form are the body of the loop; it is the bindings that are replaced, not the exprs. | 2008-11-14 | ||
39 | TYPO | Newest clojure now works with \\W instead of \\\\W | 2008-11-14 | ||
43 | TYPO | last line of code in the page should be | 2008-11-14 | ||
18 | TYPO | (defn hello-world [name] should be (defn hello-world [name] | 2008-11-14 | ||
25 | TYPO | Lines 4 through 6 return different strings based on the the user was a visitor in the past. the the | 2008-11-14 | ||
65 | TYPO | With duck typing, an object’s type is the sum of what it can it should say: … In other words, it is more important to quack( ) and fly( )… | 2008-11-14 | ||
8 | TYPO | Clojure provides alternatives | 2008-11-14 | ||
47 | TYPO | Last sentence of 5th paragraph: “If it did, it would always evaluate | 2008-11-14 | ||
89 | TYPO | seems to be an extra “>” on the example after the %s (for [word [“the” “quick” “brown” “fox”]]
%s> " word))
the> " "
quick> " "
brown> " "
fox> ") | 2008-11-14 | ||
26 | TYPO | 2nd paragraph after 1.4 Using the Sample Code One you have downloaded the samples, … Once you have downloaded the samples, | 2008-11-14 | ||
23 | 23 | ERROR | I’m using clojure_20080916.zip and the *1, *2, *3, and *e don’t work in the REPL. I get clojure.lang.Compiler$CompilerException: NO_SOURCE_FILE:5: Unable to resolve symbol: *1 in this context | 2008-11-14 | |
15 | TYPO | missing “return true” at the end of the isBlank function in Java. I verified the /org/apache/commons/lang/StringUtils.java file. public static boolean isBlank(String str) { | 2008-11-14 | ||
23 | 23 | ERROR | Ahh the svn version works fine (*1, *2, *3, *e) | 2008-11-14 | |
92 | SUGGEST | “; you probably don’t want to cons, see below” (cons 72 (.getBytes “ello”)) | 2008-11-14 | ||
101 | TYPO | (def inventors {“java” “gosling” , “clojure” “hickey” , “ruby” , “matz” }) the last \\, could make the statement a little less clear than if it where omitted | 2008-11-14 | ||
15 | TYPO | isBlank Java code is missing a closing brace (as well as return true). Indentation seems off too. | 2008-11-14 | ||
66 | ERROR | In the type-hinted version of the sum-to function, it is defined as integer-sum-to, but the benchmark form uses faster-sum-to: (dotimes _ 5 (time (faster-sum-to 10000)) | 2008-11-14 | ||
57 | TYPO | “Powerful, in that it bring all the expressiveness…”, should be “brings” | 2008-11-14 | ||
60 | SUGGEST | The use of the Classname/membername form without parentheses only works with static fields, not static methods. Should it be clarified here? user=> Math/PI | 2008-11-14 | ||
61 | SUGGEST | In the first paragraph about idiomatic Clojure: I would also like to hear your take on (. class-or-instance member) vs. (.member class-or-instance). When to prefer one over the other? Should one form be considered more idiomatic? | 2008-11-14 | ||
61 | TYPO | Paragraph 2: “So, you should be able to use Clojure’s collections from with Clojure…” should be “from within”? | 2008-11-14 | ||
69 | TYPO | Second paragraph from the bottom is missing a close paren: “To get ready for this example, go ahead and import the following classes (we’ll need them all before we are done:” | 2008-11-14 | ||
69 | TYPO | In the last paragraph: “The easiest was is often to extend the DefaultHandler class.” I’m guessing this should be “The easiest way”. | 2008-11-14 | ||
70 | TYPO | In the description of the DefaultHandler proxy: It actually prints the name of the qname arg, not name. Also, in the JavaDoc for DefaultHandler.startElement, the name of the first argument is actually “uri”, so maybe the attribute vector of the proxy should be [uri, local, qname, atts]. | 2008-11-14 | ||
71 | ERROR | Two problems in the following code example: (dotimes i 5 1) println does not format it’s arguments, so the output looks like “Finished %d on %s 3 #<Thread[Thread-30,5,main]>” 2) The nested function definitions look a bit strange to me. Why is the function wrapped in (#(…))? Wouldn’t a simple fn do the trick? | 2008-11-14 | ||
80 | TYPO | In the code examples that follow the introduction of cloj and into: (conj sequence element & elements) The latter should probably be an into, not a conj? | 2008-11-14 | ||
37 | TYPO | In 2.3 Functions, (symbol? :hello) should be changed to (symbol? ’hello) | 2008-11-14 | ||
27 | TYPO | (take 10 introduction.fibs) does not work.. Is ‘introduction/fibs’ right, isn’t it? | 2008-11-14 | ||
69 | TYPO | In the PDF version, with syntax coloring, the “and” in “class-and-interfaces” gets colored as a function name; same in “gen-and-save-class” a few pages later. | 2009-05-27 | ||
32 | SUGGEST | When referring to Clojure functions I would not use the format f(), as that’s not how functions are written anywhere. Just f will do I think. For expample instead of: “If you want to stick to integers, you can get the integer quotient and remainder with quot( ) and rem( ):” I would prefer: “If you want to stick to integers, you can get the integer quotient and remainder with quot and rem:” Maybe use special typeface instead. This applies to other sections as well. | 2008-11-14 | ||
39 | TYPO | (re-split #“\\\\W+” “A fine day it is”) => (re-split #“\\W+” “A fine day it is”) | 2008-11-14 | ||
74 | TYPO | newManifest = new Manifest®; is translated as (.Manifest r) but should be (I believe) (Manifest. r) | 2008-11-14 | ||
77 | TYPO | “XML data is tree” probably should be “XML data is a tree” | 2008-11-14 | ||
88 | TYPO | “reduce applies f on the first two argu- | 2008-11-14 | ||
92 | SUGGEST | “The Seq abstraction of first/next ” | 2008-11-14 | ||
89 | OK | (for [binding-form coll-expr filter-expr? …] expr) in the PDF, “binding” has a function-name syntax coloring (purple? burgundy?) | 2009-02-27 | ||
90 | TYPO | In the description of lazy-cons and lazy-cat, “lazy-cons” has function-name highlighting, but “lazy-cat” does not. This is the example between the paragraphs beginning “Clojure provides several utilities…” and “The actual combination is lazy:…” | 2009-04-03 | ||
93 | TYPO | re-matcher sample code uses a pattern of #“\\\\w+” rather than #“\\w+”. | 2008-11-14 | ||
94 | TYPO | In the example of seq’ing over the file system, the example assumes that java.io.File has been imported, since it is using “File” without qualification. | 2008-11-14 | ||
94 | TYPO | In the example of seq’g over the file system using seq, the example and results is shown as (seq (.listFiles (File. “.”)) ) On my system (openSuSE 11.0, Linux) at least, the result is a list of java.io.File objects, which render as an unreadable object: (seq (.listFiles (File. “.”))) This may be a difference in how File objects are rendered, or one version may have returned filenames rather than actual File objects; the former seems more likely. | 2008-11-14 | ||
79 | ERROR | The book says: but the result on my terminal is: | 2008-11-14 | ||
106 | TYPO | “Expensive computations need to be execute in parallel on multiple cores (or multiple boxes) in order to complete in a timely manner.” This should probably be “need to be executed” or “need to be able to execute”, as needed. | 2008-11-14 | ||
66 | TYPO | “To time an operation, you can use the time.” should be “To time an operation, you can use time.” | 2008-11-14 | ||
71 | TYPO | Paragraph 2: “In Java, you must provide an implementation of method on every interface you implement.” Should be “of every method on any interface”? | 2008-11-14 | ||
82 | TYPO | Paragraph 3: “Sequences never change..” — Extra period. | 2008-11-14 | ||
118 | TYPO | The second to last line on this page has “an err” instead of “and err”: | 2008-11-14 | ||
84 | SUGGEST | “(def whole-numbers (iterate inc 1))” I think it would be a good idea to mention here or in section 4.3 that retaining a reference to the start of an infinite sequence might cause excessive memory consumption. Infinite sequences should mostly be used as streams which can be garbage collected as you move along. A single reference like “whole-numbers” can prevent this. So I think some advice could be helpful for your audience. | 2009-01-29 | ||
79 | 79 | ERROR | …towards the bottom of the page, The response from first and rest are reversed. should be: (first {:fname “Stu” :lname “Halloway”}) | 2008-11-14 | |
100 | TYPO | (def song {:name “Agnus Dei” | 2008-11-14 | ||
79 | SUGGEST | Ahh I see, this may be an implementation detail since it’s a map. | 2008-11-14 | ||
26 | SUGGEST | Although it has already been shown how to fetch and build Clojure, it hasn’t been shown how to do the same for clojure-contrib (only how to verify it’s in your classpath). It would be helpful to add instructions on how to do so. | 2008-12-02 | ||
114 | TYPO | (guess-pi (run-simulation 100)) should be (guess-pi (run-simulation 10)) you are talking about 10 iterations | 2008-11-14 | ||
119 | TYPO | The code for calls-slow-double is missing, and the code for slow-double is printed twice: Next, write a function named calls-slow-double that calls slow-double for I guess calls-slow-double should be something like: | 2008-11-14 | ||
122 | TYPO | Last sentence: “In the next chapter, you will see how Clojure | 2008-11-14 | ||
66 | TYPO | When benchmarking, you tend to want to take several measure- I believe you wanted eliminate? | 2008-11-14 | ||
66 | TYPO | (faster-sum-to 10000) => (integer-sum-to 10000) | 2008-11-14 | ||
71 | TYPO | #(fn [] => #( | 2008-11-14 | ||
80 | ERROR | (conj to-sequence from-sequence) => (into to-sequence from-sequence) | 2008-11-14 | ||
85 | TYPO |
Now that you have the basics of creating sequences, you can use other Clojure …TRUNC Filtering Sequences
Clojure provides a number of functions that filter a sequence, returning a sub…TRUNC | 2008-11-14 | ||
87 | ERROR | some returns the first true value for its predicate, or nil if no element user> (#{1 2 3} (some even? [1 2 3])) | 2008-11-14 | ||
91 | ERROR | (def x (for [i (range 1 10)] (do (println i) i))) (doall x) => user> (doall x) | 2008-11-14 | ||
94 | TYPO | (re-seq \\w+ “the quick brown fox”) => (re-seq #“\\w+” “the quick brown fox”) (sort (re-seq \\w+ “the quick brown fox”)) | 2008-11-14 | ||
98 | TYPO | (values map) => (vals map) | 2008-11-14 | ||
100 | OK | Is the color of this code strange, isnt’t it? (PDF version) (assoc song :kind “MPEG Audio File”) | 2009-02-16 | ||
108 | ERROR | (def messages (ref ())) => (def messages (ref ’())) | 2008-11-14 | ||
22 | SUGGEST | It is not clear how we get closure-contrib.jar. Earlier there was a “1.3 Running CLosure” that lists JDK and clojure.jar as the only necessary downloads. It would help if we section also included closure-contrib.jar. Unless we have this, on page 27, it is not immediately clear how we get that in order to add it to our classpath. | 2008-11-24 | ||
28 | TYPO | probably a versioning thing, but (take 10 introduction.fibs) throws a ClassNotFound (take 10 introduction/fibs) works for me | 2008-11-14 | ||
15 | ERROR | StringUtils::IsBlank() is missing a final “return true” as its last statement. | 2008-11-14 | ||
53 | TYPO | Draft says: “Since Clojure can return null, the initial if is unncessary.” Shouldn’t this be “Since Clojure can return nil …”? Also, unnecessary is spelled wrong (missing e after nn). | 2008-11-24 | ||
55 | TYPO | There is an visible in the output of your (find-doc) example. See last line below: user=> (find-doc “reduce” ) | 2008-11-24 | ||
18 | TYPO | The given erratum is missing a ‘)’ at the end, so it should be: (defn hello-world [name] (println (format “Hello, %s” name))) | 2008-11-24 | ||
57 | TYPO | “Clojure’s Java support is the both powerful and lean.” should be “Clojure’s Java support is both powerful and lean.” I don’t think the “the” before “both” is correct. | 2008-11-24 | ||
57 | TYPO | “Lean, in that can get right to the metal.” should be “Lean, in that it can get right to the metal.” | 2008-11-24 | ||
61 | TYPO | “In Java, arrays are have their own syntax” should be “In Java, arrays have their own syntax” | 2008-11-24 | ||
93 | ERROR | Regexp in re-matcher example has an escaped back-slash in it, meaning the Regexp doesn’t match the string, as of v1086 | 2008-11-24 | ||
114 | 114 | TYPO | Clear the counter’s errors, Should be: Clear the counter’s errors, | 2008-11-14 | |
24 | SUGGEST | “The #{} is a literal for an empty set, since there are no visitors yet.” That sentence is confusing to me. Yes, “#{}” is the empty set literal, but that is not /because/ there are no visitors yet. I suggest you drop the second clause, and leave it at “The #{} is the literal for an empty set.” | 2008-11-14 | ||
25 | TYPO | In the last paragraph on the page, you write “even though there are no locks, either directly in the code…” but isn’t dosync performing an implicit lock? | 2008-11-14 | ||
83 | OK | For the range function, you may want to clarify somewhere (although the examples show this) that the value of the “end” argument does not appear in the sequence returned by range. I might have suggested using “limit” as a replacement for “end”, if it weren’t already so coded in Clojure itself. | 2009-01-29 | ||
45 | ERROR | The sentence: “When you create a new namespace, the java.lang package and the Clojure namespace are automatically available to you” is not correct. If you create a new namespace with “ns” the Clojure namespace is available in the new namespace; however, if you create the new namespace with “create-ns”, the Clojure namespace is NOT available in the new namespace. | 2008-11-14 | ||
35 | TYPO | Only nil? is nil, and only false is false?. should read: Only nil is nil?, and only false is false?. | 2008-11-14 | ||
18 | TYPO | s/Lisp/Clojure/ in “Lisp doesn’t care about commas | 2008-11-14 | ||
81 | TYPO | Joe Asks last paragraph: “When you ask the REPL to display | 2008-11-14 | ||
96 | TYPO | First paragraph, “Then, create a clojure-loc function then counts…” should be “Then, create a clojure-loc function that counts” | 2008-11-14 | ||
112 | SUGGEST | Maybe “you can send the agent a function to update its state” is enough explanation for some (along with “send tells the agent to update itself on a thread pool”), but not for me. I suggest that you explain something about the interface of the function used to update the agent, rather than requiring the reader to infer it from examining run-simulation (because you’ve only touched upon multimethods by this point anyway). | 2008-11-14 | ||
15 | SUGGEST | As per above, the two blank methods aren’t quite equivalent as the first accepts strings containing non-space whitespace characters. Perhaps replace (every? #{\\space} s) with (every? #(Character/isWhitespace %) s)? It reinforces Java interop as well. | 2008-11-14 | ||
18 | ERROR | Should be: (defn hello-world [name] I believe. | 2008-11-14 | ||
42 | TYPO | “Functions are not the only way to have “have” is unnecessary | 2008-11-14 | ||
49 | SUGGEST | When talking about recur, I’d like to suggest that you talk briefly about tail recursion and tail call optimization. The JVM does not support TCO now but there seem to be strong indicators that it is coming which means that loop/recur might not be necessary in the future, leading to recursive code that looks closer to that written in other Lisps. | 2009-01-29 | ||
14 | TYPO | “Lisp brings wisdom | 2008-11-14 | ||
22 | TYPO | Is there a reason to run the REPL with | 2008-11-14 | ||
112 | TYPO | Here’s my log: user=> (def counter (agent 0)) You had #=(var user/counter), | 2008-11-14 | ||
15 | TYPO | Along with what has already been said, I don’t think it makes sense for nil to be counted as a “blank” string. To me nil represents the absence of anything. I understand that you are just trying to replicate StringUtils functionality, but you may want to pose the question “Is a nil string really a blank string?” It may deter from the point of that section, but just wanted to give my .02 cents. | 2008-11-14 | ||
18 | SUGGEST | The choice of wording when talking about commas is a little confusing. Maybe it should read something more like “Clojure doesn’t need the commas, but allows them for the purpose of readability.” | 2008-11-14 | ||
50 | SUGGEST | On the very first sentence of this page, I would suggest changing “The wikipedia” to either “Wikipedia” or “The Wikipedia article on metadata”. | 2008-11-24 | ||
19 | TYPO | It’s not “Guiseppe Verdi”, but “Giuseppe Verdi”. | 2008-11-24 | ||
22 | TYPO | Using the latest clojure source (13th Nov 08) on my Windows XP pc, the output of the “hello” function definition is not: #=(var user/hello) but #’user/hello | 2008-11-24 | ||
65 | TYPO | Idiomatic Clojure takes advantage of duck typing, but you can This should be: Idiomatic Clojure takes advantage of duck typing, but you can add type hints. See Section 3.2, Adding Type Hints, on page 68 for performance or documentation purposes. | 2008-11-24 | ||
34 | SUGGEST | It wasn’t quite clear at first why exactly you had to use (apply str …) in order to get a string back. I thought just calling (str (interleave …)) would work. It took a few doc calls and a couple of minutes to realize that interleave created a sequence, and that apply is needed so that you can work on the sequence. By just calling str I was calling toString on a sequence object (I’m not even sure if that makes sense, but it’s how I understand it). Anyways, you may want to clarify what is going on here. Unless I’m just a slow learner. | 2008-12-02 | ||
26 | TYPO | The command to fetch Clojure-contrib from svn is incorrect. Instead of: svn co -r 240 svn co It should be: svn co -r 240 | 2008-11-24 | ||
26 | TYPO | The classpath used for clojure includes directories that don’t exist (e.g. /book/examples doesn’t exist in the given code). It should be: export CLASSPATH=/jars/clojure.jar:\\ | 2008-11-24 | ||
27 | SUGGEST | Was previously able to run the book examples with B1.0 but cannot for B2.0. (require ’introduction) still returns nil as it should but cannot call fibs: (take 10 introduction/fibs) Also, at the bottom of the page the same example is used but with introduction.fibs instead of introduction/fibs. Is one of these a typo? | 2008-11-24 | ||
64 | SUGGEST | In Figure 3.1, the Sugared column’s contents go off the page and are unreadable. | 2009-04-29 | ||
89 | TYPO | Instead of {:a 1 :b 2 :c 3} it should be {:a=1 :b=2 :c=3}. | 2008-11-24 | ||
14 | TYPO | “Clojure is Elegant”: In title case, always capitalize “Is”. This error appears in headers throughout Chapter 1. | 2009-02-16 | ||
25 | TYPO | “This helps hello will scale well to multiple processors.” Two competing clause structures here. Pick one. :-) | 2008-11-24 | ||
27 | ERROR | Re: the problem with running (take 10 introduction/fibs), the problem appears to be namespace-related. In the source code file book/examples/introduction.clj, the first line is “(ns examples.introduction).” I changed it to “(ns introduction)” and everything worked fine. BTW, (take 10 introduction/fibs) works fine, but (take 10 introduction.fibs) does not. | 2008-11-24 | ||
88 | ERROR | In the example for using first and rest on a map, the return values are reversed. The text reads: (first {:fname “Stu” :lname “Halloway”}) (rest {:fname “Stu” :lname “Halloway”}) It should be the other way around: (first {:fname “Stu” :lname “Halloway”}) (rest {:fname “Stu” :lname “Halloway”}) | 2008-11-24 | ||
35 | SUGGEST |
At this point the reader, who was expecting \
At this point, we kind of expect an explanation as to why clojure seems to always escape line breaks, transforming actual line feeds into \ And indeed the next paragraph starts with: Aha, we’re getting there …
Talk of a let down! We were led to expect the explanation about this \ The java interop stuff surely has its place in the book, but not by using the word “wrap” within eye distance of the \ :-) | 2009-02-16 | ||
39 | SUGGEST |
Fine so far … except that the next paragraph throws through a loop:
Aha? so doc-string? and attr-map? are predicates, right? Nope. Since you are already using * with meaning zero or more in “[params *]”, why not use this very same convention everywhere instead:
| 2008-11-24 | ||
21 | ERROR | The last line of this page says the book targets subversion revision 1087, but the preceding command line instructions for checking out and building the clojure source code use revision 1097. | 2008-11-24 | ||
51 | TYPO | “The first time through, loop binds result an empty vector, and …” This should read “The first time through, loop binds result to an empty vector, and …” instead | 2008-11-24 | ||
62 | TYPO | import takes a variable number of lists, with the first part OF each list being | 2008-11-24 | ||
34 | SUGGEST | You list +, -, *, /, !, ?, ., and _ as characters that can appear in symbols, then immediately show us >, <, =, and >=. I don’t know if the first list is incomplete or Clojure is currently being more permissive than it intends, but right now: user=> (def oh> “oh greater than”) If those shouldn’t work, it would be good to point out that Clojure gets to use a handful of symbols we don’t. If they should, then they should go on the list (even though they’re much less likely to be useful than the characters you list now). Thanks. | 2009-02-16 | ||
37 | TYPO | “So far, you have seen numeric literals, lists, symbols, strings, charac- We’ve also seen vectors. | 2008-12-02 | ||
39 | SUGGEST | The use of “(defn name doc-string? attr-map? [params*] body)” for showing the shape of a form is surprising here, since we haven’t seen it yet, and it’s styled just like actual code samples. In this case you could show us an example with trailing comments on the doc-string and attr-map lines letting us know those are optional, but presumably that’s going to get onerous before long (not to mention we don’t know what an attr-map looks like yet). Probably there ought to be distinct styling with an explanation beforehand as to what that styling means. | 2008-11-24 | ||
115 | TYPO | Line 3lets a pro Missing a space. | 2008-11-24 | ||
47 | TYPO | Third paragraph (in-ns REPL example); the name of the name namespace should be quoted, i.e. | 2008-11-24 | ||
47 | ERROR | “When you create a new namespace with in-ns, the java.lang package and | 2008-11-24 | ||
104 | SUGGEST | In order to use the duck streams they must first be imported from clojure-contrib: (use ’clojure.contrib.duck-streams) | 2008-11-24 | ||
109 | TYPO | • assoc returns map with a key/value pair added should be • assoc returns a map with a key/value pair added | 2008-11-24 | ||
27 | ERROR | Because of the namespace change, | 2008-11-24 | ||
94 | SUGGEST | In the list of data constructors, “set” is used to construct sets, but it is stated that its argument list is different than list, vector, and hash-map. Function hash-set is the way to construct sets and it is consistent with other constructors in the way it treats its arguments. Perhaps “set” should be mentioned as an additional function to create sets. | 2008-11-24 | ||
128 | OK | There is currently no run-simulation function in concurrency.clj, so it is not possible to follow along in this section yet. Perhaps add it in or make a note of it for the interested reader? | 2009-01-29 | ||
131 | TYPO | The code at the top of the page defines backup-agent, which was already defined on the previous page. The context implies that add-message-with-backup should be defined here instead (since it doesn’t get defined later and is needed at this point). | 2008-11-24 | ||
47 | TYPO | (in-ns myapp) throws java.lang.Exception: Unable to resolve symbol: myapp in this context (NO_SOURCE_FILE:19) whereas (in-ns ’myapp) works just fine | 2008-11-24 | ||
33 | TYPO | Missing space before the \\1 in “as opposed to the | 2008-11-24 | ||
7 | TYPO | The font of the first 3 paragraphs on page 7, up to the footnote numeral, displays in an unreadable squashed-thin font in Okular (Linux KDE4 PDF viewer). This also occurs in various other places in the PDF. | 2009-05-27 | ||
114 | TYPO | “You are going to use this object several times, so seq it and stuff [it] into a var named prop-descs:” (“in” should be “it”) | 2008-11-24 | ||
89 | SUGGEST | I think the statement “conj adds a single item to a collection” may be slightly misleading/confusing. I read that as “you can only insert one item at a time with conj.” It seems like the real distinction you are trying to make is that conj adds an element “as-is” to the sequence. So if you conj a set to a sequence it will keep the set “intact.” Whereas, if you do into it will pull each element from the set (i.e. sequence) and “put it into” the target sequence. I realize I’m using bad verbiage since everything is immutable, but I think I made my point clear. | 2008-12-02 | ||
82 | ERROR | Apparently the call to init on line 11 of the ant-project def requires ant-launcher.jar be included in the classpath in addition to ant.jar. Error: apache-ant-1.7.1 | 2008-11-24 | ||
30 | TYPO | I think (javac {:srcdir src :destdir dest})) is supposed to be (javac {:srcdir src :destdir build})) | 2008-11-24 | ||
38 | TYPO | In this list Form Example(s) Primary Coverage You say that Keyword & Symbol are covered, but I don’t see the coverage. | 2009-01-13 | ||
82 | TYPO | “representation of a Projectdoes not tell you” | 2008-11-24 | ||
68 | ERROR | dotimes requires a vector for init condition. Text has: | 2008-11-24 | ||
68 | SUGGEST | sum-to examples can be more consistent, even if functionally equivalent. | 2008-11-24 | ||
28 | ERROR | Get Java exception java.lang.Exception: namespace ‘introduction’ not found after loading ‘/introduction’ after entering (use ’introduction). | 2008-12-02 | ||
41 | TYPO | Lower third of page: “self-explantory” should be “self-explanatory” | 2008-12-02 | ||
42 | TYPO | “There is an ever shorter syntax” should be “There is an even shorter syntax” | 2008-12-02 | ||
47 | TYPO | Very top: the second occurrence of “foo” should be formatted like the first one | 2009-02-16 | ||
82 | TYPO | In the bullet list under the source code for the ant-project definition: “The proj on line 10 is the return value of the let…” I think should read “The proj on line 13 is the return value of the let…” since line 13 reads “proj))”. That looks like the return value to me. | 2008-12-02 | ||
92 | TYPO | Sentence “The replicate function replicates an element xn times.” is missing a space between x and n, it should read | 2008-12-02 | ||
92 | TYPO | Sentence “The replicate function replicates an element xn times.” is missing a space between x and n, it should read | 2008-12-02 | ||
92 | TYPO | Sentence “The replicate function replicates an element xn times.” is missing a space between x and n, it should read | 2008-12-02 | ||
133 | TYPO | extra “this” in “Calculations like slow-double this are good candidates for memoization.” | 2008-12-02 | ||
84 | ERROR | Using (doto task …) will already return task, it’s not necessary to explicitely return it from the function. | 2008-12-02 | ||
53 | SUGGEST | This section is puzzling to me "This makes sense if you go though it step by step. The metadata macro When you create a new object based on an existing object, the existing I feel like the start of the second P contradicts the first. I think I understand what’s meant now, but only after reading a separate blog article on the topic | 2009-01-13 | ||
66 | ERROR | “…such as to-array, which creates an array directly from any sequence.” You then show to-array passed a vector, which seq? tells us is not a sequence. It seems like there’s a distinction that should be made between things that really are sequences and things that can have sequences wrapped around them by clojure when necessary. | 2008-12-02 | ||
46 | SUGGEST | I’m finding that I want more explanation of a few core things. For example, what’s a symbol and what’s a keyword? I know you want to gloss over now and dig into detail later. But, at this stage of the book I’m toying on my own and not knowing some of the core things is frustrating. I could read ahead, but I prefer to read linearly, and I expect I’m not alone there. I think the best solution to my concerns is put something short and sweet on everything from the lists on Figure 2.1 and Figure 2.2. | 2009-02-16 | ||
41 | OK | In the anonymous functions examples I found I was using the #body syntax, is there a reason that you use the (fn [] #body) syntax instead? | 2009-02-16 | ||
23 | SUGGEST | You might want to mention how to get out of REPL. | 2008-12-02 | ||
21 | SUGGEST | You might want to emphasize more how important it is that you grab the svn revision instead of the last release available as a download. Something along the lines of “The examples in the book will not work if tried on the September 2008 release of Clojure” would probably be sufficient. | 2008-12-02 | ||
47 | ERROR | I get user=> (in-ns ’myapp) instead of user=> (in-ns ’myapp) | 2008-12-02 | ||
47 | TYPO | String works fine but doc doesn’t myapp=> String However, doc seems to be available when fully qualified myapp=> ’clojure.core/doc | 2008-12-02 | ||
52 | TYPO | To test reference quality, should be To test reference equality, | 2008-12-02 | ||
92 | TYPO | Missing space in | 2008-12-02 | ||
92 | SUGGEST | Last example, using cons with a map. The end result is a seq of key/value pairs? Is there an easy way to turn this back into a map? I think a little more detail on this would be worthwhile. | 2008-12-02 | ||
93 | TYPO | “but that order depends on implementation detail and” Should that be “on an implementation detail” or “underlying implementation details”? | 2008-12-02 | ||
59 | TYPO | shouldn’t (and (get {\\b \\y} \\z) 0) be | 2008-12-02 | ||
153 | TYPO | The IPersistentVector example code uses java.util.Collection, not IPersistentVector. Its the same as the previous example. | 2008-12-02 | ||
18 | TYPO | missing closing parenthesis in (defn hello-world … | 2008-12-02 | ||
159 | TYPO | first paragraph: “We have already covered it in detail …” | 2008-12-02 | ||
174 | OK | On Paul Barry’s recommendation, I’m using AquaMacs: h_ttp://aquamacs.org h_ttp://paulbarry.com/articles/2008/07/02/getting-started-with-clojure-and-aquamacs | 2009-02-16 | ||
24 | SUGGEST | Please explain how to do this: “you can test your install by navigating to the directory where you placed clojure.jar, and running the Clojure Read-Eval-Print Loop (REPL).” I use a script suggested by Paul Barry: ht_tp://paulbarry.com/articles/2008/07/02/getting-started-with-clojure-and-aquamacs | 2008-12-02 | ||
67 | TYPO | Figure 3.1 runs off the page | 2009-04-29 | ||
119 | TYPO | In the code for set-property!, for a readable error message there should be a space at the end of “No such property” as there is in “No task named ” on the next page. | 2008-12-02 | ||
125 | TYPO | I find this frustrating: “Notice how the Clojure model fits the real world.” In the current-track example the Clojure model fits the real world, but I can imagine lots of examples where it doesn’t (for example, incrementing a playcount). Maybe STM is most appropriate where the situation being modeled maps intuitively to repointing refs, but if that case exists to be made, you haven’t made it yet. If it’s worth saying, how about “Notice how in this example the Clojure model…”? | 2008-12-02 | ||
59 | SUGGEST | If I’m predisposed to hating lisp, I’m going to look at this example and say: “All the work is done in the indexed function, but the author isn’t counting those lines, branches, etc.” Recommendation: ditch indexed and use indexed’s map function in index-of-any. You get the same stats, but are free from the objection. | 2008-12-02 | ||
16 | OK | “expressions begin with a verb” I would not use the term “verb” here, but rather “operator” since “verb” does not sound familiar to many programmers. However I think most programmers reading this book know what functions and operators are. Maybe some reference to mathematical notation which also puts function names before its arguments might be illuminating. A simple statement that Lisp consistently does the same for operators that are put in infix position in math and one or two examples should make this sufficiently clear for everybody. | 2009-01-29 | ||
109 | TYPO | Last sentence on the page: “to find out much” should be “find out how much” | 2008-12-02 | ||
113 | TYPO | Bullet-point “merge”: “If multiple maps contains” should be “If multiple maps contain” | 2008-12-02 | ||
95 | TYPO | “The functions below are grouped into three broad categories:”, but four categories are listed. | 2008-12-02 | ||
96 | TYPO | “The replicate function replicates an element xn times.” needs a space between “x” and “n”. | 2008-12-02 | ||
102 | TYPO | displayed result of the (for [word… comprehension adds an extra “>” character after each word as:
the> " "
quick> " "
brown> " "
fox> ") | 2008-12-02 | ||
92 | ERROR | (first {:fname “Stu” :lname “Halloway”}) this is wrong. first doesn’t return a seq, but rest does. Should be: (first {:fname “Stu” :lname “Halloway”}) | 2008-12-02 | ||
45 | TYPO | “There is an ever shorter syntax” -> “There is an even shorter syntax” | 2008-12-02 | ||
43 | TYPO | The function “greeting” is defined with a single parameter … “username” … along with a documentation string describing the function. When the “doc” function is invoked upon greeting, the output contains “name” instead of “username” both in the documentation string and in the parameter list. The paragraph on the same page describing arity also refers to “name” instead of “username” . | 2008-12-02 | ||
78 | TYPO | “This makes is very easy …” should be | 2008-12-02 | ||
55 | TYPO | In the last sentence, “useidentical?” should be “use identical?”. Note the space added. | 2008-12-02 | ||
29 | SUGGEST | I’m trying to get clojure-contrib to be recognized. Please indicate what directory you are in to run svn. More detail on how CLASSPATH is interpreted would help (not every reader is up-to-speed with Java and Ant). Please give a concrete example showing the expected directory structure. Is there some way to see what directories (require ) searches? | 2008-12-02 | ||
59 | SUGGEST | “The inner get checks” and “[…] the some function calls[…]”. I would suggest changing the font for both “get” and “some” or use quotes of some sort as the sentence is not grammatically correct otherwise. (I had to read “the some function calls” thrice before understanding that what was meant was “the some function calls”.) | 2008-12-02 | ||
60 | SUGGEST | The discussion of the merits of the functional vs imperative version of ’index-of-any | 2008-12-02 | ||
125 | OK | Something I’ve been struggling with in the presentation I’ve been assembling: more realistic examples of where you would use agents and STM. From my read of how per-thread Vars work, you should be able to override the implementation of any method using a Var, and interesting possibility, especially for testing. | 2009-01-29 | ||
21 | TYPO | “…These features makes Clojure code less list-y…” | 2009-01-29 | ||
75 | TYPO | I get user=> (describe-class “foo”) but I don’t see java.lang.String cannot be cast to java.lang.Class did I miss a setting? | 2009-01-13 | ||
77 | TYPO | you don’t need the commas in the args for startElement (startElement [qname local qname atts] If they are there for clarity, I think the example would benefit from calling that out. | 2009-01-13 | ||
78 | OK | While working with the following code (dotimes [i 5] I tried to use the #(body) anonymous function form, which I couldn’t get to work. I noticed that doing two things (sleep & print) wasn’t going to work well for me. (or maybe I missed the obvious way to do it). Once I noticed that I was trying to do two things, it felt very similar to the section that talks about side effects and (do …). It might be worth pointing it out and discussing how #body doesn’t allow you to execute multiple functions (seamlessly), but fn [] body does. And, whether or not you think that’s a good thing. | 2009-02-16 | ||
80 | TYPO | for those of us who haven’t had to deal with Java classpaths in the past, getting this running was quite a pain. I think a few more hints would be helpful. Just telling me that you have $CLOJURE_CLASSPATH setup wasn’t super helpful. It turned out I was missing a colon at the end of my classpath string. | 2009-01-13 | ||
80 | SUGGEST | It’s not immediately obvious to me why the [_] is needed in (defn WidgetTest-testOne [_] Why would an argument be passed to a test function? | 2009-01-29 | ||
82 | SUGGEST | an example of using (with-open) would be helpful. | 2009-01-29 | ||
83 | SUGGEST | I get to Adding Ant Projects and Tasks to Lancet and I don’t have ant.jar. I’m on a plane, so I’m not getting ant.jar right now. I’m headed to a family members house a bit in the country where I won’t have internet for a week. That’s a bit of a bummer. Back in the intro when I got Clojure, it would be nice if it also said “If you want to download all that you’ll need for this book, you’ll also need clojure-contrib and ant.” Directions could be inline, or you could give a page number and leave the directions where they are. | 2009-01-13 | ||
84 | OK | I found myself wanting to do (Mkdir/class) instead of (class mkdir-task), but I got an error. So I tried something even simpler. user=> (BigDecimal/class) I assume this is because there’s some Java magic that makes .class look like a Field when it’s actually not, but that’s not immediately obvious to non-Java programmers. | 2009-02-16 | ||
95 | TYPO | The functions below are grouped into three broad categories: That reads strangely. Did you mean four categories? Or are you assuming zero based index? =) | 2009-01-13 | ||
104 | TYPO | I think (def x (for [i (range 1 2)] (do (println i) i))) is supposed to be (def x (for [i (range 1 3)] (do (println i) i))) since user=> (range 1 2) | 2009-01-13 | ||
114 | TYPO | (def inventors {“java” “gosling”, “clojure” “hickey”, “ruby” “matz”}) doesn’t seem to need the commas, tho I can see why they might add clarity. If that’s why you use them, I’d point that out, since they aren’t strictly required. | 2009-01-13 | ||
114 | SUGGEST | Why create (def inventors {“java” “gosling”, “clojure” “hickey”, “ruby” “matz”}) (which is a hash, not a set) and never use it? | 2009-01-13 | ||
115 | TYPO | I think | 2009-01-13 | ||
132 | TYPO | Shouldn’t (clear-agent-errors counter) be (clear-agent-errors counter) | 2009-01-13 | ||
135 | SUGGEST | I felt like the monte-carlo simulation was way too large a step from the previous simple agent examples. Something with far less complexity is probably much more instructive. | 2009-01-29 | ||
40 | SUGGEST | “Other than false, nil also evaluates to false” - I think “Other” is an awkward word there; “In addition to false,” would be clearer. | 2009-01-13 | ||
40 | TYPO | “Other than false and, nil, …” - remove comma after “and” | 2009-01-13 | ||
42 | SUGGEST | “If a function is a predicate…” - I don’t think you’ve defined what a predicate is at this point. | 2009-01-13 | ||
46 | TYPO | When to use anonymous functions: “called from more than once place”: replace “once” with “one” | 2009-01-13 | ||
31 | ERROR | Reloading Changed Libraries (use :reload ’introduction) ; clojure svn revison 1131 wants: (use :reload ’examples.introduction) | 2009-01-13 | ||
28 | TYPO | “On 2, hello checks to see if name is already in the set” -> “if username is already in the set”. | 2009-01-13 | ||
29 | ERROR | In clojure r1097, require gives additional (and useful) feedback: | 2009-01-29 | ||
37 | SUGGEST | “As you can see, Clojure has a built-in Ratio type” — could demonstrate this: | 2009-01-13 | ||
53 | TYPO | “Clojure can afford to have a small set of flow should only be one ‘use’ | 2009-01-13 | ||
42 | TYPO | Figure 2.2: Reader Macros “Regex Pattern #”foo" => a java.util.regex.Pattern Section 4.4, Seq-ing Regular Expressions, on" page ### is not given and/or improperly formatted | 2009-02-16 | ||
17 | TYPO | What is “threaded member access”? Why not do something simpler to start? | 2009-01-13 | ||
50-51 | ERROR | pp 50-51 (prob. a W32 diff.) myapp> java.io.File/separator | 2009-01-13 | ||
55 | TYPO | The last sentence, “To test reference quality, use identical?:” should be: | 2009-01-13 | ||
56 | TYPO | “This makes sense if you go though it step by step.” | 2009-01-13 | ||
67 | TYPO | Section: Using Java Collections - Prgrph 2 last sentence: “Clojure’s functional style.” | 2009-01-13 | ||
77 | TYPO | DefaultHandler#startElement accepts params named uri, localName, qName and attributes. You have duplicated the qName and ignored the uri in binding the params which caused slight confusion. | 2009-01-13 | ||
114 | OK | The languages, letters, beverages, inventors example code appears to be laid out in some sort of table within the PDF. | 2009-01-13 | ||
85 | ERROR | (def project (org.apache.tools.ant.Project.)) should be (?) (def project (org.apache.tools.ant.Project.)) | 2009-01-13 | ||
83 | SUGGEST | ANT is a ridiculous XMLism with no expressive power gained in exchange for the perversion of XML’s obfuscation. It seems newcomers to programming understandably acclimate to ANT for the simple reason that they haven’t used make, or are averse to make’s stupid tab syntax, whereas multi-decade Unixers see it for the ephemeral pop XML-culturalism it is. The book is fantastic. | 2009-01-29 | ||
67 | ERROR | The snippet on the page reads: To make this work with clojure-svn as of Sun Dec 7 19:29:07 CET 2008 I had to add ‘-quotes: | 2009-01-13 | ||
47 | SUGGEST | With respect to the square-corners function. For the developer who is not familiar with Lisp, this example isn’t completely clear. It took me a couple reads to realize that the let expression itself produces a value. This is not the first time that ‘let’ is used, but this is the section where ‘let’ is explained. It would be good to be more explicit about how the value of the let expression is calculated, possibly by showing the result of calling square-corners. Really, it just seems like ‘let’ could use a better introduction somewhere. | 2009-01-29 | ||
92 | TYPO | In the text bubble, the origin of Cons “it is more accurate to say Missing a space cons Constructs a new sequence | 2009-01-13 | ||
150 | TYPO | Presumably, the string in the (unless true…) example should read “this should not print” | 2009-01-13 | ||
98 | SUGGEST | You show using the list, vector, hash-set and hash-map functions. I think it would be good to add the sorted-set and sorted-map functions. | 2009-02-16 | ||
134 | TYPO | “You number will probably not match those below” should be “Your number will probably not match those below” | 2009-01-13 | ||
155 | SUGGEST | “In the code above, the bolded portions are the body to be generated, and the remainder is the macro code.” Even at 800% zoom, it’s hard for me to detect any bolding. Perhaps I’m looking at the wrong code, or bolding isn’t working and you need a different font instead. | 2009-04-29 | ||
79 | ERROR | I think this is an error? qname is there twice in the parameter list. (proxy [DefaultHandler] [] This is at the top of the page. | 2009-01-13 | ||
171 | TYPO | Notice the doubled parentheses. The inner parentheses call :has-run to Should be ‘has-run?’ | 2009-01-13 | ||
186 | TYPO | Per fectionist that you are, you cannot stand that vectors print with There’s an extra single quote after “So’” | 2009-01-13 | ||
46 | TYPO | In the output of (doc greeting), the doc-string should be “Returns a greeting of the form ‘Hello, username.’”, not “…‘Hello, name.’”. It looks like the parameter name and doc string were changed, but the code wasn’t re-run. | 2009-01-13 | ||
27 | SUGGEST | It would be nice to show how to create a struct and then access the fields after you introduce defstruct. I can do: But haven’t yet figured out how to get the slots, e.g., the following fails: | 2009-01-13 | ||
39 | TYPO | You say: Given that how do we get >, <, = into symbols? Since you show (< 5 2) in your examples on this page, we know that those characters are allowed (or are they something that looks like a symbol but isn’t). | 2009-02-16 | ||
52 | ERROR | In the code example at the top of the page, str-join isn’t imported in the use statement: (use ’[clojure.contrib.str-utils :only (re-split)]) even though it is used 3 lines later: (str-join " " [w1 w2 w3 “…” ]))) I believe you want this instead for the use statement: (use ’[clojure.contrib.str-utils :only (re-split str-join)]) | 2009-01-13 | ||
156 | ERROR | Top (description of macroexpand): “until the returned form is longer a macro” should have a “no” | 2009-01-13 | ||
52 | ERROR | For the ellipsize function definition I think you need to ‘use’ the str-utils str-join function also else you get this error “java.lang.Exception: Unable to resolve symbol: str-join in this context (NO_SOURCE_FILE:4)”. I worked properly when I added “(use ’[clojure.contrib.str-utils :only (str-join)])”. | 2009-01-13 | ||
49 | ERROR | The ellipsize() function example has incorrectly added the contrib.str-utils library. It reads: | 2009-01-13 | ||
88 | ERROR | While working along with the clojure version suggested, the safe-instantiate-task function did not work, with the problem apparently being the function “throw-if.” I checked the api and special forms and could not find “throw-if”. I changed the code to I also wrote a throw-if as follows: I found this possible problem on page 88 (Section 3.5) of my pdf, but the above errata for the page do not match the contents on my page. | 2009-01-13 | ||
151 | TYPO | double colon at the end of the sentence: “Macros provide a layer of indirection, so that you can automate the common parts of any recurring pattern..” | 2009-01-13 | ||
169 | TYPO | “… let’s use them to convert Lancet until a DSL.” ‘until’?? perhaps you mean ‘into’? | 2009-01-13 | ||
169 | TYPO | “However, calling Lancet is clunky, and using it feels more like calling an API that writing a build script.” ‘than’ rather than ‘that’ | 2009-01-13 | ||
171 | TYPO | “… extracts the has-run-rn from its metadata …” this should be the ‘has-run-fn’ | 2009-01-13 | ||
171 | ERROR | “(defn has-run? [v] ((:has-run (meta v))))” i think this should be | 2009-01-13 | ||
174 | TYPO | “Make sure that the function itself and the has-run? and rest functions work as expected.” ‘reset’, not ‘rest’ | 2009-01-13 | ||
81 | TYPO | The “Creating Java Classes” section disappeared. It was in beta 3, but is now missing. | 2009-01-29 | ||
20 | SUGGEST | It might be confusing to talk about “keys of a set” before having clarified what sets are. If readers are coming from languages like Python and JavaScript, they would be used to the word `keys’ being used in the “key/value” context of Python dictionaries or JS objects. For readers like me, it would be clarification enough to point out that Clojure has collections like maps, sets, and vectors (as on p.29) before talking about sets. | 2009-02-16 | ||
20 | SUGGEST | (top of page) It seems a tad confusing to call the first argument of commute `ref’ right after covering `ref’ as a function of its own. | 2009-01-13 | ||
87 | TYPO | #=(var user/echo-task) should be #’(var user/echo-task) | 2009-01-13 | ||
52 | TYPO | The definition of ellipsize needs re-split AND str-join from clojure-contrib str-utils: (use ’[clojure.contrib.str-utils :only (re-split str-join)]) | 2009-01-13 | ||
12 | TYPO | Missing “that”: Lancet is a Clojure-based build system [that] works with Apache Ant. | 2009-01-13 | ||
15 | SUGGEST | Link problem: in the pdf, the grey boxes are not clickable; only the text within it is. I find myself clicking several times until I hit a letter (using evince in ubuntu to display the .pdf). For example the box “Download examples/preface.clj” | 2009-03-31 | ||
17 | SUGGEST | Notice that in macosx java 5 is preinstalled, and that newer versions come from developer.apple.com, not from sun.com. | 2009-01-29 | ||
17 | SUGGEST | Chapter one assumes one is using a terminal — since the introduction states this book is not for novices to programming languages, perhaps that’s ok. | 2009-01-29 | ||
19 | SUGGEST | ‘coll’ is not obvious for ‘collection’. It wasn’t to me the first time I saw it, it isn’t still now—had to think 2 seconds. I suggest addding a table of common informal abreviations… or at least a footnote. | 2009-01-13 | ||
23 | TYPO | Missing section number: | 2009-03-20 | ||
24 | SUGGEST | The floating box for running unit tests is out of place. nothing else in the text refers to it. | 2009-02-16 | ||
25 | TYPO | “examples.introdution” is missing a ‘c’ | 2009-01-13 | ||
44 | OK | Although rhickey doesn’t mention the dot ‘.’ as a reader postfix macro, thats who it looks to my perhaps misguided self: user=> (macroexpand-1 ’(String. “hello”)) The table doesn’t mention the prefix and postfix dots at all. | 2009-02-16 | ||
43 | TYPO | Figure 2.1 overflows past the page margins (at least in ubuntu/evince). Plus, it’s not a figure but a table. Same with figure 2.2. | 2009-04-29 | ||
44 | TYPO | Figure 2.2 overflows past the page margins (at least in ubuntu/evince). Plus, it’s not a figure but a table. Same with figure 2.1. | 2009-04-29 | ||
63 | TYPO | Missing an ‘e’ in “unnecessary”: | 2009-01-13 | ||
63 | TYPO | Misspelled “langauge”: | 2009-01-13 | ||
66 | TYPO | On the previous, title page, “Sun” is capitalized when it shouldn’t: it’s the star, not the company. | 2009-01-13 | ||
66 | TYPO | Never heard of “statics” (plural) as an adjective: | 2009-01-13 | ||
67 | TYPO | Same again: never heard of “statics”. Perhaps you are using it as shorthand for “static fields and methods”? The text: | 2009-01-13 | ||
67 | TYPO | I suggest Math/PI (no parenthesis) as an alternative to (. Math PI). If clojure makes a point of having less parens and accessing static fields as variables in a namespace, let it show! | 2009-01-13 | ||
68 | SUGGEST | I suggest adding a (note the dot at the end of ClassName) after ‘form’ in the sentence: | 2009-01-13 | ||
69 | TYPO | Figure 3.1 overflows the page width a lot on the right. | 2009-04-29 | ||
69 | ERROR | “doto” needs revision: now it needs dots for each method call. (later on, on ant project, you use it with dots). | 2009-01-13 | ||
71 | SUGGEST | The asterisk in the code font is not very clear, at least in ubuntu/evince. I’d suggest using a proper, courier-style asterisk (with latex, the impossible is possible). | 2009-05-27 | ||
72 | TYPO | For mnemonics, should mention that ‘memfn’ means ‘member function’ or ‘method function’. Otherwise it’s just an arbitrary weird name. | 2009-01-13 | ||
74 | SUGGEST | TDD note is unprofessional. | 2009-01-13 | ||
77 | TYPO | Adding type hints: 3 purposes, not two. The second one is dual (you even added an ‘and’). | 2009-01-13 | ||
77 | SUGGEST | The #^Class example is a bit ill-chosen, because it’s confusing: the description uses #^ClassName. Why not choose another example, showing for example optimization for #^String? | 2009-02-16 | ||
78 | SUGGEST | “Calling Clojure from Java” is misleading. I can’t come up with a better title, but it needs to convey the idea that it’s not the java programmer who is doing the calling, but java libraries. Perhaps “Handling Java callbacks in Clojure” or something along this line. | 2009-01-29 | ||
81 | ERROR | “Loading Clojure into a Running Java Application” is empty. | 2009-01-29 | ||
82 | SUGGEST | try-catch is explained in “Cleaning up resources”, not in “Wrapping checked exceptions” — reads misplaced to me. | 2009-01-29 | ||
83 | TYPO | Space needed between ‘r’ and ‘f’ of “jarfile”; even the font is different: | 2009-01-13 | ||
91 | SUGGEST | Code block is broken in an ugly way, leaving one stranded line in the next page, after a floating text box. | 2009-03-20 | ||
103 | TYPO | This sentence doesn’t make any sense to me. Where’s the gotcha? why? | 2009-01-13 | ||
105 | OK | 4.4 bullet-list is a repetition of chapter 4 opening bullet-list. Plus it’s missing Strings and arrays (which, in java, are neither collections nor any of the other entries) | 2009-01-13 | ||
108 | OK | Any reason not to use (memfn getName) instead of #(.getName ) ? Same for map #(.toUpperCase) above. | 2009-01-13 | ||
59 | SUGGEST | Someone following through the documents in the REPL will have redefined serializable-stu via (def serializable-stu #^{:serializable true} {:name “stu”}). Subsequently, (def stu-with-address (assoc serializable :state “NC”)) will not have e-mail associated with it. Even so, the printed value is “user/stu-with-address”, not {:name “Stu”, :email “stu@thinkrelevance.com”, :state “NC”} as shown on page 59. | 2009-02-16 | ||
68 | ERROR | Clojure’s logging message seems to have changed (.getLocation… blahblah) now returns: #<URL file:<path-to/clojure.jar>> | 2009-01-13 | ||
70 | TYPO | In the paragraph, “The odd output is courtesy…” toString()for" needs a space. | 2009-01-13 | ||
58 | OK | “You can prove that stu and serializable-stu are different objects by calling identical?:” But this is true even if I make a similar stu without any metadata: user=> (def stu {:name “Stu” :email “stu@thinkrelevance.com”}) | 2009-01-13 | ||
20 | TYPO | The line | 2009-01-29 | ||
49 | TYPO | …needs to be called from more than on[c]e place. | 2009-01-13 | ||
120 | TYPO | I can’t see any reason you’d want this (.invoke (. pd getWriteMethod) inst (into-array [value])))) instead of (.invoke (.getWriteMethod pd) inst (into-array [value])))) | 2009-01-13 | ||
143 | TYPO | The output of running these has changed from -> #=(var user/println-once-agent) and -> #=(var user/println-once) to #’user/println-once-agent and #’user/println-once | 2009-01-13 | ||
121 | TYPO | … function lets you pass keys as symbols instead of strings. Are they symbols or keywords? Prior to this sentence I thought :foo was a keyword. | 2009-01-13 | ||
73 | SUGGEST | The (bean ..) example doesn’t work with Java 6, at least not on the Mac. I don’t believe 6 directly supports DES/CBC/PKCS5Padding ciphersuites. I think you should find a less fragile bean example. | 2009-02-16 | ||
139 | ERROR | (use ’[clojure.contrib.memoize :only (memoize)]) It looks like memoize has been moved from contrib to clojure.core. | 2009-01-13 | ||
41 | OK | “…you are passing it a single argument which contains the argument list.” When you say the “the argument list” it somehow seems odd. Might it be better to say “a sequence”? | 2009-01-13 | ||
41 | OK | Sorry, I wish I could edit my suggestion. Instead of “the argument list”, how about “…you are passing it a single argument which is a sequence containing the argument list.” | 2009-01-13 | ||
41 | OK | Ignore my suggestions on this page. I was wrong and I just didn’t originally get what you meant by “sequence.” I think part of it is that I automatically started thinking about types. For example, ‘(interleave “Attack at midnight” “The purple elephant chortled”)’ returns a list. But you refer to it as a “resulting sequence.” The reason that calling ‘(str (interleave "Attack at mi…’ doesn’t work as expected is that the one argument, a list of characters returned by interleave, is passed to the function str and is converted to a string just like it printed out previously, but it is preserved by escaping the slashes. Apply as described seems a bit magical. But maybe it could be better explained than as “unrolling argseq into an argument list”. Really it is a bit like an in place re-write. It is equivalent to evaluating argseq to a value and then evaluating “(f resulting-value-of-argseq)”. i.e. The apply function places the passed in function at the head of the list created by evaluating argseq. And the newly created list is finally evaluated. e.g. user=> (interleave “blah” “blek”) (apply str (interleave “blah” “blek”) | 2009-01-13 | ||
44 | OK | I was immediately curious what the quote function would be used for. The following would have been nice. user=> (apply + (1 2)) user=> (apply + ’(1 2)) | 2009-02-16 | ||
148 | TYPO | Line 2 “before using a macro” rather than “before use a macro” | 2009-01-13 | ||
52 | TYPO | The use statement in the ellipsize example should be getting str-join as well e.g. | 2009-01-13 | ||
52 | SUGGEST | In the example.. Wouldn’t it be slightly better to use “\\s+” for the regular expression, which wouldn’t add any extra complexity for the reader? That way something like the following would work as expected. (ellipsize “The quick brown fox jumped over the lazy dog.”) | 2009-01-29 | ||
53 | OK | You provide many small examples, why not provide an example as to why you should use the clojure.core name space? It would make it obvious to the reader why it is needed. user=> (in-ns ’myapp) myapp=> (clojure.core/use ’clojure.core) | 2009-01-29 | ||
54 | OK | (use :reload ’examples.exploring) “use reload” appears to be an important and often used concept. Why not provide the smallest possible example of using it? Maybe I’ll give an example tomorrow when I’m not so tired. | 2009-02-16 | ||
54 | SUGGEST | “If you make changes in a namespace and want to make those changes Maybe it is just me, but this could be misleading. Initially I thought this implied that changes made to a namespace in the REPL must some how be “exported” to the running program and that things do not take effect immediately to a program running in a separate thread. Thus, I thought the redefinition of println-alt below would have no effect on the running function which takes 20 seconds to complete. I thought for the redefinition to take place, there had to be some type of export into the running space. Obviously, I was wrong. I now take it that what you meant to say is… “If you make changes to a file associated with a particular namespace and you want to make those changes available to a running program, then add the :reload option to use it.” (in-ns ’test) (in-ns ’user) | 2009-02-16 | ||
59 | ERROR | problem with ‘(def serializable-stu #^{:serializable true} {:name “stu”})’ ;first case shown ;problem case shown ;suggested case | 2009-01-13 | ||
171 | TYPO | The meta key for has run is :has-run-fn, but the has-run? function is looking for has-run. | 2009-01-13 | ||
62 | SUGGEST | It is a bit hard to show in this example, but since you are pointing out how things work in pieces you might try to show what “some” does. At the minimum you might describe it as a function that takes in a function as the first argument and the second argument as a list of arguments to be applied to the function. For me, the two examples were illuminating. | 2009-02-16 | ||
71 | SUGGEST | (map (fn[x] (* x 3)) (range 1 11)) favor instead (map (fn [x] (* x 3)) (range 1 11)) This would be match the style you have done so far throughout the book. While playing around I discovered that (index-of-any“zzab”#{\\b\\y}) would have worked on an earlier page, but obviously few would do such a thing. | 2009-01-13 | ||
31 | SUGGEST | Cross references to the sections about three items listed under “There are three reasons that Clojure can attract more interest now than functional languages have in the past:” would be useful for those who are curious about those aspects of Clojure. | 2009-01-13 | ||
33 | ERROR | I get a different output to the anonymous function mid-page: user=> (.start (new Thread (fn [] (println “Hello” (Thread/currentThread))))) | 2009-01-29 | ||
82 | SUGGEST | I recommend the following as an example for “with-open”. (import ’(java.io File FileInputStream)) | 2009-01-29 | ||
89 | TYPO | for readers of the B4 (but covered by someone else on the previous page)… instantiate-task will fail as written. “throw-if” is not a valid function so far as I know. use the following instead. (defn instantiate-task [project name] | 2009-01-13 | ||
175 | TYPO | define-ant-task will create a function named after an Ant task. The Remove extra will. | 2009-01-13 | ||
176 | TYPO | Test define-ant-task by creating a mkdir task, and then calling mkdir: According to the macro there should be a second argument passed in. I believe it is the actual string name for the task (in this case “mkdir”). | 2009-01-13 | ||
179 | TYPO | define-all-ant-tasks in the printed code has two implementations. Remove the first as it is incorrect. | 2009-01-13 | ||
192 | TYPO | Clojure’s inspector library uses Swing to create simple views of data. You Did you mean inspect-tree in the second example? | 2009-01-13 | ||
190 | TYPO | :acc/Checking in service-charge example is missing a colon | 2009-01-13 | ||
92 | TYPO | “In the output above, the result of rest or cons is a seq, not a vector.” Don’t you mean “not a list” instead of “not a vector”? When vectors are printed they are surrounded by “[ ]” and a list is surrounded by “( )”. However, a list and a seq are both surrounded by “( )”. | 2009-01-13 | ||
110 | ERROR | This may be nit picking, but the “non-svn?” function doesn’t work very well unless you are checking stuff in the current directory. For instance…. user=> (defn non-svn2? [file] (not (.startsWith (.toString file) “.svn”))) You could just make note of it if you don’t want to do it the right way, which is more complicated. That way someone doesn’t copy it into something of value. I wrote the program as specified without looking at your example. I came up with something a bit more safe. But I didn’t use the “for” construct as requested. (defn non-blank? [line] (defn regex-matches? [str regex] (defn non-svn-dir? [file] (defn non-svn? [file] (defn clojure-source? [file] (defn count-file [file] (defn clojure-loc? [dir] | 2009-02-16 | ||
128 | SUGGEST | I recommend.. “Notice that the update function is conj (short for conjoin), not cons. The important distinction here is argument order because of the way commute is defined.” On a first pass read about commute, I misunderstood what you were specifically going on about with argument order and it took a few moments to get back on track. You say, “Using commute instead of ref-set makes the code … less contentious for threads. … The important distinction here is argument order.” I took this to initially mean that the argument order matters because it is less contentious for threads and not because of the way commute works/is defined. I know you get on about this right after you show (cons item sequence) But I was on the wrong track and thought you were merely just stating it as a matter of fact and not that it is the reason to care about ordering. | 2009-01-13 | ||
12 | TYPO | Missing “will”: Starting from scratch, you [will] build a usable subset of Lancet by the end of the book. | 2009-01-13 | ||
88 | ERROR | add (use ’[clojure.contrib.except :only (throw-if)]) before defining safe-instantiate-task. | 2009-01-13 | ||
133 | ERROR | @counter it should be @counter We redefined the counter back to zero. Then we unsuccessfully tried updating it. And then when we print it. Thus the value is 0 and not 1. | 2009-01-13 | ||
41 | ERROR | You define apply as: but the Clojure API defines it as: This caused a bit of confusion for me on pg 135 in your definition of parallel-guess-pi. Apply was being passed 3 arguments instead of the expected 2. | 2009-01-29 | ||
135 | SUGGEST | I recommend taking the time and space to explain exactly how the parallel-guess-pi works. My take on this…(Feel free to use or change.) Line 2 defines trials as the number of guesses that each agent should take. We don’t care if we are slightly off and do not mess with the remainder since this is a case of shot guns and grenades only needing to be close enough. Line 3 defines defines agents as a list of individual agents. This list is created by a for comprehension. We just need to loop as many times as there are threads and we do not need any information from the looping process. Thus we use “_” to throw away the number generated by using “range”. Line 4 sends each agent on its mission. Remember that doseq executes “(send a run-simulation)” in series, but send returns immediately. Line 5 waits for all of the agents to finish. It is interesting to note that apply is being used where we do not see any parenthacies around the second argument. This works because “agents” is a list. Line 6 merges all the results together into a single number. You might note that this is the first time that we are using “apply” to pass in an argument besides the contents of the argument list. We are passing in “+” to the “merge-with” function in addition to the maps. Thus there are three arguments instead of two. Also it is minor, but if someone is typing in everything this name conflicts with the one already defined. Maybe changed it to parallel-reckon-pi. | 2009-01-29 | ||
137 | OK | I think it would be very helpful to others to add (let [foo “let foo”] (println foo)) as an example and explain the difference between it and (let [foo “let foo”] (print-foo)) and (binding [foo “bound foo”] (print-foo)) I have used thread local variables before in Java, but I think it would be helpful to see how and why this would be used. Off hand it would seem a lot less likely to be needed because of the functional nature of the language. I also think the example you used could be slightly expanded, to clarify what exactly is overshadowed. Below is what I had in mind. (def foo 10) | 2009-02-16 | ||
139 | ERROR | for other readers of B4… (defn memoize is the missing function definition. It was removed from contrib and I don’t readily see it in my version of clojure. It is suppose to making its way there? | 2009-01-13 | ||
20 | OK | In the “introduction” example, the variable “past-visitor” is better named “past-visitor?”. That’s in my opinion of course. Forgive me for speaking out of turn! | 2009-01-13 | ||
142 | SUGGEST | I think the description of how the function works could be made a bit more clear. Line 2 stores the original value of the agent in sentinel. This value sticks around with the function because it is referenced by the function. Whenever you see the sentinel value equal to the agent value, you know that the function has not yet run. Also remember that “[& args]” means that the args symbol is assigned the one or more arguments passed to the anonymous function. Inside the new function…. must use send-off instead of send. **Remember that send-off sets the agent to the return value of the function that ran. Thus when you try to run it again, the value of the agent and the sentinel will not match and the function will not be executed twice. | 2009-01-13 | ||
26 | OK | The Clojure implementation of blank? has “Download examples/introduction.clj” above it. Wrong file. As an aside, I don’t know what common practice is, but it might be nice for beginners if a predicate function like blank? returned true or false. | 2009-01-13 | ||
26 | OK | SORRY — INCORRECT ERRATUM ABOVE. “The Closure implementation of blank? …” It is not the wrong file at all. Forgive my hastiness. I thought it was a separate file for each code example, but it’s not. | 2009-01-13 | ||
176 | ERROR | (define-ant-task mkdir mkdir) is the correction… as someone pointed out there is a second argument missing, but it is not a string. | 2009-01-13 | ||
176 | SUGGEST | nitpicking, but what about (sort (task-names)) instead of (task-names) No one would really look through an unsorted list that long. :) | 2009-01-13 | ||
40 | TYPO | In the example code involving small-int and big-int, the return values are inconsistent: #’small-int vs #’my-app/big-int. When I run that code in the REPL, I get #’user/small-int and #’user/big-int. | 2009-01-13 | ||
41 | TYPO | The two code examples involving interleave contain incorrect formatting, either for the code, or the return value. (“Attack at midnight” is some extra context if needed.) | 2009-01-13 | ||
43 | SUGGEST | On this page, you introduce the reader to the functions true?, false? and nil?. It might be worth explaining the convention of using question marks in the names of functions that behave as predicates. Question marks in function names will be seen as unusual by a subset of your readers. | 2009-01-29 | ||
53 | TYPO | Inconsistent formatting of exceptions (e.g. java.lang.Exception: No such namespace: File). In one case it’s preceded by an arrow and is blue. In the other case it’s not preceded by an arrow and is the same colour as the code. | 2009-03-20 | ||
183 | OK | (defmulti my-print class) You define both of these methods and then turn around and ask us to call This works because we did define that function earlier, but obviously it should be (my-print “stu”) because we are testing what we just wrote. | 2009-01-13 | ||
184 | OK | “… each implementation of my-println …” should be | 2009-01-13 | ||
184 | OK | (my-println 42) should be (my-print 42) | 2009-01-13 | ||
185 | OK | (my-println (java.sql.Date. 0)) should be (my-print (java.sql.Date. 0)) and (my-println (java.util.Random.)) should be (my-print (java.util.Random.)) | 2009-01-13 | ||
187 | SUGGEST | You indicate to place the code in the namespace “exam- For brevity in the book, you could just note that you are not issuing that command at the REPL. | 2009-01-13 | ||
63 | OK | “So it turns out that writing indexForAny without for loops or variables is actually easier. As a bonus, the code becomes shorter, easier to read, and less error prone.” I found the Clojure version of indexForAny to be hard to read, hard to understand (it needed a lot of explanation in the book) and quite error-prone (I made a lot of errors trying to reimplement it without looking at the source). The LOC metric is not fair, because the Clojure code is very dense. This would be more fair:
Also worth mentioning is that I found it so much easier to implement using loop/recur. It worked first time, in fact.
That’s clearer to me because the code is highlighting the essential point of the function: if the current character is a “matching” one, return the current index. There might be some value in presenting both functions. Just for your consideration :) By the way, my background is Ruby, not Lisp. | 2009-02-16 | ||
79 | TYPO | “In this case none are needed”: missing period at end of sentence. | 2009-01-13 | ||
81 | OK | Wouldn’t: (Manifest. r) be: (def newManifest (Manifest. r)) , since you want to be able to refer to the new object as newManifest? | 2009-01-13 | ||
18 | TYPO | The snippets don’t reflect the quotes in output that are actually there. user=> (hello “Hans”) | 2009-01-13 | ||
11 | OK | Hi Stuart, This is an open request for you to add a chapter. I know you are probably rolling your eyes by now given that you have an aggressive publish date, but please here me out. Object Oriented design has reigned king for well over a decade. And a large majority of your likely readers come from the Java and .NET world. Many of us, including myself, have years of experience designing utilities and applications with object oriented design in mind. This mindset has a way of shaping the larger structure of programs—which includes design patterns and even larger super structures. The way that you encapsulate methods and data is certainly different in Clojure. You don’t define them as private, but use “let” instead. Name spaces are not set in stone. OOP polymorphism primarily revolves around being able to call a particular method chosen at runtime and it usually involving a hierarchy of types. And this polymorphism is used everyday without much special thought given about it. But as you point out in your chapter on multimethods, it isn’t used frequently when programming in Clojure. Thread-local bindings in Clojure go much further in concept than java.lang.ThreadLocal in Java. And lisp macros open up a world of wondrous possibility and danger that you don’t find in Java and .NET (including F# from what I can tell). And java’s ideas on metadata with annotations is far less capable than Clojure’s idea of meta data. Clojure is far more alien to us than even a language like Scala or F# that allows one to blend OOP and FP. Sure you can call Java from Clojure, but that isn’t the point. Immutability and the world of verbs is likely to have a large impact on the structure of things. It would be nice to have some thoughts from you as it relates to Clojure about how FP affects programs on the large, the medium, and the small. For example on the small, I would have never considered storing helper functions in meta data like you did with Lancet in chapter 7. On the medium, you could talk about how the need for OOP design patterns are largely mute or the possibility of DSLs in ones code base saving a great deal of time and LOC. And on the large, I just don’t really know. For a start, you might take a look at " orgonblog.spaces.live.com/Blog/cns I think it is even more important to air out this idea of structure because there seems little if anything written about the subject. You can find plenty of material about OOP analysis and design, but what is there for FP analysis and design? I can find very little on the subject, especially languages like Clojure that are more purely functional. I’m sure one could write an entire book on this subject, but it would be great to hear 15-20 pages from someone that has written a substantial number of lines of code in a FP language on a nontrivial sized code base. Feel free to email me at kaz0358 AT ksu.edu if you have any thoughts or questions on what I’m trying to get on about. | 2009-01-29 | ||
90 | TYPO | ’seek-a-bull: missing/incorrect quotes? Should be “seek-a-bull” or “seek-able” or “seekable”? (Quotes included.) | 2009-01-13 | ||
157 | TYPO | “Rewrite chain using spicing unquote to splice in rest:” — “splicing” is typo’d as “spicing”. | 2009-01-13 | ||
42 | ERROR | Keyword :tag, :doc Section 2.1, Forms, on page 37 | 2009-01-13 | ||
108 | TYPO | Formatting error for the output of the function after the comment “;overkill”. The output should be blue and left-aligned. | 2009-05-27 | ||
109 | TYPO | Incorrect indentation in code under “filter to count only non-blank lines”. | 2009-01-13 | ||
148 | TYPO | “The Only Way To Encapsulate A Pattern.” I think you have two periods at the end of that sentence. | 2009-01-13 | ||
153 | TYPO | In “when-not” at the bottom of the page, “-not” is a different colour from “when”. | 2009-05-27 | ||
155 | TYPO | “In the code above, the bolded portions are the body to be generated, and the remainder is the macro code.” Maybe it’s too late at night, but I’m not seeing any bolded portions. | 2009-04-29 | ||
66 | SUGGEST | You should give a quick example to on how to call a java method that takes a variable number of argument list. I ran into this and it took a bit of googling to find the answer. This seems like a good example… (. System/out printf “%s %s %s” (to-array [“1” “2” “\ | 2009-02-16 | ||
63 | TYPO | word “language” spelled incorrectly in footer | 2009-01-13 | ||
131 | TYPO | “That is because senddoes not know the new value.” Note the missing space. | 2009-01-13 | ||
137 | OK | I did not find the section on bindings very illuminating. Turning to the REPL, I found the following sequence helpful.
Hope that’s of use. | 2009-02-16 | ||
142 | TYPO | “Line2 stores the original value…”. Note the missing space. | 2009-01-13 | ||
145 | TYPO | “runonce returns a vector of the three locally-defined functions has-run, reset-fn, and the anonymous function starting on line 9.” “has-run” is supposed to have a question mark after it. | 2009-01-13 | ||
44 | TYPO | An overview of the different usages of the # would be extremely helpful. There are at least 7 in the book : | 2009-01-29 | ||
59 | ERROR | (def persistent-stu #^{:com.thinkrelevance/persistent true} stu) should something like: (def persistent-stu #^{:com.thinkrelevance/persistent true} {:name “stu”}) because of the same “where did the meta go?” warning you described on the previous page. | 2009-01-13 | ||
121 | ERROR | … function lets you pass keys as strings instead of keywords | 2009-01-13 | ||
70 | SUGGEST | (make-array (. Character TYPE) 5) I think you should really show how to make a native array type. I spent quite a bit of time searching for this. You might also mention that there are helper functions for creating native number arrays such as int with the int-array function. | 2009-02-16 | ||
23 | ERROR | The line continuation character in the Windows command line interpreter is carat (^) not backslash (\\). The launch command on Windows should be: SET CLASSPATH=/jars/clojure.jar;^ | 2009-01-13 | ||
57 | SUGGEST | I think it would be very helpful to talk about the three following cases as it relates to loop/recur. And what their impact is particularly on memory. Some might be surprised that it does not have tail call optimization. This is the simplest case that I could think of. Maybe this is the right spot to talk about it. I don’t know what you got cooking in chapter 5. (defn piano-plus [x y] (defn piano-plus-try [x y] (defn piano-plus-better [x y] | 2009-02-16 | ||
123 | SUGGEST | Here is a simple idea for chapter 5. There should be at least a couple examples of how to get around the “recur only at tail position” problem. (defn fib [n] (defn fib-list [] ; have to be creative | 2009-01-29 | ||
40 | ERROR | The class of expression (def big-int (* 1000 1000 1000 1000 1000 1000)) as received from evaluating expression is java.lang.Long on my computer instead of java.math.BigInteger in the text. I’m using Max OS X 10.5.6 with this version of JVM: Java™ 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284) | 2009-01-13 | ||
33 | TYPO | bad hyphenation for “stand-alone” in the text it’s hyphenated “stan-dalone” | 2009-03-20 | ||
34 | TYPO | in the ant example xml the “compile” target is colored differently than the rest of the example (blue instead of red), this was in Evince 2.24.1 (Ubuntu 8.1) | 2009-05-27 | ||
50 | TYPO | “(let [bindings] exprs)” isn’t formatted the same way other representations like this are, that is, with blue text and a grey box around them. | 2009-01-13 | ||
56 | TYPO | (loop [bindings ] exprs) is missing it’s gray background box | 2009-01-13 | ||
57 | TYPO | “(recur exprs*)” is missing it’s gray background box | 2009-01-13 | ||
60 | TYPO | the result of “(meta #’meta)” is different than shown (using the version of clojure asked for in the first chapter). The result I get from the REPL is as follows: | 2009-01-29 | ||
60 | ERROR | (def persistent-stu #^{:com.thinkrelevance/persistent true} stu) This doesn’t add the metadata, in fact it’s the same form as your “be careful” example on the previous page. | 2009-01-13 | ||
154 | TYPO | (when-not false (println “this”) (println “and also this”)) | 2009-01-13 | ||
135 | ERROR | Executing this code from page 135 triggers the following exception: java.lang.IllegalArgumentException: No value supplied for key: user$fn__1197@89f302 (NO_SOURCE_FILE:2) I’m using the latest versions of clojure (r1207) and clojure-contrib (r368) | 2009-01-29 | ||
73 | ERROR | (. currentTimeMillis System) does not work. | 2009-01-29 | ||
216 | TYPO | first line should read (compojure.jetty/start snippet-server) | 2009-01-29 | ||
207 | TYPO | “You can add your own assert expressions to test-is, see the source code for the assert-expr multimethod for details.” The comma in that sentence should be a semi-colon. | 2009-01-29 | ||
209 | SUGGEST | In the function ’insert-snippets, I was confused for a while at the use of the let variable “created_at”. That is the name of a column, but you are using it to represent a timestamp. A small thing, I know, but I think the variable would be better named “now” or “timestamp”. | 2009-02-16 | ||
211 | TYPO | “Verify that the improved select-snippets works: […]” The code following this sentence doesn’t call select-snippets. I’m pretty sure it doesn’t even call it directly. I may be wrong, but at the very least, I’m confused, which is a worthwhile bug report :) | 2009-01-29 | ||
213 | TYPO | Sorry if this erratum report is incorrect, but… “This example is from demo.cll:” I’m going out on a limb and assuming that should be “demo.clj”. | 2009-01-29 | ||
217 | TYPO | “submit-button is a trivial helper, with a signature analogous [to] text-area’s.” Missing the “to”. | 2009-01-29 | ||
225 | SUGGEST | It’s not particular to this page, but on one page we have three code extracts with the exact same header: “Download examples/snake.clj”. This repetition seems unnecessary to me; you may want to save some space. As a reader, I’m well aware that I can download the sample code, and am willing to look at the beginning of the chapter to find out how to do so. Just a thought. | 2009-01-29 | ||
226 | OK | (defn head-overlaps-body? [{[head & body] :body}] You have head and body flipped around as arguments to “includes?”. (defn includes? | 2009-01-29 | ||
227 | OK | (turn (create-snake) [0 –1]) I wonder why you aren’t using (dir VK_UP) instead of [0 –1]. That goes for a few other function calls up to this point as well. | 2009-02-16 | ||
54 | SUGGEST | You don’t cover all of the special destructuring forms. I recommend that you either add them. Or point out that there are others and create a footnote with the URL to clojure.org/special_forms indicating to look under let. I was a bit surprised by your final exmaple, the snake game. | 2009-02-16 | ||
19 | TYPO | after the svn co of clojure-contrib you say “cd clojure” when you need to “cd clojure-contrib” to build clojure-contrib | 2009-01-29 | ||
18 | SUGGEST | It would help to know which svn version of clojure and clojure-contrib were built and bundled with the sample code in the text. That way, if I’m used to building it I can just build the correct versions to following along with the text. | 2009-01-29 | ||
230 | TYPO | “paint-Component calls proxy-super to invoked the normal JPanel behavior, …”. Should be [invoke], not [invoked]. | 2009-01-29 | ||
230 | TYPO | “If the game is over, it displays a dialog and then resets the game.” The code indicates that these actions are performed in the opposite order. I think the order you mention in the text is more sensible, so perhaps the code should change rather than the text. | 2009-01-29 | ||
223 | TYPO | Dimension doesn’t appear in the Java imports, but it is used in ’game-panel. | 2009-01-29 | ||
22 | TYPO | The line (dosync & exprs) should be in a different colour/background colour, like (commute r update-fn & args…) | 2009-01-29 | ||
46 | TYPO | For example, you can create a person struct: | 2009-01-29 | ||
228 | SUGGEST | Just reporting a version-skew: the discussion of the Snake mutable model mentions “atoms”, which are not yet described in the section on concurrency (or anywhere else). | 2009-01-29 | ||
22 | ERROR | I question whether the hello function is truly safe for multiple threads, since the deref outside of the transaction could get a different snapshot than the commute inside the transaction. | 2009-01-29 | ||
26 | ERROR | Sample code shows correct full namespace specification for fibs, but prose says “you must say introduction/fibs”. | 2009-01-29 | ||
31 | TYPO | Did you mean to leave out the verb in “The whole language there, all the time”? | 2009-01-29 | ||
32 | SUGGEST | It’s not clear that the first cond example is Common Lisp and will actually throw an error in Clojure. | 2009-01-29 | ||
210 | OK | I would strongly recommend changing the example to something other than a database of clojure code snippets. Having clojure code contained in string literals inside code examples inline in a book is very messy, and given that this is a fairly introductory book on the language, it’s not reasonable to assume all readers will be able to quickly differentiate the snippet clojure code from the actual clojure code. How about using the same music example from earlier in the book? If not that, then just about anything else would be better than source code. | 2009-02-16 | ||
210 | OK | “(let [created_at (now)]…” and the accompanying explanatory sentence “The let calls now only once, guaranteeing that both records have the exact same created_at value” distract from the point of this chapter, not to mention introducing the confusion of “created_at” being the name of two different things. It’s not important that the two rows have the same created_at value. | 2009-02-16 | ||
134 | ERROR | I got different output for the validated message output than that in the text. I’m using clojure svn revision 1195 and clojure-contrib revision 335 which I believe matches the expected builds for b5 of the book. Here was my output: | 2009-01-29 | ||
135 | ERROR | The following also occurs on clojure r1195 and clojure-contrib r335 | 2009-01-29 | ||
135 | ERROR | agent validators changed at r1193 after that use something like: user=> (def counter (agent 0 :validator #(if (not (number? %)) (throw (IllegalStateException. “not a number”)) true))) | 2009-01-29 | ||
46 | ERROR | “Internally, the struct stores its values in indexed slots, which results in slightly faster access than a map.” Is this true? The Clojure web site talks about more efficient key storage but doesn’t mention faster access. The implementation of PersistentStructMap shows each lookup must still pull the key out of a map. It’s a shared map of keys, thus the efficient storage. The accessor function is there if you really need faster lookup. | 2009-01-29 | ||
54 | TYPO | “The greet-author-1 functions works fine” functions should be function? | 2009-01-29 | ||
23 | TYPO | The doc output for str needs to be updated to reflect the new namespace. The page shows clojure/str but the latest clojure code shows clojure.core/str. | 2009-01-29 | ||
25 | SUGGEST | The use of the repl.sh script appears only on page 25, but I did all examples before that starting the REPL as described on page 18. May be worth mentioning how to start the REPL with history support thanks to the script repl.sh on page 18. | 2009-01-29 | ||
31 | TYPO | “These features makes”, should be “make” | 2009-01-29 | ||
42 | OK | What about accentuated characters? user => (apply(interleave “Bonjour raphaël” “Ceci est le code secret”)) “BCoencjio uers tr alpeh ac�old” | 2009-01-29 | ||
239 | TYPO | “While writing the book, I used Emacs …” | 2009-01-29 | ||
210 | ERROR | As clojure.contrib.sql has changed, the current print-snippets function does not work anymore. The correct form is now: (defn print-snippets [] | 2009-01-29 | ||
53 | SUGGEST | In the explanation of | 2009-01-29 | ||
59 | SUGGEST | about “plan to use do rarely”: I’m new to clojure and lisp style programming. In other programming languages, I rarely have an if or an else branch with only one statement. Is this different in clojure? Maybe an example for people new to this style of programming? | 2009-02-16 | ||
62 | TYPO | Here is the metadata for the str var: should be | 2009-01-29 | ||
53 | SUGGEST | I think it would be helpful to show what you mean by “def and defn work by creating Vars and root bindings …” I certainly didn’t give this much thought initially. A simple example would be…. (defn foo [] (bar) (foo) (bar) And then generally indicate people should not do this. And this is what “let” and anonymous functions are for. | 2009-02-16 | ||
66 | SUGGEST | index-of-any will work with Vector or String search chars if you use (set) within the get: user=> (defn indexed [s] (map vector (iterate inc 0) s)) | 2009-01-29 | ||
88 | ERROR | The version of repl.sh that I puleed from github did not have ant.jar and ant-launcher.jar in the classpath. | 2009-01-29 | ||
148 | SUGGEST | The same code appears (except for namespace declaration) on 148 and 149 at the end of chapter 6. It is good to summarize all code snippets at chapter end, but in this case this appears reducdant. | 2009-01-29 | ||
145 | TYPO | Repetition of the word “are” in the following If the agent’s value and the sentinel are are equal, then the original function has never run. | 2009-01-29 | ||
65 | TYPO | Misspelling “langauge” in footnote at end of Exploring Clojure extract | 2009-02-16 | ||
173 | TYPO | “by create a deftarget” should be “by creating a deftarget” | 2009-01-29 | ||
172 | SUGGEST | It would be nice to know exactly which files I needed to use to “catch up” on the dependencies for lancet. I closed the REPL for the first time and didn’t have the versions that I typed still in there, and had to do a bit of digging to find which ones I needed. It wasn’t much work, but just a quickie note on which files were necessary to type the following additions to lancet would’ve been brilliant. For example, I wasn’t sure if step 3 included step 1 and 2 already or if I needed all three files. Also, whether I should use the _repl.clj or the_complete.clj versions. For anyone else, the following worked: yep no step one, and dash ‘ | 2009-02-16 | ||
180 | ERROR | The return value of the following is incorrectly nil: (sleep {:seconds 5}) Instead the return value is the task itself. | 2009-01-29 | ||
179 | ERROR | The return value of the following is incorrectly nil: The return value is actually the task itself which is also emphasized in the text. | 2009-01-29 | ||
78 | SUGGEST | I’m a complete newbie in Clojure, but I’m surprised of the code for sum-to as it seemed to me to be java-like in clojure. And indeed (I think), there’s a much more elegant approach: (reduce #(+ %1 %2) 0 (range 10)) I find it strange to have such code after having ported a java method to clojure a bit earlier, and touting the fact that it didn’t need branches or loops. | 2009-02-16 | ||
192 | TYPO | “require difference balance”-> “…different…” | 2009-01-29 | ||
192 | SUGGEST | P. 192 talks about the namespacing mechanism for keywords; and the use of keywords to designate a semantic class. P. 45 says “keywords cannot contain a period (.) or name a class.” This does not exactly contradict p. 192, but given the different meanings of the term “class” and the use of the period in namespace definitions, some explanation would come in handy. | 2009-02-16 | ||
191 | OK | It seems weird to show how you can use ::Checking as a shorthand for ::examples.multimethods.account/Checking and then use the longer version. I’d probably introduce the alias version first and then show the ::Checking version and use the ::Checking version in all subsequent examples. | 2009-02-16 | ||
19 | OK | on *nix and MacOs rlwrap is a handy library that adds history, inline-editing and much more to all kind of shells so just run: | 2009-02-16 | ||
191 | ERROR | If following along at the REPL and creating the multimethod at the REPL, the following isn’t correct: The ::Checking and ::Savings need to be ::acc/Checking and ::acc/Savings. | 2009-03-20 | ||
192 | ERROR | If following along and typing at the REPL, the following code is incorrect: (defmulti account-level :tag) There needs to be namespace qualifications on the tags, ::acc/Savings ::acc/Checking ::acc/Premium ::acc/Basic I keep bringing these differences up as the previous chapters were all done at the REPL just fine (with minor differences in namespaces for some values) with the text as printed. This section is different because you explicitly called out putting the first bit of code in a seperate file. So yes this code works as listed if it’s put in the file and :reload’d but the mixture of REPL code and code in the file make it a bit unclear. | 2009-03-20 | ||
202 | TYPO | code listing is cut off at the bottom of the page | 2009-05-27 | ||
200 | OK | instead of: wouldn’t the following also test it (building off the created functions from (define-all-ant-tasks) in the last chapter): (mkdir {:dir “foo”}) | 2009-02-16 | ||
202 | ERROR | the functions in the doto’s weren’t updated like they were in step 2 on page 126 | 2009-01-29 | ||
217 | TYPO | “functions like text-area and submit- | 2009-01-29 | ||
44 | TYPO | At the end of the page, “or nil if they key is not found” should be “or nil if the key is not found”: s/they/the/. | 2009-01-29 | ||
46 | TYPO | The code examples in Table 2.1 is not properly typeset as code. Code in Table 2.2 on the next page is slightly better, but inconsistent with the font used for code in the main text. | 2009-02-16 | ||
14 | TYPO | In the middle of the page, some of the examples of the form grammar are incorrectly typeset: (example-fn zero-or-more-arg*) In both cases, the “or” part of the argument is in brown instead of the blue used for the rest of the sample. | 2009-03-20 | ||
52 | SUGGEST | The intro to section 2.3 correctly states that “a function call is simply a list whose first element resolves The introduction of make-greeter could be the opportunity to present this feature: ((make-greeter “Hello”) "Stuart) | 2009-01-29 | ||
52 | OK | Given that we have seen how to give a name to an “anonymous” function (and that Clojure is a Lisp-1), this begs the question: what is the difference, if any, between those: (def hello-1 (fn [name] (println (str “Hello, ” name)))) Is defn just a shortcut? | 2009-01-29 | ||
21 | OK | (ref initial-state) | 2009-01-29 | ||
216 | TYPO | “Compojure converts the options map that into attributes on” shouldn’t have the “that” and thus say “Compojure converts the options map into attributes on” | 2009-01-29 | ||
15 | OK | Current version clojure from current sample zip file fails on Win XP with “Exception in thread ‘main’ java.lang.NoClassDefFoundError: jline/ConsoleRunner” zip file downloaded 1/30 0945 Eastern from PragProg website. | 2009-02-16 | ||
159 | TYPO | Paragraph just before “Shortcutting…with memoization”: | 2009-02-16 | ||
139 | TYPO | Incorrect link in the footnote on page 139 | 2009-02-16 | ||
172 | TYPO | After an example is the following text: The “As usual, … care about.” seems to make no sense here, because there is no use of underscore nearby. There is an example that uses underscore for an ignored argument in the section “Validating Agents and Handling Errors”: | 2009-02-16 | ||
172 | TYPO | Describing when compare-and-set! can be used, the third bullet point reads, “The value stored in the atom can use identity comparison, nor equality. (Generally this will imply a primitive.)” This is not clear (and may be wrong): perhaps either
It’s hard to tell if this is intended to be “or” or “not”: “not” could be better expressed as above, and “or” should not have the comma. | 2009-02-16 | ||
147 | TYPO | CONTEXT COMMENT | 2009-02-16 | ||
148 | TYPO | CONTEXT COMMENT | 2009-02-16 | ||
149 | TYPO | comp is used to compose | 2009-02-16 | ||
152 | SUGGEST | The box is “underlapping” the footer; it’s not clear if there’s hidden text. | 2009-05-27 | ||
161 | TYPO | Clojure gives you | 2009-02-16 | ||
145 | TYPO | The printer used by the REPL will, by default, print the | 2009-02-16 | ||
147 | TYPO | head is :t and tail is :h rather than head is :h and tail is :t | 2009-02-16 | ||
159 | SUGGEST | There’s a use of multi-methods and it has not been explained earlier what it is. | 2009-02-16 | ||
158 | OK | I don’t see why the lazyness solves the recursion problem. Will read it again, but might be explained more clearly maybe? | 2009-02-16 | ||
17 | OK | Please could you say “Unix” and not “*nix” everywhere? The joke wears thin after the second repetition, and the regexp does not match in any useful way. You could say something in the intro to the effect that Unix includes Linux, BSD and so on. | 2009-02-16 | ||
168 | SUGGEST | Explain this: how commes that I can’t call add-message as this: add-message(“bonjour”) add-message( :bonjour ) | 2009-02-16 | ||
42 | ERROR | “As the code above shows, doubles can lose precision, but BigDecimals cannot.” In general it is wrong to suggest that non-trivial calculations can be done without loss of precision. The area of floating point calculations is a difficult one that does not lend itself to quick summary sentences. Maybe safest to say something along the lines of “if you think additional bits of accuracy may help, you can use big doubles, but be aware that they will probably not solve your problem and will cause your program to run many orders of magnitude more slowly”. | 2009-02-16 | ||
141 | TYPO | Third paragraph, first line: “show-stoppper” should only have two ’p’s in “stoppper”. | 2009-02-16 | ||
144 | TYPO | In a couple places — starting on this page, but also in following pages — you talk about “a trillion” numbers. I think you’re short a few orders of magnitude in the code (showing billions instead of trillions): e.g. (def lots-o-fibs (take 1000000000 (lazy-cons-fibo))) 1 billion (10^9) 1 trillion (10^12) | 2009-02-16 | ||
153 | TYPO | A mutual recursion occurs when the recursion bounces between two ore more functions… | 2009-02-16 | ||
154 | TYPO | For example, you can think of oddness and evenness in terms | 2009-02-16 | ||
155 | TYPO | If the return value is a function, then the trampoline assume (should be: ‘assumes’) … | 2009-02-16 | ||
157 | TYPO | replace takes an s-list, and (guess that should be an article) oldsym, and a newsym, and replaces … | 2009-02-16 | ||
171 | TYPO | This sentence doesn’t make sense as written: “If you player set to random play, maybe you listen to several tracks in a | 2009-02-16 | ||
26 | TYPO | “Because Clojure objects are Java objects, you can also show any Clojure to see its underlying Java API.” should read something like “Because Clojure objects are Java objects, you can also show any Clojure object to see its underlying Java API.” | 2009-02-16 | ||
65 | SUGGEST | You say “and see that Clojure enforces the :type tag”, when :type has not been mentioned before, although :tag has several times. If :type was intended with the colon, could you explain it a bit more? | 2009-02-16 | ||
91 | TYPO | Last paragraph : Where interop is concenred … should be When interop is concerned .. | 2009-02-16 | ||
140 | TYPO | “Line 6 defines an anonymous function”… not really, you gave it a name: fib. | 2009-02-16 | ||
192 | OK | In the step_3_repl.clj code snippet, maybe (function) should be (apply function args) | 2009-02-16 | ||
22 | SUGGEST | The sentence “Sets are functions of their keys” comes across a bit odd. Sets don’t have keys but rather elements. Maybe instead something along the lines of “A Clojure set can itself serve as a function, returning its argument when that is a member of the set or nil otherwise.” | 2009-02-16 | ||
23 | ERROR | My previous erratum report on this issue seems to have been rejected due to my inclusion of a URI (Your system only warns after submission that they aren’t allowed…). The REFER form at the bottom of this page fails due to a conflict with the user-defined HELLO function: (The other errata listed for this page (books.pragprog.com/titles/shcloj/errata/add?pdf_page=23) seem to be out of sync with the current PDF version. They refer to content on other pages.) | 2009-02-16 | ||
187 | TYPO | In the first sentence, “use input”, should be “user input”. | 2009-02-16 | ||
267 | ERROR | Section 9.4 (Farewell) mentions GUI development as does the first list on page 248 at the beginning of chapter 9, but the chapter does not contain anything about building a GUI with clojure. | 2009-02-16 | ||
31 | SUGGEST | I recognize that there is some disagreement here, but I believe that the consensus is that parameters are names and arguments are values associated with these names when a function is invoked. Thus, “For example, function | 2009-02-16 | ||
34 | TYPO | “thread safety” is inconsistently hyphenated: This guarantees thread safety, and it is easier to use than Java | 2009-02-16 | ||
91 | TYPO | “first time cthe class is loaded.” —> “time the class” | 2009-02-16 | ||
127 | OK | I think it would be useful to discuss some of these functions in relation to the ones that have already been introduced. It seems strange to introduce select here with no mention of filter - a quick contrast would be helpful | 2009-02-16 | ||
171 | TYPO | “atoms do no participate in transactions” should be “do not” | 2009-02-16 | ||
171 | TYPO | “IF you need coordinated access” should be mixed case | 2009-02-16 | ||
172 | SUGGEST | “This rules out swap!, which has side effects” The meaning of this is not clear to me, nor is the contrast with reset!. Above text says not to put side effects in your swap! fn (that makes sense), and now this says swap! has side effects. How is that different than “blindly updating” which reset! does? | 2009-02-16 | ||
175 | SUGGEST | “Transactions cannot have side effects” That’s a little strong. They should not have side effects, but the language doesn’t prevent you from putting them in the transaction. | 2009-02-16 | ||
192 | TYPO | “It is perfectly fine ot use” should be “to” | 2009-02-16 | ||
192 | TYPO | “This function will There is no agent in the example. | 2009-02-16 | ||
225 | SUGGEST | Would it be worth calling resolve instead of ns-resolve in order to see if the name is already def’ed in either clojure.core or the current namespace? | 2009-02-16 | ||
164 | TYPO | Java Concurrency in Practive | 2009-02-16 | ||
157 | TYPO | The result: (replace ’((a b) (((b g r) (f r)) c (d e)) b) ’b ’a) has an extra ‘)’ at the end it should be: (replace ’((a b) (((b g r) (f r)) c (d e)) b) ’b ’a) | 2009-02-16 | ||
169 | OK | “You cannot use commute to update the counter..” This passage could use some clarification - I found myself rereading it several times to understand the meaning you intended | 2009-02-16 | ||
160 | OK | I get an StackOverflowError when using the memoized versions of m and f: user=> (time (m 250)) This is using the sample code and launch script from git. I assume your JVM has been launched with more memory than mine, however, elsewhere in the book it’s always blown stack and memory at the same time. | 2009-02-16 | ||
88 | ERROR | the git version of the samples didn’t have a “classes” directory so running “bin/tasklist.sh snippets/example-build.xml” couldn’t find the class. And, typing the following in the REPL “(compile ’examples.tasklist)” wouldn’t work until I added a “classes” folder. After adding the “classes” folder and compiling the examples.tasklist code, then calling “bin/tasklist.sh snippets/example-build.xml” worked from the command line. | 2009-02-16 | ||
184 | SUGGEST | I didn’t feel this was particularly clear: ‘The {:keys [body dir]} | 2009-02-16 | ||
172 | SUGGEST | I don’t see how “As usual, the _ indicates an argument that | 2009-02-16 | ||
43 | SUGGEST | The discussion of character literals includes \ | 2009-02-16 | ||
43 | SUGGEST | After showing how to uppercase a string there is no example to uppercase a character. The reader may be surprised to discover that .toUpperCase doesn’t magically work on characters too. Instead, Character/toUpperCase is required. | 2009-02-16 | ||
122 | ERROR | The end of section 4.4 mentions that the lazy XML and zip-xml support will be described in Chapter 9, but Chapter 9 doesn’t seem to mention these at all. | 2009-02-16 | ||
171 | TYPO | For example, you can set current-track to “Credo”: Make the case consistent on Credo | 2009-02-16 | ||
46 | SUGGEST | It is never explicitly stated that keyword names start with a colon character. This fact is presumably clear from the examples, but it should be mentioned directly. | 2009-02-16 | ||
48 | OK | Section 2.2 states: While it is true that ’ was used in the introduction to require/refer/use it was never explicitly discussed. Perhaps the reader happily copied the examples given. But it is likely that the reader has forgotten about any exposure to ’ by this point in the book. | 2009-02-16 | ||
48 | SUGGEST | The Regex Pattern example in Figure 2.2 really looks as though it uses single-quotes, which is of course a syntax error. The examples in section 4.4 have a much clearer font. But it doesn’t appear that the required syntax is explicitly described anywhere. | 2009-03-27 | ||
48 | OK | The discussion of Regex Pattern syntax should also distinguish between Clojure syntax and the Java strings required to designate Java Patterns, e.g., the awkwardness of “\\\\W+” in Java vs. the more streamlined #“\\W+” in Clojure. | 2009-02-16 | ||
31 | TYPO | Closing paren with no matching opening paren. In the first bullet under the ‘Lisp, with Fewer Parentheses’ section, the sentence, “For example, function | 2009-02-16 | ||
40 | TYPO | The sentence, “Create a vector of the numbers 1,2, and 3:” is likely missing a space between the “1,” and the “2,”. | 2009-02-16 | ||
54 | TYPO | The word “var” is displayed in inconsistent fonts. “… the following def creates a var …” displays “var” in a sans serif font highlighting it as though it were a keyword or something. This same font is used later in reference to the “var” special form. However, other references to “var” as a noun use the regular font. | 2009-02-16 | ||
54 | OK | Inconsistent use of the terms “bound”, “binding”. At the beginning of section 2.4 we have “The symbol user/foo refers to a var which is bound to the value 10.” Under the next subsection “Bindings” we have “Vars are bound to names, but there are other kinds of bindings as well.” The Common Lisp standard defines a binding as “an association between a name and that which the name denotes”. This is the second sense used in the book. The first sense of a “binding” between a var and its value is inconsistent. | 2009-02-16 | ||
56 | SUGGEST | Discussion of greet-author-2 function: “…bind first-name to the first-name of the function parameter.” | 2009-02-16 | ||
57 | OK | The example function “ellipsize” demonstrates destructuring where one doesn’t care about other elements beyond the first 3. It would be helpful to show an example to capture all remaining elements, e.g., “[[w1 w2 w3 & others] (re-split …”. This technique is not readily discovered from the Clojure site. I found it via Google Groups. Also, maybe an example destructuring a string: [[c1 c2 c3 c4] “pung”] | 2009-02-16 | ||
57 | TYPO | This is a silly erratum, but the sentence “The quick brown fox jumped over the lazy dog.” should contain the word “jumps” rather than “jumped”. The whole point of the sentence is to exercise every letter of the alphabet. As is, the letter “s” is missing. | 2009-02-16 | ||
151 | TYPO | Line 4 after “Tail recursion”: | 2009-02-27 | ||
163 | TYPO | (def add-3 ((curry ) 3) should be (def add-3 ((faux-curry) 3), for “curry” is not defined. | 2009-02-27 | ||
189 | TYPO | “Clojure’s finaly concurrency API” should be finally. | 2009-02-27 | ||
190 | SUGGEST | The use of “pure” in the update mechanism table is confusing because I’m not sure if you mean pure in the same way that the FP chapter talks about pure. We’re supposed to use pure functions to update Refs, but impure functions are ok for Agents. | 2009-02-27 | ||
8 | SUGGEST | The signature is the only thing that wraps to the next page on the forward. Looks odd. | 2009-03-20 | ||
199 | OK | The code sample (defn head-overlaps-body? [{[head & body] :body}] I get this for (doc includes?): I’ve got the December 16, 2008 version of seq_utils.clj. Someone let me know if there’s a new, different version. | 2009-02-27 | ||
284 | TYPO | Godel is misspelled as Gaudel. | 2009-02-27 | ||
71 | TYPO | Do you mean to have set literals #{} instead of map literals here? (index-of-any {\\z \\a} “zzabyycdxx”) | 2009-02-27 | ||
22 | SUGGEST | The bullet point that begins “Redefine private to mean” refers to redefining “private”, but the example fragment of a class definition above it doesn’t mention “private”. Perhaps there should be agreement since the current topic is “so many words in Java are prescribed by the language def”. | 2009-02-27 | ||
96 | TYPO | Uncoordinated is spelled “Uncoodinated” | 2009-02-27 | ||
167 | TYPO | At the bottom of the page, it should read: (rem (trampoline trampoline-fibo 1000000) 1000) in place of: (rem (trampoline tail-fibo 1000000) 1000) PS Paul | 2009-02-27 | ||
223 | TYPO | The example in the last entry in Figure 7.2 doesn’t make sense to me and has a trailing ‘)’. It currently reads: same as “wrapping evaluation”). | 2009-03-20 | ||
284 | TYPO | “Gödel” comes through in the bibliography as “GÃüdel” (upper-G, upper-A-with-tilde, lower-u with superimposed double-quotes or double-prime mark…) | 2009-02-27 | ||
64 | TYPO | “If you do not want to use a fully-qualified classname, you can map one | 2009-02-27 | ||
64 | TYPO | " If you want to use a Clojure var from | 2009-02-27 | ||
65 | TYPO | “The simple for m of use above causes the current namespace to refer to | 2009-02-27 | ||
65 | TYPO | Some inconsistency in coloration of REPL samples. E.g., “(round 1.2)” is blue rather than brown. | 2009-05-27 | ||
65 | SUGGEST | Just checking—the illustration of the “ns” macro should stand “as is”? In particular, the :use clause should specifically not include clojure.contrib.math. Otherwise this would obviate the preceding example of mapping the “round” function into current namespace? 3 other related suggestions: | 2009-02-27 | ||
66 | OK | Back on topic…it would be helpful to throw in an example of “if-not” (not even mentioned in the book). Also, considering how short section 2.5 is, it would be nice to cover “cond” as well. I think people w/o prior Lisp experience might have trouble with “cond”. | 2009-02-27 | ||
66 | OK | It seems typical in Lisp books during the discussion of “if” to point out how it could not possibly be implemented as a function, thereby highlighting the difference between special forms and functions. | 2009-02-27 | ||
34 | TYPO | ‘if’ in the ‘hello’ method description in the code sample is highlighted in red | 2009-05-27 | ||
170 | TYPO | transactions should be singular in the following sentence fragement: “Where multiple ref | 2009-02-27 | ||
22 | SUGGEST | It might be fun in the “Why Lisp?” section to add a quick note explaining why there is no precedence/associativity table in the book as many programmers from other languages may expect to find. Fully-parenthesized expressions eliminate the ambiguity. | 2009-02-27 | ||
69 | SUGGEST | In an ideal world, the title for section 2.6 would read “Where’s My for Loop?”. | 2009-02-27 | ||
69 | SUGGEST | I realize that you are merely comparing Java and Clojure implementations of the indexOfAny() method and not out to slam the Apache code. However, it is germane to the complexity and potential for errors in the Java code to note two coding errors: On the other hand, you don’t discuss performance here. At the very least, the Clojure version requires more memory due to the ephemeral sequence created by the “indexed” function. | 2009-02-27 | ||
000 | OK | I suggest you mention clojure.lang.Script. The REPL is good, and can load files, but simple non-interactive execution is important too, and this option not mentioned in the book. | 2009-02-27 | ||
181 | TYPO | “During Transation A” -> “During Transaction A” | 2009-02-27 | ||
183 | SUGGEST | In the validate-message-list function at the bottom of the page, I think it would be better to use “when” instead of “if”. I don’t think there’s a reason to return true when validation passes. | 2009-03-20 | ||
188 | SUGGEST | Consider changing the name of the file used for backup of chat messages to have an extension of .txt instead of .clj since .clj files typically contain Clojure source code. | 2009-02-27 | ||
189 | TYPO | errata to a previous errata - “finaly” should be “final”, not “finally” | 2009-02-27 | ||
24 | OK | 5th para (4th li) | 2009-02-27 | ||
95 | OK | tasklist.clj ‘duck-streams’ should be ‘duck_streams’ with and under score | 2009-02-27 | ||
100 | OK | (use ’[clojure.contrib.duck-streams :only (spit)]) should be: (use ’[clojure.contrib.duck_streams :only (spit)]) with an under score instead of a dash. | 2009-02-27 | ||
47 | TYPO | In the bullet list of things a symbol might name, the Java class “java.lang.Ransom” is included. I’m guessing that Random is the class that was intended. | 2009-02-27 | ||
47 | TYPO | In the paragraph immediately following the bullet list, Clojure should “support” not “supprt” | 2009-02-27 | ||
183 | SUGGEST | Let me take back my previous comment about this page. I just learned that validator functions don’t have to throw an exception. They can just return a boolean value. That means the example on this page doesn’t need to throw an exception You can get rid of the if and use every? instead of not-every?. That will be much simpler! | 2009-03-20 | ||
178 | TYPO | you can tell that calls-slow-double is slow because is does the same work over and over again. in the third paragraph should be you can tell that calls-slow-double is slow because it does the same work over and over again | 2009-02-27 | ||
178 | TYPO | Sixth paragraph, last sentence refers to the function calls-slow-binding, but the function should be called calls-slow-double. | 2009-02-27 | ||
76 | SUGGEST | Figure 2.4 describes the :arglists metadata key as “list of argument names used by doc”. As I argued before, I believe this should be “parameter names”. Moreover, the value of :arglists is really a list of vectors indicating the different arities and parameter names that the function will accept. | 2009-02-27 | ||
47 | TYPO | java.util.Ransom should be java.util.Random | 2009-02-27 | ||
74 | SUGGEST | “Most of the metadata keys on a var are added automatically…” Wouldn’t it be simpler (and more accurate since keys can’t be added w/o values) to say: “Most of the metadata on a var is added automatically…” | 2009-03-20 | ||
74 | OK | The syntax box for the metadata reader macro makes it look as though there are two components: #^metadata form Instead, maybe “#^metadata-form”? The same holds true for Figure 2.2. | 2009-02-27 | ||
74 | SUGGEST | Multiline REPL output is colored inconsistently. | 2009-05-27 | ||
74 | OK | The metadata for the “shout” function contains“:tag java.lang.String”, which presumably refers to the result type? There doesn’t seem to be any indication of the expected argument type in this metadata (:arglists doesn’t preserve it). The example at the bottom of the page then demonstrates that “shout” must take a String argument. However, the metadata doesn’t inform us of this fact? | 2009-02-27 | ||
75 | ERROR | You state that function metadata can be placed at the end of body: 1. You don’t explain why you’ve switched to the alternative “defn” form. In particular, you don’t mention why this doesn’t work: | 2009-02-27 | ||
75 | SUGGEST | The final paragraphs of the Reader Metadata section are a nice touch—clarifying distinction between #^ and “with-meta”. Stuff that I probably wouldn’t have straightened out until a second or third reading otherwise. | 2009-02-27 | ||
88 | OK | The function unchecked-sum-to doesn’t work due to java.lang.UnsupportedOperationException: Can only recur from tail position. | 2009-02-27 | ||
54 | OK | The syntax box for “defn”: However, you defer discussion of “attr-map?” until section 2.7, but there are no examples of that part of the “defn” syntax there. | 2009-03-20 | ||
78 | TYPO | “… makes it easy to cleanup resources using the with-open idiom.” | 2009-03-20 | ||
55 | OK | On your PCL blog (ch. 5) you show an interesting alternative to support optional arguments rather than defining multiple arities: | 2009-03-20 | ||
82 | OK | You mention int-array, etc. for the creation of arrays of primitives. But for whatever reason, Clojure does not provide byte-array, char-array, boolean-array. Maybe a note showing how to create these via make-array: | 2009-03-20 | ||
82 | OK | The syntax boxes for “make-array”, “aset”, “aget” clearly show that they support multi-dimensional arrays. Perhaps you should point out in the subsequent discussion of “to-array”, “into-array”, “amap”, “areduce” that they really only work with single-dimensional arrays, e.g., (aget (into-array [[1 2 3] [4 5 6]]) 0 0) doesn’t work. Of course, Java doesn’t really have multi-dimensional arrays anyway… | 2009-03-20 | ||
84 | OK | In the discussion of “amap” this is a little unclear: “expr” must specifically call (aget a idx) to produce a value based on that array element. Indeed, we can do silly things like this otherwise: | 2009-03-20 | ||
85 | OK | It’s probably obvious (dangerous words!), but just in case it isn’t you might want to highlight how in “memfn” toUpperCase loses its initial “.”, whereas in the anonymous function version the dot is necessary: | 2009-03-20 | ||
85 | SUGGEST | Pages 83 and 85 both contain discussion of Java’s String.format/Clojure’s format. Should these be consolidated? I can see an argument for keeping things as is—each section has a different emphasis. So there is duplication but perhaps not unnecessary duplication. | 2009-03-20 | ||
80 | OK | Neither the explicit constructor nor the syntactic sugar seem to support Java generics? | 2009-03-20 | ||
88 | OK | In the discussion of the function integer-sum-to you don’t mention why it is necessary to use “let” to rebind the parameter’s value as an int. Why not use metadata as in ch. 2 to declare the type of the parameter: | 2009-03-20 | ||
88 | TYPO | “Clojure’s convenient math operators (+, I think you mean “results” rather than “arguments” here. | 2009-03-20 | ||
88 | OK | In unchecked-sum-to, should you use an unchecked-add rather than “inc”? | 2009-03-20 | ||
88 | OK | Whoops…in my previous comment about unchecked-sum-to, simply changing (inc i) to (unchecked-add i (int 1)) actually slows it down! This seems slightly faster than unchecked-sum-to: | 2009-03-20 | ||
92 | TYPO | “… event driven APIs such as Swing or some XML parsers.” =>“event-driven” | 2009-03-20 | ||
98 | TYPO | “The tasklist class is plain old Java class, consisting of constructors, Missing “a”: “a plain old Java class” | 2009-03-20 | ||
156 | TYPO | Fourth line: “correctly choosingfibo over other aproaches”, there should be a space between “choosing” and “fibo” and approaches is spelled with 2 “p”s | 2009-03-20 | ||
263 | TYPO | index-of-any is defined twice in the code example, once without a :test and once with. | 2009-03-20 | ||
94 | OK | At the top of the page you present 3 anonymous functions using the shortcut #(…) notation. Then in the thread example you switch back to the “fn” notation. Maybe I’m not sufficiently used to the shortcut notation yet, but this is kind of disorienting. (I’m very comfortable with the “fn” notation from using Common Lisp’s LAMBDA.) | 2009-03-20 | ||
95 | OK | When discussing tasklist.clj is it worth pointing out the difference between calling gen-class directly vs. from within the “ns” macro (i.e., :gen-class)? Specifically, no :name clause is needed when in “ns”—it’s inferred from the namespace name. Also, is it worth mentioning how the generated class (reader.tasklist) violates the normal Java naming convention for class names (initial capital)? Is this class not really for human consumption? Or just for use from within Clojure? Would Java programmers be confused to encounter such a class name? | 2009-03-20 | ||
95 | SUGGEST | “Add a -main function to reader.tasklist that prints Should be “prints the task list”? (i.e., regular English rather than the function name defined on the next page) | 2009-03-20 | ||
77 | OK | It might make sense to reinforce the word “interoperability” at the start of chapter 3. As it stands, the word is only used once in the entire book. I’m sure readers can figure out what “interop” means but it is kind of slangy. This would be the spot to clarify the meaning. | 2009-03-20 | ||
95 | SUGGEST | On this page you refer to a “state structure” identified as “state” by the :state clause in the “ns” macro. On the next page you claim: “The state method is named state because that is what we requested in :gen-class.” Is this inconsistent? structure vs. method | 2009-03-20 | ||
175 | OK | great book! on the memoization using lazy seq: def m-seq (map m … I assume that this m is different than the m on p 173, and the m on p 174, but not clear. I.e. something like (defn m [n] | 2009-03-20 | ||
191 | TYPO | 2nd para under The Unified … | 2009-03-20 | ||
209 | TYPO | Macros first para end | 2009-03-20 | ||
209 | TYPO | Sorry - leave as “feature”. Or perhaps “a new feature” as opposed to “your own new feature”. I had no specific feature in mind when I read this sentence so it felt wrong. | 2009-03-20 | ||
96 | TYPO | “Next, implement the a handler for the init method.” Extraneous “the” here. | 2009-03-20 | ||
70 | OK | I was reading through your book “Programming Clojure” the other day and on page 70 I found this code fragment (defn index-filter [pred coll] Is the (when pred .. ) really required there? I am no expert on Clojure (hence I didn’t log a bug on the prag prg site) but it seems to me that the “when pred” is repeated twice in the function, once at the beginning of the function and once in the list comprehension. I tried a few simple examples at the repl and the variant witout the initial (when pred) seemed to work. iow, this (defn index-filter [pred coll] seemed to work for the simple examples I tried. Of course I could be missing some deep Clojure magic (as I said, I am no expert and am extrapolating off my scheme and python knowledge to guess how the function works). In which case, I apologize for wasting your time, but maybe in the next version of the book you could add a sentence explaining why the (when pred) idea needs to be repeated twice in the code fragment. Great book btw! | 2009-03-20 | ||
95 | OK | In the :import section of the “ns” macro on this page you switch without explanation from the list-style imports on pages 64, 74, 92 to a using vectors. This has nothing to do with using “ns” vs. using “import” directly? Perhaps the only real difference is that “import” is a function while “ns” is not. Therefore, the lists/vectors in “import” would typically be quoted to prevent evaluation. Unless you did something like this: | 2009-03-20 | ||
69 | SUGGEST | … Apache Commons project, which is respected for quality…. I believe that you have no intent of sarcasm but the ‘respected for quality’ flies in the face of the example and made me wonder a bit. By dropping the ‘respected for quality’ adjective, the facts will stand by themselves and the chosen example is otherwise a fine item for improvement. Thanks for the book. | 2009-03-20 | ||
33 | TYPO | Excerpt: Use dosync to add a visitor within a transaction: “stu” here should be “Stu”. A few lines below visitors is derefed to show #{“Stu”}. Cheers, | 2009-03-20 | ||
95 | ERROR | The example tasklist program included with the book code does not function as shown at the top of this page. In fact, there is nothing in the “classes” directory, so the bin/tasklist.sh script fails. If the reader follows along with the text and creates his own reader.tasklist, then this runs fine. However, since Clojure uses a 1-pass compilation, the definition of the task-list function must be located before where it is referenced in -main. This is different from the order of presentation in the text. | 2009-03-20 | ||
98 | TYPO | “You will need to have your classes on the classpath, plus clo- Should be clojure-contrib.jar | 2009-03-20 | ||
111 | TYPO | “…implementation details of Lisp on original IBM 704 platform.” Should be “the original” | 2009-03-20 | ||
103 | TYPO | The latest version of Clojure in the book’s code bundle prints methods differently than shown in the book: is now: (Obviously disregarding the ellipsis.) | 2009-03-20 | ||
35 | TYPO | The line “The book samples all unit tested” should be something like “The book samples are all unit tested”. | 2009-03-20 | ||
55 | OK | It would be great if there were a small section about output , especially formatted output, in the book. Input/Output should ideall be dealt with early in the book. | 2009-03-20 | ||
117 | OK | (apply str (interpose \\, [“apples” “bananas” “grapes”])) Rather than a comma char, maybe the string “, ” to follow normal English convention following a comma with a single space. | 2009-03-20 | ||
118 | SUGGEST | “For each collection type in Clojure, there is a function that converts a This is awkward to handle. Converting a list of arguments—the first thing that came to mind was something like this: (vector ’(1 2 3 4)) Your syntax diagrams make it clear, but maybe you should say something like “… a function that takes an arbitrary number of elements and creates a collection of the appropriate type containing those elements.” | 2009-03-20 | ||
118 | TYPO | “vector also has a cousin, vec, that takes a single collection argument “varible” -> “variable” | 2009-03-20 | ||
119 | SUGGEST | It’s curious how whitespace is not needed to separate the tokens here: #{\\a\\e\\i\\o\\u} Also, I’m nitpicking here, but f(x) doesn’t designate a function. It identifies the image of x under f, an element of the range of f: | 2009-03-20 | ||
119 | SUGGEST | It seems a bit of a stretch to connect split-at to take-while and drop-while. There isn’t anything going on “while” some predicate is true. It simply splits the collection at a specified point. Maybe you should introduce it after split-with (which still should be tied to take/drop). | 2009-03-20 | ||
120 | OK | " some returns the actual value of the first match instead of true." I’m being picky here, but “some” returns the first non-false value returned by its predicate: | 2009-03-20 | ||
121 | SUGGEST | You should probably point out that “map” can work with multiple sequences in parallel: | 2009-03-20 | ||
49 | ERROR | I suspect as a result of the change to lazyness in Clojure, the results of some example code is not as per the text any more. user=> (interleave “Attack at midnight” “The purple elephant chortled”) | 2009-03-20 | ||
206 | TYPO | About half way down the page where it says “(line 3remembers” | 2009-03-20 | ||
94 | TYPO | “For one-off tasks likes XML and thread callbacks…” Should be “like” (singular). | 2009-03-20 | ||
121 | TYPO | In the explanation of list comprehensions you mention “predicates on the elements” and then “an output function that produces output from the elements of the input lists that satisfy the predicate”. In the second phrase, perhaps “the predicate” -> “these predicates” | 2009-03-20 | ||
122 | SUGGEST | You don’t discuss the :while test in a list comprehension (anywhere in the book apparently): | 2009-03-20 | ||
263 | TYPO | The first two assertions in the :test metadata for index-of-any are identical: | 2009-03-20 | ||
122 | OK | You might make a reference in the list comprehension discussion back to your function index-filter in section 2.6 to demonstrate the destructuring that ‘for’ can do. | 2009-03-20 | ||
64 | TYPO | Top of the page the word namespace is hyphenated as names- Cheers, | 2009-03-31 | ||
140 | ERROR | (set-property! echo-task “message” “a new message!”) should be (set-property! echo-task :message “a new message”). We used “name” in property-descriptor in order to be able to use keyword property names | 2009-03-20 | ||
121 | SUGGEST | You point out the connection between list comprehensions and set theory. It would be useful to give a concrete example of the different syntax. For example, your even natural numbers example: | 2009-03-20 | ||
125 | SUGGEST | (cons 72 (.getBytes “ello”)) Would this be clearer? | 2009-03-20 | ||
127 | SUGGEST | It would be useful to discuss the ‘sort’ function a bit further here. For example, how do you sort in descending order, case-insensitive sort, etc…? You only have examples of ‘sort’ using the default comparator (ascending) in the book. The documentation at clojure.org is not helpful either. | 2009-03-20 | ||
141 | OK | " After more than a decade dominated by object-oriented pro- To reinforce your earlier reference perhaps this should read: “… dominated by the nouns of object-oriented programming…” | 2009-03-20 | ||
129 | SUGGEST | In the clojure-loc auxiliary functions ‘non-svn?’ and ‘clojure-source?’ wouldn’t it be preferable to use .getName as you did earlier rather than .toString? In principle this could generate a shorter string on which to search for the filename extension. | 2009-03-20 | ||
129 | OK | I’m overdoing it here, but clojure-loc would be more accurate if it didn’t count comment lines. Also, placing the ‘non-svn?’ test first in the list comprehension should be more efficient since we’re testing the front of the string (maybe that depends on the relative number of “.svn” and “.clj” files…): (defn clojure-loc [base-file] | 2009-03-20 | ||
129 | ERROR | The function ‘non-svn?’ does not work as intended. First, by using .toString rather than .getName on File objects there will likely be path information in front of the “.svn” directory name, so trying to test with .startsWith will fail. Furthermore, even if .getName were used, the only File’s returned by file-seq that would match would be the “.svn” directories themselves. These directories would be weeded out, but their contents would not. It appears that all the SVN files at issue end in “.svn-work” or “.svn-base”. However, the “clojure-source?” function would eliminate these file anyway. Consequently, “non-svn?” appears to be irrelevant. | 2009-03-20 | ||
130 | OK | It might be helpful to emphasize how xml-seq performs a depth-first traversal of the XML tree with literal content (strings) or empty elements as leaves. | 2009-03-20 | ||
131 | SUGGEST | You don’t have a separate “Functions on Vectors” section, so it would be helpful to note here that ‘peek’ does not behave like ‘first’ for vectors. Rather, it behaves like ‘last’. | 2009-03-20 | ||
131 | OK | The Clojure community has adopted a confusing convention of using the question mark as both a tag in predicate names (even?, zero?) and as a meta-character as in regular expressions (0 or 1 instances). Consequently, the following syntax diagram is difficult to read: | 2009-03-20 | ||
135 | OK | Considering that strings are sequences in Clojure, is there a reason to do: | 2009-03-20 | ||
134 | OK | The whole “Function on Sets” section is nicely done. You have 2 good examples (languages/beverages and composers/compositions) which are instructive and interesting. The section discussing relational algebra uses the concrete example particularly well to illustrate a potentially abstract topic. | 2009-03-20 | ||
140 | SUGGEST | “Line 3 lets a property-descriptor…” Lets it do what? :) Maybe clearer: “Line 3 creates a local variable pd in which to store a property-descriptor…” | 2009-03-20 | ||
140 | SUGGEST | “Clojure functions that deal with side ef fects are often prefixed with do…” Is it right to say this considering that all but dorun/doall are macros rather than functions? | 2009-03-20 | ||
142 | OK | At the REPL you advocate restrictive ‘use’ forms to minimize namespace collisions: I believe this is the equivalent inside ‘ns’: | 2009-03-20 | ||
141 | OK | You might mention when redefining instantiate-task that the newly-defined auxiliary functions must be placed before it in the source file (or ’declare’d). This is how you organize the source listing on page 142. But without you highlighting this issue it would be confusing for the user to encounter compiler errors if they simply appended set-property!, etc… at the bottom of their work from the previous chapter. | 2009-03-20 | ||
147 | ERROR | " There is only one scope: the function’s argument list. " Fortunately this is not completely true. Any nested function definition (let/letfn) can take advantage of variables in their enclosing scope. This is what makes closures interesting. I don’t think closures are inherently “impure”. | 2009-03-20 | ||
219 | TYPO | “Begin the macro body with a syntax unquote (‘) to treat the entire thing as a template” I think this paragraph should say “syntax quote”, rather than “syntax unquote”? | 2009-03-20 | ||
151 | OK | You explain how stack-consuming-fibo is impractical due to its consumption of stack frames. You might also mention how inefficient it is due to redundant computation. For instance, computing F4 results in F1 being computed 3 times and F0 and F2 twice each. | 2009-03-20 | ||
155 | TYPO | By working pairwise, it then calculates the Fibonaccis by carring along just “carrying” | 2009-03-20 | ||
63 | SUGGEST | I think a good and complete explanation of destructuring belongs in this book, rather than pointing to an online reference, for three reasons: 1. You can do a good job of explaining it. | 2009-03-31 | ||
151 | SUGGEST | I recommend using the new ‘letfn’ for the local function in tail-fibo. Also, “Structure and Interpretation of Computer Programs” (2e pg. 39) has a slightly more streamlined version of this Fibonacci implementation. In Clojure, with your naming conventions: | 2009-03-20 | ||
153 | SUGGEST | “The only difference between tail-fibo and recur-fibo is on line 7, where Another minor difference is that the local function is actually anonymous here. Apparently ‘recur’ doesn’t need a name to know where to loop. | 2009-03-20 | ||
153 | SUGGEST | Wow! It would really be helpful to include a note highlighting why this works: You mention on pages 34 and 51 how sets and maps can be accessed as though they were functions by their elements/keys. I don’t recall you pointing out that vectors can be similarly indexed. | 2009-03-20 | ||
183 | ERROR | The def of messages with the :validator… (def messages (ref () :validator validate-message-list)) …gives me an error… java.lang.IllegalArgumentException: Wrong number of args passed to: core$ref (NO_SOURCE_FILE:34) In my REPL. | 2009-03-31 | ||
186 | ERROR | Similar to page 183 a call to gives an error: java.lang.IllegalArgumentException: Wrong number of args passed to: core$agent (NO_SOURCE_FILE:33) I believe I’m using the latest version of clojure, but I’m not sure how to determine that. | 2009-03-31 | ||
48 | SUGGEST | It would be best to avoid automatic hyphenation in literals, like “formfeed” (or is it “form-feed”?) | 2009-03-31 | ||
50 | SUGGEST | Are the predicates also listed in a reference section of this book? If so, it would be good to reference that section here. Online documentation is nice, even essential these days, but books have advantages too, especially while you’re reading a hardcopy of said book away from a computer. | 2009-03-31 | ||
158 | SUGGEST | “… if you accidentally hold the head (first item) of a sequence.” | 2009-03-31 | ||
158 | SUGGEST | “This is a very pretty definition, | 2009-03-31 | ||
159 | SUGGEST | You might remind the reader why in count-heads-pairs you are using the less perspicuous variable ‘cnt’ rather than ‘count’. You explain the issue of shadowing clearly on pg. 38. However, on pg. 153 you use ‘count’ as a local variable in fibo-series. Maybe that should be ‘cnt’ too. :) | 2009-03-31 | ||
159 | SUGGEST | In count-heads-pairs, the following test: | 2009-03-31 | ||
160 | SUGGEST | Is there some reason why by-pairs can’t be defined thus? | 2009-03-31 | ||
161 | SUGGEST | This may be too terse for illustrative purposes: :-) | 2009-03-31 | ||
163 | SUGGEST | For people new to functional programming it’s helpful to explain the origin of the term “curry”. If they don’t know who Haskell Curry was they get confused about spicy Indian food. | 2009-03-31 | ||
15 | TYPO | “…how Clojure idioms differe from languages…” | 2009-03-27 | ||
54 | TYPO | Figure 2.2 - the table of Reader Macros - is too wide for the page. The column entitled “Primary Coverage” extends out to the right past the margin and out of the page. | 2009-04-29 | ||
83 | SUGGEST | The discussion of Clojure’s format is repeated on page 84. It probably only needs to be mentioned once and the section on Convenience Functions seems like a better place than here. | 2009-03-31 | ||
166 | SUGGEST | “Clojure’s implementation uses a bitwise and to implement The word ‘and’ should be displayed in a different font (as odd? and even?) are to indicate mention rather than use here. | 2009-04-03 | ||
171 | TYPO | “I could not resist the temptation ways-> way | 2009-03-31 | ||
168 | SUGGEST | After defining trampoline-fibo, it would be useful to explicitly highlight the correspondence between the shorthand notation: You might also want to contrast this kind of closure (a function, ‘fib’, captured and called from outside of its defining scope) with the more common kind you discuss on pg. 58 (make-greeter creates a closure over a regular ‘data’ variable). | 2009-03-31 | ||
168 | TYPO | " For self recursions like trampoline-fibo, trampo- self-recursions | 2009-03-31 | ||
169 | SUGGEST | " If not, you will be happy to have trampoline in your bag of tools. " Don’t people usually carry tools in boxes and tricks in bags? :-) | 2009-03-31 | ||
170 | SUGGEST | “… containing a single ’bottom element” Don’t really need to quote those symbols in the text (especially since you’ve used a different font). Looks kind of odd… | 2009-03-31 | ||
171 | SUGGEST | When I first looked at Wallingford’s replace-symbol code I thought “This is overly complex. This function implements Common Lisp’s SUBST function. I’ve written it myself as an exercise using a single function. There’s no need for two.” However, after reading Wallingford’s paper and seeing his rationale I realize that his version is actually quite elegant—following the BNF for the s-list datatype. You’ve chosen a nice example here for which a lazy sequence provides a clear solution. The link to Wallingford’s paper is very useful too. However, there are 3 issues: | 2009-03-31 | ||
160 | SUGGEST | Why does take-pair bother supplying a name if (fn take-pair [c] … when take-pair does not call itself recursively? | 2009-03-31 | ||
164 | TYPO | I don’t see why faux-curry is faux at all based on the wikipedia article on currying. Looking at that, it is not clear what the behavior of curry should be when applied to functions of arity less than 2. The way faux-curry behaves seems as reasonable a generalization as any, mathematically. If there is a reference on currying that can be footnoted here, that woud be nice. | 2009-03-31 | ||
175 | TYPO | “Operations that are logically independent are easier to implement This is true, but it isn’t one of “several reasons that programs need to do more than one thing at a time”. | 2009-04-03 | ||
173 | SUGGEST | In the section “Losing Your Head” you advise: " you should normally expose lazy sequences as a function that returns the sequence, not as a var that contains the sequence." But here in the memoization section you state: “The final trick is to guarantee that the cache is built from the ground up by exposing sequences, instead of functions.” Maybe a comment explaining that this does not contradict the earlier advice. Exposing the sequence is appropriate for the purpose here. | 2009-04-03 | ||
177 | ERROR | “The ref wraps and protects access to its internal state. If you look at (def current-track (ref “Whatever Happened to Soy Bomb”)) (def pung (ref 9)) | 2009-04-03 | ||
178 | SUGGEST | Your description of the property of atomicity doesn’t address what seems to be its fundamental nature: all or none. A complex transaction can’t partly succeed. It completely succeeds or completely fails. | 2009-04-03 | ||
179 | SUGGEST | “…four transactional properties are called the ACID” Does ‘the’ belong there? | 2009-04-03 | ||
179 | SUGGEST | “Users of the chat application want to see the most recent message first, More precise? | 2009-04-03 | ||
13 | TYPO | “Clojure is a power ful, general purpose programming language.” general-purpose | 2009-03-27 | ||
183 | SUGGEST | “Database transactions achieve consistency through various integrity Really nitpicking here, but should “achieve” be “maintain” instead? The point being that the system should never enter an inconsistent state. | 2009-04-03 | ||
286 | SUGGEST | There is no entry for the ‘cond’ macro in the index. Also, there is an index entry “Functions, deeply nested”. This is a misleading reference to the function deeply-nested used on pg. 170. | 2009-04-03 | ||
62 | TYPO | “It is also possible to simultanesouly - | 2009-04-03 | ||
189 | TYPO | In “Since only refs provide coordinate updates”, “coordinate” should be “coordinated”. | 2009-04-03 | ||
284 | TYPO | (This is the Bibliography page.) The title of Hofstadter’s book should start with “Gödel” (with an o-umlaut), not “GÃ˝udel” (with an uppercase A-tilde and a lowercase u-Hungarian-umlaut which I couldn’t even copy properly into the browser). Also there is some junk after the bibliography list. | 2009-04-29 | ||
183 | SUGGEST | The full syntax for ref (pg. 183), atom (pg. 184), and agent (pg. 186) should use ‘options*’ rather than ‘options?’. The notation conventions on pg. 16 state that the ? is associated with an optional arg rather than the zero or more possible with these functions (:validator, :meta). | 2009-04-03 | ||
188 | SUGGEST | “You can check both the in memory messages…” in-memory? | 2009-04-03 | ||
188 | SUGGEST | “… backup only changed infor mation since the last backup.” Maybe: only backup information that has changed since the last backup. | 2009-04-03 | ||
189 | TYPO | There is a stray footnote number next to ‘send’ in Figure 6.1. This throws off the count so that the first actual footnote in chapter 6 on pg. 199 is numbered 2. | 2009-05-27 | ||
189 | SUGGEST | “…from the peculiar semantics of each API:” Maybe instead “the semantics peculiar to each API” | 2009-04-03 | ||
191 | TYPO | “…stays in effect down any chain of calls that begin in the binding form…” ‘chain’ is singular => “any chain that begins” => “any chain of calls that begins” | 2009-04-03 | ||
202 | SUGGEST | In the Snake GUI section multimethods are used before they have been introduced - there should be a reference to the multimethod chapter. | 2009-04-03 | ||
140 | TYPO | [2nd prose paragraph, last part of last sentence] reads: “so stuff in into a var named …” thus, it should read: “so stuff it into a var named …” | 2009-04-03 | ||
191 | SUGGEST | A bit of a terminology conflict with the Lisp-specific concept of “special variables” here and the more general sense of the word ‘special’ as used on pg. 31 “Special Variables” e.g., *1, *2, *3. The index entry for “Special Variables” refers to the Lisp sense. | 2009-04-29 | ||
47 | ERROR | The list of characters allowed for a symbol does not include <, >, or =; how is it then that >, >=, <, <=, =, and -> are valid symbols? (These name Clojure functions, at the least…) | 2009-04-03 | ||
172 | TYPO | [2nd para., end of last sentence] reads: “… make the function more Clojurish in another way*s* as well:” I think you either meant this or that: | 2009-04-03 | ||
197 | TYPO | “Snakes are little bit more complicated” “a little bit” | 2009-04-03 | ||
198 | TYPO | “assoc retur n a new snake” returns | 2009-04-03 | ||
83 | TYPO | The result of to-array is an Object[], but the text shows a hybrid: | 2009-04-03 | ||
30 | TYPO | Missing space in “->#’user/hello”. | 2009-04-03 | ||
16 | SUGGEST | The distinction in usage of `->’ and `|’ is not clear. page 61 page 91: (several other examples may exist) Although it is not clear to me, what is meant by `cannot easily be distinguished from code and results’, but similar snippets should be treated in the same way, e.g. page 56 looks like any of the examples given above (ie. it is a function that prints to the console and does not have any meaningful return value). | 2009-04-03 | ||
198 | SUGGEST | The section on the snake game discusses complex “bindings” in several spots. Back on page 63 you state: “The Snake game in Section 6.6, A Clojure Snake, on page 194 makes heavy use of destructuring.” Perhaps you should add a note in the snake section reminding the reader of the idea of destructuring, for example when discussing the ‘move’ function. As it is, the word “destructuring” doesn’t show up until the last page of this section. | 2009-04-03 | ||
199 | SUGGEST | “It has none of the things that make code dif ficult to understand: global state, local variables, mutable state.” The functional model of the snake game does make use of global state (free variables) in several places. However, since this state (height, width, win-length,…) is immutable there are no side effects to worry about. This reduces the complexity of understanding the non-local aspects of the code. | 2009-04-03 | ||
202 | TYPO | “Swing calls the paintComponent (line 3) to draws the panel.” draw | 2009-04-03 | ||
202 | TYPO | “If they keyboard input was not an arrow key…” they -> the | 2009-04-03 | ||
202 | SUGGEST | “…the dirs function returns nil and update-direction does nothing.” Strictly speaking, it’s the ‘turn’ function that does nothing. ‘update-direction’ calls ‘alter’ in any case. | 2009-04-03 | ||
203 | SUGGEST | “please use your local operating-system fu” Is that too slangy? | 2009-04-03 | ||
206 | TYPO | “It is initially set to sentinel, which means that the target has not run yet” Missing period at end of sentence. | 2009-04-03 | ||
206 | TYPO | “If the result is sentinel, then this is the first caller, . Line 7 calls the function, and reset!s the result.” Not clear whether this was meant to be 2 sentences. | 2009-04-03 | ||
207 | SUGGEST | It would be helpful to demonstrate what the reader is supposed to do with the result returned by the ‘runonce’ function. This output must be captured for future use unlike defining a function via ‘defn’, for instance. Also, there are several inconsistencies in the ‘runonce’ function. The ‘reset-fn’ and ‘has-run?’ functions are returned in the opposite order in which they are defined in the ‘let’ form. They also gratuitously use different syntax in their definitions—they are both anonymous functions without parameters. Why do they look different? Finally, the “main” function (the 3rd one) returned by ‘runonce’ isn’t even named at all as the other two are. | 2009-04-03 | ||
205 | TYPO | Lancet is incorrectly capitalized twice on this page. It appears that every other instance of ‘lancet’ in the book is an appropriate case-sensitive occurrence. | 2009-04-03 | ||
231 | SUGGEST | There are numerous references throughout the book to the term ‘DSL’, however, the word is only defined offhandedly at the end of chapter 3 on page 107. Even here, no connection is made between the initialism and its meaning. Section 7.5 should explicitly define what a DSL is. | 2009-04-03 | ||
211 | TYPO | “Now you can clearly see that functions arguments are always evaluated…” Either missing an apostrophe: “functions’ arguments” or maybe just “function arguments” | 2009-04-03 | ||
211 | TYPO | Inconsistent hyphenation with “macro-expansion time”. Sometimes it appears as “macro expansion time”. | 2009-04-03 | ||
34 | SUGGEST | Re: examples/introduction.clj…may I suggest a refactoring? Thusly (sorry in advance if this renders badly): (def visitors (ref #{})) This: - removes the unnecessary (for this example) setting of ‘past-visitor’, which is never used again, and removes the cognitive overhead of the reader having to figure out what the ‘let’ special form does for now - shifts the critical section to be only the (alter…) (which has implications for the read above it, but the point is that’s the only part of the function that really requires thread safety; N.B.: why doesn’t (alter…) automatically execute inside a (dosync…)?) Cheers, | 2009-04-03 | ||
161 | SUGGEST | It’s worth mentioning that, even without the partition function, by-pairs could be defined much more simply as (defn by-pairs [x] (map vector x (rest x))) | 2009-04-03 | ||
214 | SUGGEST | “You do not want to quote expr and form, because they are macro This is a little confusing since the referent of the word they/them changes from one sentence to the next. In the first sentence, ‘they’ refers to the symbols ‘expr’ and ‘form’, which should be evaluated during macro expansion. In the second sentence, ‘them’ refers to the actual forms passed to the ‘unless’ macro. These are not evaluated during macro expansion. | 2009-04-03 | ||
72 | TYPO | occcurence typo | 2009-04-03 | ||
193 | TYPO | [5th prose paragraph, end of last sentence] reads: “far from the point in you source where…” but should read: “far from the point in you*r* source where…” | 2009-04-03 | ||
216 | SUGGEST | “Since when does not have to use its second argument as an else This is kind of an unconvincing explanation. In any case, it’s really the 3rd arg (and subsequent args) that we’re discussing. The 2nd arg is the ‘then’ clause. It might be useful instead to remind the reader of the significance of evaluating multiple forms (implies side effects) as you did on page 67 discussing ‘do’. | 2009-04-03 | ||
218 | TYPO | “Test that this new version of chain can correctly generate a single method call:” “single-method” | 2009-04-03 | ||
218 | SUGGEST | “(defmacro chain For consistency with earlier versions of ‘chain’, the ‘rest’ parameter should be ‘more’. Same for top of next page. | 2009-04-03 | ||
236 | SUGGEST | The definition of the deftarget macro can be made shorter and clearer if you first take care of the problem with the “def” special form: that giving something metadata requires use of a reader macro, which is problematic when defining a macro. So start by defining (defmacro def-with-md [md sym & optional-init] which is a macro that could be useful in a lot of other macro-defining contexts. Then deftarget can be defined as (defmacro deftarget [sym doc & forms] This avoids all the indirection with gensym. | 2009-04-03 | ||
116 | SUGGEST | Use repeat instead replicate, because repeat now supports two arguments, and replicate is likely to be removed from the core. | 2009-04-03 | ||
118 | TYPO | Missing space in “differently:set”. | 2009-04-03 | ||
118 | SUGGEST | Place the hash-set example before introducing `set’ for a smoother flow. | 2009-04-03 | ||
121 | TYPO | The color of the output of the second line in the second example on the page should be blue. | 2009-05-27 | ||
121 | TYPO | [argument] -> element? f is a function of two arguments. reduce applies f on the first two [arguments] in coll, then applies f to the result and the third [argument], and so on. | 2009-04-03 | ||
125 | TYPO | “\\h” should be “\\H” in the fix for #38306 | 2009-04-03 | ||
220 | TYPO | “… it resolves the symbol to a fully qualified name.” “fully-qualified” | 2009-04-03 | ||
165 | ERROR | `curry’ should be `faux-curry’ here: | 2009-04-03 | ||
170 | TYPO | Missing space in `symbols.replace’. | 2009-04-03 | ||
172 | SUGGEST | Use `when’ instead of `when-let’. | 2009-04-03 | ||
191 | TYPO | Missing `|’ before console output. (let [foo “let foo”] (print-foo)) | 2009-04-03 | ||
211 | TYPO | Missing space between `if.unless’, also missing `|’ before console output in | 2009-04-03 | ||
36 | TYPO | “Fully qualified names get old quickly” should be “Fully qualified names get odd quickly” | 2009-04-29 | ||
155 | SUGGEST | Maybe it’s just me, but it took me a while to understand how using “lazy-seq to replace recursion with laziness” in lazy-seq-fibo worked. Maybe adding something like the following would help: The laziness turns the formerly recursive calls into a sequence of calls only as each element of the sequence is evaluated or realized. | 2009-04-29 | ||
289 | SUGGEST | Index “letfn” as well as “let”. | 2009-04-29 | ||
54 | TYPO | The primary coverage for the Anonymous function reader macro should probably be section 2.3 Anonymous functions, not 2.2 in figure 2.2. | 2009-04-29 | ||
104 | TYPO | Were some of the line numbers on the ‘lancet/step_1_repl.clj’ code sample omitted on purpose? | 2009-04-29 | ||
221 | SUGGEST | (let [a 1, b 2, bench-result (bench (+ a b))] No real need to create bench-result variable here: Same with example below this one. | 2009-04-29 | ||
221 | SUGGEST | Autogensyms now appear to have the string “auto” appended. | 2009-05-27 | ||
218 | SUGGEST | In Figure 7.1 description of auto-gensym, should be “syntax-quoted section”? | 2009-04-29 | ||
261 | TYPO | Text flows out in the bottom of the page. | 2009-05-27 | ||
284 | TYPO | The ö in Gödel became `Ãu’. | 2009-04-29 | ||
227 | ERROR | defenum/enum is not part of clojure-contrib right now. | 2009-04-29 | ||
20 | SUGGEST | A few points about the Java/Clojure comparison, isBlank vs. blank? 1. The Java code treats null as blank. It doesn’t looks as if the Clojure code caters for this. 2. Treating a string of length zero as a special case is unnecessary in the Java code - going through the for loop zero times is fine. 3. In the Java code, use negation rather than comparison with false. | 2009-04-29 | ||
205 | TYPO | Is it intentional that the args parameter(s) is never used after line 4 of the listing? Or should (function) on line 7 be (apply function args) ? | 2009-05-27 | ||
65 | TYPO | (round 1.2) is shown as returning 2, but it actually returns 1. | 2009-04-29 | ||
123 | TYPO | The REPL result of the rank and file list comprehension form isn’t marked as such. (It doesn’t have a leading “-> ” and isn’t blue.) | 2009-04-29 | ||
247 | TYPO | “plain ’ol polymorphism” should be “plain ol’ polymorphism” since the apostrophe stands for the missing letter “d”. | 2009-04-29 | ||
233 | TYPO | The example of calling (reset boo) shows a return value of nil. The reset-fn of runonce actually returns the value of the call (reset! result sentinel) which in this case is the vale of sentinel. On my system that shows up as something like: user> (reset boo) | 2009-04-29 | ||
132 | TYPO | ([:a :b :c] 1) | 2009-04-29 | ||
278 | ERROR | At the end of the Posts and Redirect section I couldn’t “create a few snippets” because the code emitted by (new-snippet) wasn’t recognized as HTML, at least by Safari 4 beta. I change the (html) call to emit and that worked. Adding the layout code in the subsequent section also worked. | 2009-05-27 | ||
222 | SUGGEST | “All flow control macros must eventually call a spe- eventually -> ultimately ? | 2009-04-29 | ||
110 | TYPO | Shouldn’t “(rest aseq)” be “next aseq”? | 2009-04-29 | ||
50 | TYPO | The regular expression given to find-doc, to find all predicates, seems to be too inclusive. It appears | 2009-04-29 | ||
57 | TYPO | I don’t believe that the vector form of the ‘use’ function, used near the top of the page, has been seen before and it may not be obvious what it is doing. A 1/2 sentence of explanation might be useful here. | 2009-04-29 | ||
57 | TYPO | Shouldn’t the syntax of anonymous functions be described as | 2009-04-29 | ||
51 | TYPO | -> “I dunno! It is missing a quote at the end | 2009-04-29 | ||
57 | TYPO | Not a huge omission, but the sample text to each of the filter examples is “A fine day it is” except the one right after the (fn [params*] body) which is just “A fine day”. It doesn’t change the output or anything but looks strange given the surrounding examples. | 2009-04-29 | ||
135 | TYPO | The font for the examples of ‘assoc’, ‘dissoc’ and ‘merge’ change from the blue repl output to red repl input in the middle of repl output. | 2009-05-27 | ||
56 | SUGGEST | “Writing method implementations that differ by arity is useful. But if you come from an object-oriented background, you will want polymorphism, […]” I think “Writing functions that differ by arity …” would be better, since you are discussing functions here, not methods. The following sentence, which describes the object-oriented view, would still make sense. | 2009-08-16 | ||
34 | SUGGEST | The comment in line 2 of examples/introduction.clj states | 2009-08-15 | ||
36 | TYPO | first line on page says | 2009-08-15 | ||
55 | TYPO | mid page: | 2009-08-16 | ||
67 | TYPO | top of page “| Saw a big number 200” should be (remove a blank) “| Saw a big number 200” | 2009-08-16 | ||
74 | TYPO | Near mid-page: To add your own key/value pairs to a var, use the metadata metadata should be in italic | 2009-08-16 | ||
77 | TYPO | gen-and-save-class doesn’t seem to exist | 2009-08-16 | ||
256 | TYPO | collection-tag definition is out of dat | 2009-08-16 | ||
152 | ERROR | The analysis of stack-consuming-fibo is a bit misleading. It generates a number of stack frames exponential in n. (This is also proportional to n, but that is a much weaker statement). There is also a small grammar error in that sentence. | 2009-08-16 | ||
116 | TYPO | Near top: repeat should be in italics | 2009-08-16 | ||
94 | SUGGEST | The example code scripts in bin only work under bash. Under csh or tcsh, they immediately error out. One easy way to make the scripts more compatible would be to insert the line: | 2009-08-16 | ||
24 | SUGGEST | The common lisp code goes across a page break and is thus hard to read. I suggest reformatting it so it all comes on one page. | 2009-08-16 | ||
29 | TYPO | Quoting a text placed at the end of the page: “[…] You do not have to worry about any of this, because the sample code includes all these files and the REPL launch scripts place them on the classpath.” | 2009-08-16 | ||
33 | SUGGEST | if is rendered as a keyword in 3rd line of examples/introduction.clj | 2009-08-16 | ||
36 | TYPO | Referencing the namespaced version of fibs, the text has “examples.introduction.fibs” whereas it should be “examples.introduction/fibs” | 2009-08-15 | ||
1 | ERROR | In the repl.bat file in the code download each REM command is lacking a space after it so you get errors running the file. | 2009-08-15 | ||
39 | TYPO | wrt to “Anonymous Functions”, the book states “The syntax looks like this: (#body)”, should be #(body). | 2009-08-16 | ||
188 | ERROR | the example create-runonce defines the (fn [& args]) but doesn’t actually apply the args to the function. this makes the example in the book do nothing but print a newline. the (reset! result (function)) this will make it work | 2009-08-16 | ||
28 | ERROR | It is mentioned twice that “Clojure relies on Java’s BigDecimal class for arbitrary-precision decimal numbers.” The first time with a reference to the bottom of the page and the second time with the URL directly. | 2009-08-16 | ||
76 | ERROR | - You can also pass a nonstring to shout and see that - Clojure enforces the :tag by attempting to cast the Nope, otherwise this would fail too: user> (defn #{:tag String} shout [#{:tag String} s] s) The :tag definition allows Clojure to select .toUpperCase from String class in compile time and when shout is invoked ClassCastException is thrown because it is invoked on instance of wrong type. Without :tag definition .toUpperCase must be resolved during shout invocation which fails if not defined for given argument class. | 2009-08-16 | ||
46 | TYPO | On the bottom third of the page, after “Now you can call round without having to qualify its name:”, the code example is, (round 1.2) The result is actually 1, not 2. | 2009-08-16 | ||
104 | 124 | ERROR | (for [n (whole-numbers) :while (even? n)] n) yields an empty list and not (0) as the seq from (whole-numbers) starts from 1. (sugg: replace even? by odd? to get (1) as an example) | 2009-08-16 | |
223 | ERROR | In the following text, “. . . until the unlucky day that you picked a local name like start, which Shoudn’t the result be along the lines of: | 2009-08-16 | ||
33 | TYPO | Just a silly typo… The first call to “(hello ”Stu“)” doesn’t show the correct output from the REPL. That is, it doesn’t have the " marks. The second call does. | 2009-08-16 | ||
66 | ERROR | incorrect result of (round 1.2) shown. It shows 2 when it’s 1. | 2009-08-16 | ||
72 | ERROR | (index-filter #{\\a \\b} “xyz”) returned () instead of nil | 2009-08-16 | ||
81 | ERROR | user=> (import ‘(java.util Random Locale) ’(java.text MessageFormat)) Hence, the last import was returned instead of nil… | 2009-08-16 | ||
192 | ERROR | There’s a bug in Clojure 1.1.0-alpha-SNAPSHOT that breaks binding. So with the code download for the book the examples don’t work as they should. e.g. I get the following: user=> (def foo 10) Note that the binding didn’t update the value of foo to 42 and returned the root binding 10 instead… | 2009-08-16 | ||
153 | TYPO | I still get StackOverflowExceptions for n = 10000, although the presented solution is supposed to fix it. But the cuplrit is actually not “replace-symbol”, but “deeply-nested”. | 2009-08-16 | ||
208 | ERROR | as written create-runonce can’t be used to create and run println-once the way it is shown. create-runonce returns a function that when executed with parameters doesn’t pass the parameters to the wrapped function. So when creating println-once and calling it with (println-once “there can be only one!”) will yeild a blank line and nil. The blank line is calling println without args (i.e. (reset! sentinel (function)) in the code) and nil is the result of the function (println returns nil) create-runonce needs to be modified to pass the arguments through the anonymous function to the wrappered function (function). Try the following instead: user=> (defn create-runonce [function] | 2009-08-16 | ||
72 | SUGGEST | The code given for index-filter contains a redundant use of ‘when’. The code is given as: The ‘when’ is not needed. The following suffices: The sequence comprehension already checks that the predicate holds. | 2009-08-16 | ||
223 | TYPO | sample doesn’t match text: In the text it says the result is 1228277… but in the code sample the elapsed is 128277….. | 2009-08-16 | ||
233 | TYPO | Not sure if this is a typo or something I don’t understand (as it works fine). The bench-fn example has a superfluous “>” symol in it. Here’s the example from the book: The > symbol is after the parameter list for the anonymous function. It seems to work the same with or without the > so I’m not certain it’s wrong… | 2009-08-16 | ||
259 | SUGGEST | It is non-obvious how to run the (.setDir mkdir-task “sample dir”) from a new REPL (or fairly clean one). For example, one would think the following would work: user=> (use ’lancet.step-4-complete) However, mkdir-task is undefined… The answer lies all the way back in section 3.5 with the following def: user=> (def mkdir-task (org.apache.tools.ant.taskdefs.Mkdir.)) It would be nice to have the code repeated here for easily following along at the REPL or a pointer back to that section… | 2009-08-16 | ||
273 | ERROR | The following call for the modified select-snippets doesn’t need the with-connection: with-connection was just added inside select-snippets itself, so wrapping it in a with-connection is redundant. | 2009-08-16 | ||
124 | ERROR | The evaluation of (for [n (whole-numbers) :while (even? n)] n) is listed as (0). I believe it should be () as 0 is not included in the whole-numbers list. | 2009-08-16 | ||
40 | ERROR | The function clojure.contrib.repl-utils/source does not work with the version of clojure.jar included with the book source code download (which appears to be an alpha build of clojure 1.1.0). It does work with clojure-1.0.0.jar. | 2009-08-16 | ||
203 | TYPO | The second code snippet still has result 3 not 1228277342451783002 as stated in the next line. | 2009-08-16 | ||
154 | ERROR | At the bottom of the page: =
Line 2 introduces the letfn macro:
(letfn fnspecs & body)
; fnspecs > (fname [params*] exprs)+ The last “fnspecs” is incorrect. The online documentation calls this “fnspec” and says that fnspecs is a vector of fnspec. Suggested change: =
Line 2 introduces the letfn macro:
(letfn fnspecs & body)
; fnspecs > [(fname [params*] exprs)+] | 2009-08-16 | ||
32 | ERROR | Clojure source should be obtained via: | 2009-08-21 | ||
118 | SUGGEST | When the “repeat” function is first introduced on the 3rd line (The repeat function repeats an…), its name is written with the “normal text” font, instead of the monospaced one normally used for function names (as it’s done two lines later in “Try to repeat some items…”). | 2009-10-20 | ||
13 | TYPO | The output of the first (hello “Stu”) is missing the double quotes, it should be: The output of the second (hello “Stu”) on that page is correct. | 2010-06-16 | ||
18 | TYPO | The first paragraph mentions examples.introduction.fibs and it should probably be examples.introduction/fibs. | 2010-06-16 | ||
93 | OK | The following statement does not seem to be true : (next aseq) is equivalent to (seq (rest aseq)) | 2009-10-20 | ||
93 | OK | Sorry, my bad…. just double-checked again, the statement in the book is correct. Sorry. | 2009-10-20 | ||
36 | DEFER | In the example of redefining the hello function to be hello-with-memory, the text says you can verify the new functionality by typing (hello “Rich”) and then typing (hello “Rich”) again. If you use (load-file “examples/introduction.clj”) to automatically enter the example code instead of typing it in by hand, however, the example fails, because the example file defines everything in the “examples.introduction” namespace. When you type just (hello “Name”), you’re really getting (user/hello “Name”), which is the simpler function you typed in before. The new function lives in “examples.introduction/hello”. Typing (examples.introduction/hello “Rich”) twice in a row does display the new functionality. | This is a good point for the next edition. | ||
134 | ERROR | “The stack-consuming-fibo creates a number of stack frames proportional to n” n should be (2 to the n) because each call generates two calls. | 2010-06-16 | Rephrased in second printing. | |
23 | DEFER | In | This example code showing lancet usage is not intended to be run at this point in the book. To see where lancet has gone since the book has been published, see http://github.com/technomancy/leiningen | ||
172 | ERROR | Using the “binding” form does not work properly on Mac OS Snow Leopard using the code downloaded from the Programming Clojure website. (def foo 10) (binding [foo 42] foo) The Clojure version reported by the REPL is 1.1.0-alpha-SNAPSHOT. | 2010-06-16 | This was a one-off issue with a few builds of Clojure, now fixed. Please get the source code from http://github.com/stuarthalloway/programming-clojure if possible. | |
223 | TYPO | When talking about auto-gensym, the “try it” example is `foo#. The font in the PDF makes this appear like ’foo#. Copying gives the correct backtick, however. | |||
292 | TYPO | under lemma Refs, the second line reads “concurrrency model and”, which I guess should be “concurrency model and”. | 2010-06-16 | ||
Title | TYPO | The “Version of Book With Error” combo box on the “Add Erratum for Programming Clojure” webpage (i.e. the page I am filling this out on) states that the publication version P2.0 date is Oct 20, 2009. My copy of the book says: There is no Sept 16, 2009: P2.0 value in the combo box. | |||
189 | OK | Line 8 of the runonce code has a nil that looks like it can be omitted. | 2010-07-19 | Returning nil prevents reset-fn from exposing implementation details. | |
209 | OK | line 8 of the runonce code has a nil that could be omitted. | 2010-07-19 | Returning nil prevents reset-fn from exposing implementation details. | |
208 | OK | (function) should be (apply function args) | 2010-07-19 | This is not a problem once #41579 is fixed. Thanks! | |
223 | 203 | OK | The example shows what would happen if Clojure allowed unqualified symbols “start” and “result” in a macro. The example continues with “start” being bound to the user’s value, 1. This gives an erroneous result on the time it takes to add the numbers, NOT the result of adding the numbers. So, in the middle of the page, “All of | 2010-07-19 | The macro trumps the let binding, not the other way around. Try it and see. |
208 | OK | The definition of println-once should be | 2010-07-19 | This is not a problem once #41579 is fixed. Thanks! | |
208 | TYPO | I see what you are doing now. But if you leave line 7 of the code with (function) and include the argument to println in the def of println-once then you should omit the argument in the two calls to println-once at the botgtom of the page | 2010-06-16 | ||
52 | OK | This may be a misunderstanding on my part, but for the code example: the book states “The index/element pairs of (indexed coll) are bound to the names idx and elt but only when (pred elt) is true.” It seems that elt, at the very least, must get bound regardless in order to evaluate whether (pred elt) is true; it does not make sense to me that it could base its decision to bind or not based on whether an as-yet-unbound name satisfies a predicate. Alternately, if it is clever enough to somehow recognize “I only want to bind values to [idx elt] if the value that would be bound to elt satisfies pred, so I will test pred with that value.” then that should probably be explicitly stated, though I am not sure that that is actually different than binding. | 2010-07-19 | I believe the existing text is simple and accurate. | |
52 | OK | In the definition of index-filter, what is the purpose of the outer when? | 2010-07-19 | Prevent NullPointerExceptions when passed nil. | |
31 | DEFER | The remark about “following the *nix instructions” for Cygwin is not accurate. From a Cygwin shell, the repl.sh script does not work. You must change the -cp argument (quote it and change colons to semicolons). The reason is that java for Windows uses a different path separator. | |||
145 | SUGGEST | The instantiate-task function does not need to add task at the end, since (doto task exp1 exp2 ..) returns task implicitly | 2010-06-16 | This was fixed prior to the first printing. | |
223 | TYPO | While describing about symbol capture using the bench macro, the explanation seems correct but the code has a typo. (let [start 1 end 2] Here result should be 1228277342451783002 and :elapsed time should be different. The text following this gives the correct description though. | 2010-06-16 | Fixed in second printing. | |
84 | TYPO | In there paragraph right after the (make-array String 5) example, you state that “[Ljava.lang.String” is the JVM spec’s encoding for an array of String objects. The semicolon is missing from that. The encoding should be “[Ljava.lang.String;” as the semicolon matches the starting “L”. | 2010-06-16 | ||
74 | OK | The phrase, metadata is “data about data”, is technically incorrect. Although it is more common in English to do so, the preferred is still to treat data as plural. Thus it should read metadata are “data about data”. The wikipedia says “the word metadata is” which is singular because it is referring to “the word” and not “metadata”. | 2010-07-19 | Author's choice. | |
52 | ERROR | (index-filter #{\\a \\b} “xyz”) returns (), not nil. | 2010-06-16 | This was fixed in the second printing. | |
73 | TYPO | At the footnote at the bottom of the page, you say you could write an “functional indexForAny” in java, but it should be “indexOfAny” to agree with the rest of the text. | 2010-06-16 | ||
39 | TYPO | (#body) instead of #(body) | 2010-06-16 | ||
27 | SUGGEST | This is about “cond”. I got the impression that Clojure supports the Common Lisp cond form (with parentheses). But when I tried typing the example code, I got an error: (cond After reading the paragraphs on cond, I thought Clojure supported both the Common Lisp form that had parentheses and the form that didn’t have parentheses. Maybe the paragraph can have a note about that? I wouldn’t have understood this without typing in the example. | |||
36 | TYPO | The if in a comment block is colored. | |||
236 | TYPO | A normal quote is used in the first listing of deftarget rather than a back-quote. | |||
75 | SUGGEST | The metadata reader macros described have been deprecated with the release of Clojure 1.2 — ‘’ is now used to attach metadata to objects (with a shortcut for type hinting), and ’#’ is no longer supported. | |||
39 | SUGGEST | In the first anonymous fn example, “A fine day” string is used. | |||
97 | TYPO | The text states, “The interesting part is the :gen-classform….” I believe it should read “:gen-class form”. | |||
52 | ERROR | In the second example of the use of index-filter: (index-filter #{\\a \\b} “xyz”) should the return value be “()” (an empty list) instead of “nil”? That’s what I get, and what I’d expect. | |||
171 | 151 | TYPO | Under subheading, “Replacing Recursion with Laziness,” (replace ’((a b) (((b g r) (f r)) c (d e)) b) ’b ’a) is shown to be returning: ((a a) (((a g r) (f r)) c (d e)) a) but this throws an exception: “Wrong number of args (3) passed to: core$replace | ||
39 | TYPO | For for anonymous function using implicit parameter names is “(#body)”. Should be “#(body)”. | |||
122 | ERROR | It says: “To see a non-true match, try using some with identity to find the first non-nil value in a sequence: Shouldn’t that be “the first value in a sequence that evaluates to true”? Because otherwise it would return false wouldn’t it? | |||
153 | TYPO | Unsure if my previous attempt to submit this worked as it complained about use of a hyperlink. There’s a problem with the typesetting of the kindle version which is not a problem in the PDF. The subscripts don’t work properly - the subscript text doesn’t appear and the text which follows is in a smaller font. there’s an image at dl.dropbox.com/u/6538629/Subscripts.JPG | |||
41 | ERROR | (show java.util.HashMap) did not work | |||
38 | ERROR | The example near the top of the page is (take 10 examples.introduction/fibs). The actual expression should be (take 10 (examples.introduction/fibs)). | |||
38 | ERROR | Sorry. The other examples using fibs on this page are also incorrect. The text on the pages is (take 10 fibs). The example should be (take 10 (fibs)). | |||
39 | ERROR | The example near the bottom of the page defines the function “hello” in the namespace examples.introduction. This function was also defined on page 36 with a different implementation. If you are trying to re-create the sample code instead of simply reading it, you must overwrite the previous version. I do not believe this consequence was intended. | |||
40 | SUGGEST | I believe the “source” function is now defined is clojure.repl. | |||
57 | SUGGEST | On page 56, we define the function “greeting” in the file exploring.clj. On page 57, we redefine the function “greeting” to accept multiple arguments. It might be clearer to name these two functions differently. | |||
59 | SUGGEST | On page 58, we define “indexable-words?” as a top-level function. On page 59, we reuse that name but bind it to a locally defined function. A footnote might be nice indicating that the second usage shadows the first. | |||
73 | ERROR | On page 73, we define a function named describe-class. This function clashes with the version defined on the previous page. If we want to maintain both, I believe we need two different names. | |||
78 | SUGGEST | On page 77, we provide sample code for reader/tasklist.clj. On page 78, we then shift to example/tasklist.clj. For several minutes, I thought these we two different files needed to compile a Clojure class. Eventually, I read paragraph 4 on page 78 and discovered that files in example illustrate the provided sample code but files in reader/tasklist.clj are code that I might enter. I not mentioning the difference between code in reader and example until almost a page after introducing reader confusing. | |||
84 | ERROR | We define class-available? near the middle of the page and then we redefine it a paragraph later. | |||
106 | SUGGEST | On this page, we define the symbol x twice. When I was first entering this data myself, I did not (since I’d just defined x). When I entered the function (dorun x), I DID NOT see the same result as displayed in the book. Although I eventually determined the reason for this difference, I think it would be worthwhile to emphasize the need to define this symbol twice. | |||
203 | ERROR | When I tried the examples on this page, the Clojure repl reported an error: user=> (let [a 1 b 2] (broken-bench (+ a b))) user=> I am using Clojure 1.2. | |||
92 | TYPO | Code example at bottom of page reads: (parse (java.io.File. “examples/sequences/compositions.xml”)) However, the proper path to compositions.xml is “data/sequences/compositions.xml” |