Skip to content

Instantly share code, notes, and snippets.

@jivagoalves
Created February 3, 2014 13:52
Show Gist options
  • Save jivagoalves/8784192 to your computer and use it in GitHub Desktop.
Save jivagoalves/8784192 to your computer and use it in GitHub Desktop.
; http://aphyr.com/posts/305-clojure-from-the-ground-up-macros
; Problem 5
; Using the rationalize function, write a macro exact
; which rewrites any use of +, -, *, or / to force the
; use of ratios instead of floating-point numbers.
; (* 2452.45 100) returns 245244.99999999997, but
; (exact (* 2452.45 100)) should return 245245N .
(defmacro exact
[[f x y & more]]
(cond
(not x) `(~f)
(not y) `(~f (rationalize ~x))
:else `(let [result# (~f (rationalize ~x) (rationalize ~y))]
(if-let [next# (first [~@more])]
(~f result# (rationalize next#))
result#))))
(= (exact (*)) 1)
(= (exact (* 1.5)) 3/2)
(= (exact (* 2452.45 100)) 245245N)
(= (exact (/ 2452.45 100)) 49049/2000)
(= (exact (* 2452.45 100 2)) 490490N)
(macroexpand-1 '(exact (* 1.5)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment