3

Of the two solutions to FizzBuzz in clojure, why is the first one faster?

; #1
(defn fizzbuzzer [z]
    "fizzbuzz checker."
    (let [fizz? (zero? (rem z 3))
          buzz? (zero? (rem z 5))
          fizzbuzz? (and fizz? buzz?)]

        (cond fizzbuzz? "FizzBuzz"
              buzz? "Buzz"
              fizz? "Fizz"
              :else z)))

; #2
(defn fizzbuzzer2 [z]
    "fizzbuzz checker."
    (let [fb (str
                (if (zero? (rem z 3)) "Fizz" "")
                (if (zero? (rem z 5)) "Buzz" ""))]
        (if (seq fb) fb z)))

; profiling ;
; (time (fizzbuzzer 1500))
;  => "Elapsed time: 0.098058 msecs"
; (time (fizzbuzzer2 1500))
;  => "Elapsed time: 0.150438 msecs"

;; note: profiling done on separate instances to avoid caching

P.s. FizzBuzz?

~ If the number is divisible by 3, print Fizz instead of the number. If it's divisible by 5, print Buzz. If it's divisible by both 3 and 5, print FizzBuzz.

cdlane
  • 40,441
  • 5
  • 32
  • 81

1 Answers1

5

Second solution concatenates strings for each request when the first one returns references to existing strings. (str (if..) (if..)) creates 2 intermediary strings.

If I may add, to do a more proper profiling you need to run these functions repeatedly for some number of cycles. And for better results do it twice and discard first result, this will allow Java Just-In-Time compiler to do its job.

Ivan Koblik
  • 4,285
  • 1
  • 30
  • 33