More Clojure from Uncle Bob JSPS 28

Posted by Uncle Bob Fri, 31 Jul 2009 13:12:44 GMT

Thanks to all who posted their solutions to the Bowling Game. Just to be contrary, I decided to implement yet another kind of solution. This one clearly shows my OO roots.

h2. Here are the tests.
(ns bowling-game)
(use 'clojure.contrib.test-is)
(use 'bowling-game)

(defn roll-list [game list]
  (vec (concat game list)))

(defn roll-many [game n pins]
  (roll-list game (repeat n pins)))

(deftest can-create-game
  (is (not (nil? (new-game)))))

(deftest gutter-game-should-score-0
  (is (= 0 (score (-> (new-game) (roll-many 20 0))))))

(deftest all-ones-should-score-20
  (is (= 20 (score (-> (new-game) (roll-many 20 1))))))

(deftest one-spare
  (is (= 16 (score (-> (new-game) (roll-list [5 5 3]) (roll-many 17 0))))))

(deftest one_strike
  (is (= 24 (score (-> (new-game) (roll-list [10 3 4]) (roll-many 16 0))))))

(deftest perfect-game
  (is (= 300 (score (-> (new-game) (roll-many 12 10))))))

(run-tests 'bowling-game)

And here is the code.

(ns bowling-game)
(defn new-game [] [])

(defn frame-type [[first second]]
  (cond
    (= 10 first) :strike
    (= 10 (+ first second)) :spare
    :else :no-mark))

(defmulti frame-size frame-type)
(defmethod frame-size :strike [_] 1)
(defmethod frame-size :spare [_] 2)
(defmethod frame-size :no-mark [_] 2)

(defmulti frame-score frame-type)
(defmethod frame-score :strike [[_ first second]] (+ 10 (+ first second)))
(defmethod frame-score :spare [[_ _ next]] (+ 10 next))
(defmethod frame-score :no-mark [[first second]] (+ first second))

(defn score [game]
  (loop [frame 1 rolls game score 0]
    (if (> frame 10)
      score
      (recur (inc frame) (subvec rolls (frame-size rolls)) (+ score (frame-score rolls))))))
Comments

Leave a response

  1. Avatar
    http://uglylispcode.wordpress.com 1 day later:

    @uncle bob,

    If any yahoos try telling you that functional programming is not OOP, they are blowing smoke.

    A lambda over let over lambda is an object.

    To me the most important part of OOP is data encapsulation and having the methods that transform the data into the behavior that the object needs and the above definitely qualifies.

    You don’t think that the principles that you use for OOP no longer apply when working with a functional program? OCP, SRP, LSP, and all the rest definitely apply.

    If you keep in mind that sequences (alist and plist) is the basic data types. And that the operators (I say operators not methods) are used to transform (iteration and recursion) the lists into the outputs you desire.

    When I started working with CL, I started with making enhancements to a unit test framework called lisp-unit. What I wanted is to change its output and also to add fixtures to my tests.

    For me the unit test framework is ugly: (is(= 0 0)) what the hell! The first thing I would do is change it something like this: (should= 0, 0) or (is= 0, 0). The parenthesis has too much noise. I understand why it is, but still the nice thing about using a lisp language is that you can change it to go in the direction of a DSL. Unit testing is an DSL.

    I highly recommend that when starting a new language use it with something that you do know

    Right now I’ve stopped with the CL and am back into the dotnet world. I want to bring some of the things I learned with CL back into C#.

    My two blogs are here, check them out: http://uglylispcode.wordpress.com http://uglycode.wordpress.com

  2. Avatar
    Philip Schwarz 1 day later:

    @Uncle Bob

    When I saw your previous blog entry, Uncle Bob, JSPS: Learning Clojure, I had a go at coding the bowling game, but didn’t get round to posting my solution because I got interrupted by something else.

    I had gone for exactly the same frame-type function as you did! Here is my attempt (my first Clojure program):

    (defn frame-type [[first second]] 
        (cond (= 10 first) :strike
              (= 10 (+ first second)) :spare
              :else :normal))
    
    (defmulti score frame-type)
    (defmethod score :strike [[_ first second & rest]] 
      (+ 10 first second (if (nil? rest) 0 (score (into [first second] rest)))))
    (defmethod score :spare  [[_ _ next & rest]] 
      (+ 10 next (if (nil? rest) 0 (score (cons next rest)))))
    (defmethod score :normal [[first second & rest]] 
      (+ first second (if (nil? rest) 0 (score rest))))
    

    At the time, I did not write it test-first, but I have now tested it using a minor adaptation of your tests:

    (deftest gutter-game-should-score-0
      (is (= 0 (score  (repeat 20 0)))))  
    (deftest all-ones-should-score-20
      (is (= 20 (score  (repeat 20 1)))))
    (deftest one-spare
      (is (= 16 (score (into [5 5 3] (repeat 17 0) ) )))) 
    (deftest one-strike
      (is (= 24 (score (into [10 3 4] (repeat 16 0))))))  
    (deftest perfect-game
      (is (= 300 (score (repeat 12 10)))))
    (run-tests)
    

    I prefer my Haskell version of the Bowling Game:

    score [x, y]                             = x + y      -- Normal Frame
    score [10, x, y]                         = 10 + x + y -- Strike
    score [x, y, z]                          = 10 + z     -- Spare
    score (10:(x:(y:rest)))                  = 10 + x + y + score (x:(y:rest)) -- Strike
    score (x:(y:(z:rest)))  | (x + y) == 10  = 10 + z + score (z:rest)         -- Spare
    score (x:(y:rest))      | otherwise      = x + y + score rest              -- Normal Frame
    

    It is easier to read/understand.

    Your initial tweet about the Clojure book prompted me to get a copy of the book. I agree with your later tweet, that the book is disappointing because it feels rushed, but I guess that I’ll persevere with it, especially since you lately tweeted that your opinion of the book is changing, that the organization is frustrating, but the content is rich.

    I look forward to your future thoughts on functional programming.

  3. Avatar
    Kooba Handbags 8 months later:

    Living without an aim is like sailing without a compass. with a new http://www.handbags4buy.com/ idea is a crank until the idea succeeds.

  4. Avatar
    Bob about 1 year later:

    Really helpful for me.I have learned a lot makeup brushes about asp.net from this.

  5. Avatar
    bag manufacturer about 1 year later:

    tions to the Bowling Game. Just to be contrary, I decided to implement ye

  6. Avatar
    Mens Watch about 1 year later:

    Lady Gaga Mens Watch has undergone louis vuitton wallet a “spiritual” commitment ceremony with her boyfriend.The rolex watch ‘Paparazzi’hitmaker and Luc Carl reportedly .zf

  7. Avatar
    willson about 1 year later:

    Thanks for sharing. I get satisfaction from this site. preserve it up. uggs outlet

  8. Avatar
    Silicone Molding about 1 year later:

    Mold making is the core business of Intertech (Taiwan). With world level technology, Intertech enjoys a very good reputation for making Injection Mold and Plastic Moldsfor their worldwide customers.

  9. Avatar
    moncler about 1 year later:

    thanks for Moncler Jackets || Christian louboutin UK || Moncler coats || Christian louboutin shoes || Christian louboutin pumps your post!

  10. Avatar
    garbage bag making machine about 1 year later:

    This is one of the most professional manufacturers and suppliers in plastic packing machinery. We mainly provide non woven bag making machine,disposable glove machines,blowing film machines,flexo printing machines,garbage bag making machine etc.

  11. Avatar
    Criminal Check about 1 year later:

    The most important part of OOP is data encapsulation and having the methods that transform the data into the behavior that the object needs and the above definitely qualifies.

  12. Avatar
    lupus symptoms about 1 year later:

    I guess that I’ll persevere with it, especially since you lately tweeted that your opinion of the book is changing, that the organization is frustrating, but the content is rich.

  13. Avatar
    Tenant Screening about 1 year later:

    I understand why it is, but still the nice thing about using a lisp language is that you can change it to go in the direction of a DSL. Unit testing is an DSL.

  14. Avatar
    Criminal Records about 1 year later:

    I started with making enhancements to a unit test framework called lisp-unit. What I wanted is to change its output and also to add fixtures to my tests.

  15. Avatar
    cold room about 1 year later:

    Haile Electric Industrial Co. Ltd. is the leading manufacturer and exporter of cold room,axial fan,condensing unit,centrifugal fan,shaded pole motor and refrigeration products in China.

  16. Avatar
    vibradngers about 1 year later:

    I started with making enhancements to a unit test framework called lisp-unit. What I wanted is to change its output and also to add fixtures to my tests.

  17. Avatar
    okey oyunu oyna about 1 year later:

    Nice code. Thanks

    internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.

  18. Avatar
    shoes christian louboutin about 1 year later:

    It doesn’t matter, I can upload again for you. What server do you prefer most? :D

  19. Avatar
    beats by dr dre headphones about 1 year later:

    I found that his foot odors never bring us to death.I never regret buying these beats by dr dre studio for him. These beats by dr dre solo are just the same as selling in the franchise store.Or even better.

  20. Avatar
    bagsupplyer over 2 years later:

    Thanks for share with us.I look forward to reading more. Designer fashion women replica shoulder bag from China for sale on line

  21. Avatar
    best sleep aid over 2 years later:

    Cloudsourcing combines on-demand business process outsourcing (BPO) with crowdsourcing technologies to enable companies to purchase quality BPO services on-demand through a pay-per-use model.

  22. Avatar
    Tips For Bowling over 2 years later:

    Everybody has a high point and a lot goes into that: timing, situation, general consciousness.

  23. Avatar
    gianmarco lorenzi over 2 years later:

    too wide to freeze

  24. Avatar
    Discount Louboutin Shoes over 2 years later:

    Every women always has Christian Louboutins Wedding Shoes turn of fame but it also has its own goodbyes.

  25. Avatar
    bladeless fans over 3 years later:

    More Clojure from Uncle Bob JSPS 24 good post33

  26. Avatar
    louboutin sales over 3 years later:

    More Clojure from Uncle Bob JSPS 25 hoo,good article!!I like the post!154

  27. Avatar
    hermes blue jean over 3 years later:

    Well, potentially, yes?

  28. Avatar
    girl cosplay over 3 years later:

    http://www.outfitscosplay.com/cosplay-catalog/eureka-7-cosplay Deluxe Eureka 7 Cosplay Costumes for Sale.Find your favorite characters and cosplay outfits from all the popular anime and games.

Comments