Uncle Bob, JSPS: Learing Clojure

Posted by Uncle Bob on 07/19/2009

(JSPS: Just Some Poor Schmuck)

I’m trying to learn Clojure, and I’m finding the effort challenging. Perhaps you can help me.

Programming in Clojure (A derivative of Lisp) requires a certain “inside-out” thinking. I’m finding the combination of the shift in thought process and TDD quite difficult to resolve. So I thought I’d ask for your help.

Below is the Bowling Game written in Clojure complete with unit tests. I’m not at all pleased with the result. The tests, especially, look bizzare and backwards to me.

Please post your own solutions to this so that we can all compare and contrast them.

Tests

(ns bowling-game) (use 'clojure.contrib.test-is) (use 'bowling-game)  (defn roll-list [game list]   (if (empty? list)     game     (roll-list (roll game (first list)) (rest list))     ))  (defn roll-many [game n pins]   (loop [i n g game]     (if (zero? i)       g       (recur (dec i) (roll g pins)))))  (defn gutter-game [game] (roll-many game 20 0))  (deftest can-create-game   (is (not (nil? (new-game)))))  (deftest gutter-game-should-score-0   (is (= 0 (score (gutter-game (new-game))))))  (deftest all-ones-should-score-20   (is (= 20 (score (roll-many (new-game) 20 1)))))  (deftest one-spare   (is (= 16 (score     (roll-many       (roll-list (new-game) [5 5 3])       17 0)))))  (deftest one_strike   (is (= 24 (score     (roll-many       (roll-list (new-game) [10 3 4])       16 0)))))  (deftest perfect-game   (is (= 300 (score (roll-many (new-game) 12 10)))))  (run-tests 'bowling-game)

Code

(ns bowling-game) (defn new-game [] [])  (defn next-two-balls [rolls]   (+ (rolls 0) (rolls 1)))  (defn score-strike [rolls]   [1 (+ 10 (+ (rolls 1) (rolls 2)))])  (defn score-spare [rolls]   [2 (+ 10 (rolls 2))])  (defn score-no-mark [rolls]   [2 (next-two-balls rolls)])  (defn score-next-frame [rolls]   (if (= 10 (first rolls))     (score-strike rolls)     (if (= 10 (next-two-balls rolls))       (score-spare rolls)       (score-no-mark rolls))))  (defn score [game]   (loop [frame 1 rolls game score 0]     (if (> frame 10)       score       (let [frame-score (score-next-frame rolls)]         (recur (inc frame) (subvec rolls (frame-score 0)) (+ score (frame-score 1)))))))  (defn roll [game pins]   (conj game pins))

Comments

Leave a response