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 -~----------~----~----~----~------~----~------~--~---