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

Reply via email to