I'm putting them here for a lightweight comparison. They're not supposed to be efficient or clever solutions, just the first ones I came up with. Since there are really few differences between the two languages at this level, I took the liberty of using Clojure thread-first macro to be able to contrast something. Thanks to Sean Devlin screencast on the subject.
Scheme
(define (square x)
(* x x))
(define cube
(lambda (x)
(* x x x)))
(define (cubert x)
(cubert-iter 1 x))
(define (cubert-iter guess x)
(if (good-enough? guess x)
guess
(cubert-iter (improve guess x)
x)))
(define (good-enough? guess x)
(< (abs (- (cube guess) x))
.0001))
(define (improve y x)
(/ (+ (/ x
(square y))
(* 2.0 y))
3.0))
Clojure
(defn square [x]
Clojure
(defn square [x]
(* x x)) ;I prefer fn than using the #() macro
(def cube
(fn [x]
(* x x x)))
(defn cubert [x]
(cubert-iter 1 x)) ;Need to reorder before usage or "declare" beforehand
(def good-enough?)
(def improve)
(defn cubert-iter [guess x]
(if (good-enough? guess x)
guess
(cubert-iter (improve guess x)
x)))
(defn good-enough? [guess x]
(< (Math/abs (- (cube guess) x))
0.0001)) ;Uses the thread-first macro to make it a bit different
(defn improve [y x]
(-> x
(/ (square y))
(+ (* 2.0 y))
(/ 3.0)))
2 comments:
Wow didn't know about the screencast!
Thx for sharing!
You might want to use recur for tail recursion for the Clojure examples, otherwise you will blow the stack, given a high enough number of iterations :)
We keep hearing that the JVM will eventually include proper support for tail calls, but it has not happened yet. And Rich (Hickey) took a more risk-averse solution -- with recur -- than the Scala folks, who try and optimize tail-calls for you seamlessly (though now they added @tailrec for verification)
Post a Comment