You can find the resulting code in GitHub.
I love Midje's readability. Look at the tests:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns fizz_buzz.t-core | |
(:use midje.sweet) | |
(:use [fizz_buzz.core])) | |
(facts "About fizz-buzz-number" | |
(fact "A number that is not a multiple of | |
neither 3 nor 5 | |
is turned into a string" | |
(fizz-buzz-number 1) => "1" | |
(fizz-buzz-number 2) => "2") | |
(fact "A number that is a multiple of 3 | |
is turned into 'Fizz'" | |
(fizz-buzz-number 3) => "Fizz" | |
(fizz-buzz-number 9) => "Fizz") | |
(fact "A number that is a multiple of 5 | |
is turned into 'Buzz'" | |
(fizz-buzz-number 5) => "Buzz" | |
(fizz-buzz-number 25) => "Buzz") | |
(fact "A number that is a multiple of | |
3 and 5 is turned into 'FizzBuzz'" | |
(fizz-buzz-number 15) => "FizzBuzz")) | |
(facts "About fizz-buzz" | |
(fact "An empty collection of numbers is | |
turned into an empty string" | |
(fizz-buzz []) => "") | |
(fact "A collection of numbers is turned into | |
a string of words separated by spaces | |
where each word resulted from applying | |
fizz-buzz-number" | |
(fizz-buzz (range 1 16)) => | |
"1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz")) |
This is the FizzBuzz code in Clojure:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns fizz_buzz.core) | |
(defn fizz-buzz-number [num] | |
(let [is-multiple-of? (fn [n] (= 0 (rem num n))) | |
a-multiple-of-3 (is-multiple-of? 3) | |
a-multiple-of-5 (is-multiple-of? 5) | |
a-multiple-of-both (and a-multiple-of-3 | |
a-multiple-of-5)] | |
(cond | |
a-multiple-of-both "FizzBuzz" | |
a-multiple-of-3 "Fizz" | |
a-multiple-of-5 "Buzz" | |
:else (str num)))) | |
(defn fizz-buzz [coll] | |
(clojure.string/join | |
\space | |
(map fizz-buzz-number coll))) |
Compare it to this version I did in Racket's Advanced Student Language some time ago:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#reader(lib "htdp-advanced-reader.ss" "lang")((modname fizzbuzz) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ()))) | |
(check-expect (fizz-buzz empty) empty) | |
(check-expect (fizz-buzz (list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)) | |
(list "1" "2" "Fizz" "4" "Buzz" "Fizz" "7" "8" "Fizz" "Buzz" "11" "Fizz" "13" "14" "FizzBuzz" "16")) | |
(define (fizz-buzz loi) | |
(if (empty? loi) loi | |
(cons (translate (first loi)) | |
(fizz-buzz (rest loi))))) | |
(check-expect (translate 1) "1") | |
(check-expect (translate 3) "Fizz") | |
(check-expect (translate 6) "Fizz") | |
(check-expect (translate 5) "Buzz") | |
(check-expect (translate 10) "Buzz") | |
(check-expect (translate 15) "FizzBuzz") | |
(define (translate num) | |
(local [(define (multiple-of-3? num) | |
(zero? (remainder num 3))) | |
(define (multiple-of-5? num) | |
(zero? (remainder num 5))) | |
(define (multiple-of-3-and-5? num) | |
(and (multiple-of-3? num) | |
(multiple-of-5? num)))] | |
(cond [(multiple-of-3-and-5? num) "FizzBuzz"] | |
[(multiple-of-3? num) "Fizz"] | |
[(multiple-of-5? num) "Buzz"] | |
[else (number->string num)]))) |
They are more or less the same (except that Clojure's version returns a string whereas Racket's one returns a list of strings).
On one hand, I prefer Clojure's cond which is more readable because it's more lenient with the parentheses.
On the other hand, I really like how Racket's local allows to define local functions inside another function in the same way they are defined in a module.
In Clojure I also defined a local function is-multiple-of? using let but the result is less readable than using Racket's local.
Update: I keep on working on this kata on the next post, Practising Clojure sequences using FizzBuzz and REPL Driven Development.
No comments:
Post a Comment