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 clojure@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to