OMG, this is too much Clojure code for me to handle O.o Alex, you just killed me :) Do you previous Lisp knowledge? or Clojure is your first Lisp? you are so good.
I will spend the next couple of hours studying it. Thanks all, you are awesome. On Dec 6, 12:47 am, Alex Osborne <a...@meshy.org> wrote: > HB <hubaghd...@gmail.com> writes: > > I'm trying to write a function that calculates the length of a list: > > > (defn list-length [col] > > (if col > > (+ 1 (list-length(rest col))) > > 0)) > > > (list-length '(Java, Clojure, Scala)) > > > Upon running it in the REPL, I got the error: > > java.lang.StackOverflowError (test.clj:3) > > > What is going wrong? > > In Clojure (unlike many other lisps) the empty list (), nil and false > are different things. The empty list is "truthy". Try this instead: > > (defn list-length [coll] > (if-let [s (seq coll)] > (+ 1 (list-length (rest s))) > 0)) > > The seq function will return nil on an empty sequence. It's also good > form to capture its output as s, so that if you pass in something that's > not a sequence, for example a hash-map, then it doesn't have to be > converted to a seq twice. > > The above will still blow up with a StackOverflowError on very large > lists because it is not tail-recursive. We can transform it into a > tail-recursive form by passing the count-so-far as an optional argument > (initialized to 0) and using recur for the recursive call: > > (defn list-length > ([coll] (list-length coll 0)) > ([coll n] (if-let [s (seq coll)] > (recur (rest s) (inc n)) > n))) > > That's of course a really common pattern that comes up all the time. So > Clojure provides a higher-level function (reduce) that does the > iteration and recursion for you. So a nicer implementation might be: > > (defn list-length [coll] > (reduce (fn [n x] (inc n)) 0 coll)) > > Of course in practice you should just use the built-in count function > (which is O(1) on most data structures) but I assume this is an > exercise. :-) > > If you're interested in the history behind the decision to make the > empty list truthy, have a look here: > > http://clojure.org/lazy > > In very early (pre 1.0) versions of Clojure your function would have > actually worked as you expected. The change from the Common Lisp model > was made to allow for "fully" lazy sequences. -- 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en