Monday, April 2, 2012

On Lisp in Clojure ch 4 (4.5 - 4.8)

I am continuing to translate examples from On Lisp by Paul Graham into Clojure. Today I will go over the last few sections of chapter 4.

Section 4.5 Mapping

The map-> function is more concise in Clojure. I also think it is clearer to see that what it is doing is generating a sequence, and mapping a function over that sequence.

In the sample call to map-> I thought it would be fun to describe the functions being passed in 3 different ways, just for variety.

(defn map-> [fn a test-fn succ-fn]
  (map fn (take-while test-fn (iterate succ-fn a))))
 
(map-> inc -2 #(< % 2) (partial + 0.5 ))

Graham presents functions that take in two lists and map a function over the two lists without joining them first. He explains that it doesn't make sense to cons up a list to just pass it to another function and forget it.

Sequences in Clojure are either lazy or persistent. In either case there shouldn't be any penalty for joining the list before passing it into a function.

Section 4.6 I/O

Translating these examples was more about completeness and curiosity. If you are interacting with your program, you will probably use the repl. If you are making something for public consumption, Seesaw is great for doing desktop ui, and Noir is great for doing web interfaces.

(defn read-list []
  (str \( (read-line) \)))

(defn prompt [text]
  (do
    (println text)
    (read-line)))

(defn break-loop [fn quit]
  (let [x (read-string (prompt (str "type " quit " to quit")))] 
    (if (not (= x quit))
      (do
        (fn x)
        (recur fn quit)))))

(break-loop #(println (eval %)) :q)

Section 4.7 Symbols and Strings

Clojure's str function can turn numbers and symbols into strings, and is variadic:

(str Math/PI " pieces of " 'pi)
;;seq can convert strings into sequences of characters
(seq "bomb")
;; => \b \o \m \b

;;strings can be converted to symbols, with or without namespaces
(symbol "foo")
(symbol "some-ns" "foo")

;;Clojure also adds keywords, which you can convert to from strings:
(keyword "foo")
(keyword "some-ns" "foo")

;;If you are not qualifying the keyword with a namespace, you can also create a keyword directly from a symbol
(keyword 'foo)
(keyword "some-ns" (str 'foo))

Section 4.8 Density

This section doesn't have any examples. Graham says that writing utility functions makes your code more concise, which in the long run makes it more readable. Clojure's built in utilities also make code very concise, and also make for a common vocabulary for programmers.

No comments:

Post a Comment