Inspired by Stuart Holloway’s excellent series porting Practical Common Lisp to Clojure and Ola Bini’s bad-ass port of Paradigm’s of Artificial Intelligence to Ruby. I have started my own quest to port Paul Graham’s On Lisp to Clojure.

Posts in this series: ch. 2, ch. 2 redux, ch. 3, ch. 4, ch. 5

I have made it through chapter 2 and am ready to start the coding for chapter 3. I will post when the code is “complete”, but my progress can be followed on Github.

; pg. 10
(defn dbl [x]
  (* x 2))

(dbl 39)
(dbl 17872687642786723868743216782)

; pg. 11
(= dbl (first (list dbl)))

; pg. 12
(fn [x] (* x 2))

((fn [x] (* x 2)) 20)

; pg. 13
(def dbl (fn [x] (* x 2)))

; pg. 14
(map (fn [x] (+ x 10)) '(1 2 3))

(map + '(1 2 3) '(10 100 1000))

;; Clojure uses the Java's Comparator on the sort function
;; so there is no need to supply the < function.  In fact,
;; if you did, an exception would be thrown. (l@@k why?)
(sort '(1 4 2 5 6 7 3))

; pg. 15
;; Because Clojure is a Lisp-1, funcall is not needed.  Instead,
;; we just call directly as (f)
(defn remove-if [f lst]
  (if (nil? lst)
    nil
    (if (f (first lst))
      (remove-if f (rest lst))
      (cons (first lst) (remove-if f (rest lst))))))

(remove-if even? '(1 2 3 4 5))
(remove-if nil? '(1 2 nil 3 nil))
(remove-if (fn [x] 
             (if (> x 5)
               nil
               x)) 
           '(3 4 5 6 7))


; pg. 16
(let [y 7]
  (defn scope-test [x]
    (list x y)))

(let [y 5] (scope-test 3)) ;; no shocker here

; pg. 18
(defn list+ [lst n]
  (map (fn [x] (+ x n)) lst))

(list+ '(1 2 3) 10)

;;
;; This is surprisingly difficult given that Clojure does not allow the 
;; modification of local variables defined in a let.  Only vars (globals)
;; and class fields can be modified with the (set!) function.  
;; Therefore, I had to hack it so that the closed counter is an array
;; of one integer element.  Therefore, it is the array that is modified
;; and not the count.  The point being, if you want to create closures
;; for functions modifying local state, then you have to use a mutable object
;; to do so
;;
(let [counter (to-array [0])]
  (defn new-id [] (aset counter 0 (inc (aget counter 0))))
  (defn reset-id [] (aset counter 0 0)))


;; On the other hand, this is extremely easy
(defn make-adder [n]
  (fn [x] (+ x n)))

(def add10 (make-adder 10))
(def add42 (make-adder 42))

(add10 1)
(add42 100)
(add42 (add10 1))

; pg. 19
;; Again we run into the immutable local binding feature.  Since I already 
;; solved this problem before, getting it to work for this case was 
;; a piece of cake.
(let [n (to-array [0])]
  (defn make-adderb [m]
    (aset n 0 m)
    (fn [x & change]
      (if change
        (aset n 0 x)
        (+ (aget n 0) x)))))

(def addx (make-adderb 1))
(addx 3)

(addx 100 true)
(addx 3)


; pg. 22
;; Clojure handles this very nicely.  
(defn count-instances [obj lsts]
  (defn instances-in [lst]
    (if (list? lst)
      (+ 
       (if (= (first lst) obj) 1 0)
       (instances-in (rest lst)))
      0))
  (map instances-in lsts))

(count-instances 'a '((a b c) (d a r p a) (d a r) (a a)))


;; Tail-recursive find-if 
;; returns the first instance satisfying (f)
(defn our-find-if [f lst]
  (if (f (first lst))
    (first lst)
    (our-find-if f (rest lst))))

(our-find-if even? '(1 3 5 7 9 11 14))


; pg. 23
;; Tail-recursive our-length
(defn our-length [lst]
  (defn rec [lst acc]
    (if (nil? lst)
      acc
      (rec (rest lst) (inc acc))))
  (rec lst 0))

(our-length (range 100))
(our-length (range 0 100 2))


; pg. 24
(defn triangle [n]
  (defn tri [c n]
    (if (zero? n)
      c
      (tri (+ n c)
           (- n 1))))
  (tri 0 n))

(triangle 10)
(triangle 30000)  ;; one more zero blew my stack

-m