2008/9/30 Chouser <[EMAIL PROTECTED]>
>
> remove-if uses "regular" recursion, but because the JVM does not
> optimize away tail calls the way Common Lisp (usually) does, this
> could fail for very long lists. However, if you just replace "cons"
> with "lazy-cons" and the other recursive call with "recur", you'll
> have a beautiful lazy sequence function that will never blow the call
> stack.
>
lazy-cons rocks. remove-if with when-let and lazy-cons:
(defn remove-if
[pred lst]
(when-let [f & r] lst
(if (pred f)
(recur pred r)
(lazy-cons f (remove-if pred r)))))
For count-instances, I think I prefer to use "imperative" style, like so:
(defn count-instances [obj lsts]
(let [data (reduce concat lsts)
matches (filter #(= obj %) data)]
(reduce + (map #(if % 1 0) matches))))
>
> I'm sure you've noticed that Graham is taking some pains to make
> tail-recusive versions of his functions. In general to take advantage
> of this you'll want to use "recur" instead of the tail call.
>
> It's more idiomatic (and more succinct!) to say (if (seq lst) ...)
> than (if (nil? lst) nil ...) Also better to use (let [tri (fn [c n]
> ...)] (tri 0 n)) than to have a defn nested inside another defn, since
> the inner defn is still defining a namespace-global name, even though
> it's nested.
>
In the triangle case, I think loop/recur is clearer:
(defn triangle
[n] (loop [c 0 n n]
(if (zero? n)
c
(recur (+ n c) (- n 1)))))
Alexander
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---