Saturday, 20 December 2008
Improving my Clojure style
P22 on my list of problems seems simple, "Create a list containing all integers within a given range.". My first naive (a polite way of saying crap!) implementation is shown below:
The pattern
Much better, so now I can do:
Incidentally, this fixes another issue. If I'm using
Talking on #Clojure, I got a much better solution from kotarak + poiuyt
Much more concise!
Using
(defn my-range-crap [start end]
((fn [x y accum]
(if (= x y)
(concat accum (list x))
(recur (inc x) y (concat accum (list x))))) start end nil))
The pattern
(concat accum (list x))
is very ugly. There's a much simpler way of doing that using conj
. From the documentation.(conj coll item)
Conj[oin]. Returns a new collection with the item 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type.
Much better, so now I can do:
(defn my-range-not-quite-as-crap [start end]
((fn [x y accum]
(if (= x y)
(conj accum x)
(recur (inc x) y (conj accum x)))) start end nil))
Incidentally, this fixes another issue. If I'm using
concat
then (my-range-crap 1 50000)
blows the stack. Not good. Using conj
fixes the problem.Talking on #Clojure, I got a much better solution from kotarak + poiuyt
(defn much-better-range
[start end]
(when (< start end)
(lazy-cons start (much-better-range (inc start) end))))
Much more concise!
Using
lazy-cons
means the recursion can be explicit and that you get rid of the problems with stack overflow (it only evaluates when you need it).Labels: clojure
Subscribe to Posts [Atom]