Re: Why I'm getting StackoverflowError?

2010-12-07 Thread Meikel Brandmeyer
Hi,

Am 06.12.2010 um 22:38 schrieb Ken Wesson:

 A reduce that discards one of its arguments (e.g. (reduce (fn [n _]
 (inc n)) coll)) also strikes me as slightly icky. :)

Indeed this would fit in the 5% left. Anyway: I can't remember writing a 
function with accumulator not using the other argument in production code.

Sincerely
Meikel

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread nickik
 What is the difference between rest and next?

This has to do with lazyness. I wrote an answer to that on
stackoverflow.

http://stackoverflow.com/questions/4288476/clojure-rest-vs-next

Should answer everthing.

 I'm confused, should I use empty? or not? when to use it?
 Why Clojure decided to handle an empty list as a not false? this is a
 big (if not) departure from Common Lisp?

The list is not nil because why should a empty list be nil but not en
empty set/map/vector. To make all of them nil would probebly make
other problems (100% sure we didn't do that would be intressting to
know).

So a common pattern is to just call seq or empty on the collection to
be sure that the empty list dosn't pass as true.
(On of the constant pain points when you work on books that are
written in CL or Scheme)


Next let my talk about the Stackoverflow:

If you use empty? you don't have one on small list but if the get
bigger you run in problems because you have to many nessted stacks.

The easy (and good) solution is to pass the running result onlong the
way. This can be done in diffrent ways.

First the CL Style where you creat a new function in you function that
then does all the work. (from
Ken Wesson)

(defn list-length [coll]
  (let [ll (fn [n s]
 (if s
   (recur (inc n) (next s))
   n))]
(ll 0 (seq coll

I don't really like this because the core logic is somwhat hidden.

Then we could use arity functions. (Alex Osborne)

(defn list-length
  ([coll]   (list-length coll 0))
  ([coll n] (if-let [s (seq coll)]
 (recur (rest s) (inc n))
  n)))

This is nice style in my opinion but I would do it like this:

(defn list-lenght [coll]
   (loop [coll coll n 0]
  (if (empty? coll)
  n
  (recur (rest coll) (inc n)

or with seq instead of empty?

(defn list-lenght [coll]
   (loop [coll coll n 0]
  (if (seq coll)
  (recur (rest coll) (inc n))
  n)))

Hope that helps a little.

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread Ken Wesson
On Mon, Dec 6, 2010 at 4:02 AM, nickik nick...@gmail.com wrote:
 The easy (and good) solution is to pass the running result onlong the
 way. This can be done in diffrent ways.

 First the CL Style where you creat a new function in you function that
 then does all the work. (from
 Ken Wesson)

 (defn list-length [coll]
  (let [ll (fn [n s]
             (if s
               (recur (inc n) (next s))
               n))]
    (ll 0 (seq coll

 I don't really like this because the core logic is somwhat hidden.

???

 Then we could use arity functions. (Alex Osborne)

    (defn list-length
      ([coll]   (list-length coll 0))
      ([coll n] (if-let [s (seq coll)]
                     (recur (rest s) (inc n))
                      n)))

 This is nice style in my opinion

Not in mine -- it exposes a public API of
list-length-plus-some-integer that a) doesn't make much sense and b)
is unlikely to be supported, since the implementation could be changed
to one that doesn't expose this. Of course sometimes a user wants to
add something to a length of a seq and then they could get a slight
speedup by using (list-length s n) instead of (+ n (list-length s)),
but that is c) premature optimization in the typical case.

 but I would do it like this:

 (defn list-lenght [coll]
   (loop [coll coll n 0]
      (if (empty? coll)
          n
          (recur (rest coll) (inc n)

 or with seq instead of empty?

 (defn list-lenght [coll]
   (loop [coll coll n 0]
      (if (seq coll)
          (recur (rest coll) (inc n))
          n)))

 Hope that helps a little.

Why not

(defn list-length [coll]
  (let [s (seq coll)]
    (loop [s s n 0]
       (if s
         (recur (next s) (inc n))
         n

? This may be slightly more efficient at no cost in clarity.

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread HB
I didn't expect my question would initiate such a wonderful
discussion, I'm speechless.
Thank you all guys, you are amazing.
Alex, your posts killed in a very good way :)
It was really helpful to morph the code and transform it.

On Dec 6, 11:14 am, Ken Wesson kwess...@gmail.com wrote:
 On Mon, Dec 6, 2010 at 4:02 AM, nickik nick...@gmail.com wrote:
  The easy (and good) solution is to pass the running result onlong the
  way. This can be done in diffrent ways.

  First the CL Style where you creat a new function in you function that
  then does all the work. (from
  Ken Wesson)

  (defn list-length [coll]
   (let [ll (fn [n s]
              (if s
                (recur (inc n) (next s))
                n))]
     (ll 0 (seq coll

  I don't really like this because the core logic is somwhat hidden.

 ???

  Then we could use arity functions. (Alex Osborne)

     (defn list-length
       ([coll]   (list-length coll 0))
       ([coll n] (if-let [s (seq coll)]
                      (recur (rest s) (inc n))
                       n)))

  This is nice style in my opinion

 Not in mine -- it exposes a public API of
 list-length-plus-some-integer that a) doesn't make much sense and b)
 is unlikely to be supported, since the implementation could be changed
 to one that doesn't expose this. Of course sometimes a user wants to
 add something to a length of a seq and then they could get a slight
 speedup by using (list-length s n) instead of (+ n (list-length s)),
 but that is c) premature optimization in the typical case.





  but I would do it like this:

  (defn list-lenght [coll]
    (loop [coll coll n 0]
       (if (empty? coll)
           n
           (recur (rest coll) (inc n)

  or with seq instead of empty?

  (defn list-lenght [coll]
    (loop [coll coll n 0]
       (if (seq coll)
           (recur (rest coll) (inc n))
           n)))

  Hope that helps a little.

 Why not

 (defn list-length [coll]
   (let [s (seq coll)]
     (loop [s s n 0]
        (if s
          (recur (next s) (inc n))
          n

 ? This may be slightly more efficient at no cost in clarity.

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread Meikel Brandmeyer
Hi,

Am 06.12.2010 um 10:14 schrieb Ken Wesson:

 Then we could use arity functions. (Alex Osborne)
 
(defn list-length
  ([coll]   (list-length coll 0))
  ([coll n] (if-let [s (seq coll)]
 (recur (rest s) (inc n))
  n)))
 
 This is nice style in my opinion
 
 Not in mine -- it exposes a public API of
 list-length-plus-some-integer that a) doesn't make much sense and b)
 is unlikely to be supported, since the implementation could be changed
 to one that doesn't expose this.

One can easily hide the second arity from the contract.

(defn list-length
  {:arglists '([coll])}
  ...)

Sincerely
Meikel

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread Ken Wesson
On Mon, Dec 6, 2010 at 5:19 AM, Meikel Brandmeyer m...@kotka.de wrote:
 Hi,

 Am 06.12.2010 um 10:14 schrieb Ken Wesson:

 Then we could use arity functions. (Alex Osborne)

    (defn list-length
      ([coll]   (list-length coll 0))
      ([coll n] (if-let [s (seq coll)]
                     (recur (rest s) (inc n))
                      n)))

 This is nice style in my opinion

 Not in mine -- it exposes a public API of
 list-length-plus-some-integer that a) doesn't make much sense and b)
 is unlikely to be supported, since the implementation could be changed
 to one that doesn't expose this.

 One can easily hide the second arity from the contract.

 (defn list-length
  {:arglists '([coll])}
  ...)

Won't that make the internal recursive call fail though?

And even if not -- ugly IMO. :)

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread nickik
On Dec 6, 11:40 am, Ken Wesson kwess...@gmail.com wrote:
 Won't that make the internal recursive call fail though?

 And even if not -- ugly IMO. :)

Agree. Why make something slower and more ugly?

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


Re: Why I'm getting StackoverflowError?

2010-12-06 Thread Meikel Brandmeyer
Hi,

Am 06.12.2010 um 11:40 schrieb Ken Wesson:

 Won't that make the internal recursive call fail though?

No. Because the metadata is just documentation.

 And even if not -- ugly IMO. :)

Tastes vary. I prefer this over a second toplevel function named foo-aux or the 
like. I also prefer it over a nested let. That said, I hardly ever run into 
this pattern. Maybe because I use reduce in 95% of such cases.

Sincerely
Meikel

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


Why I'm getting StackoverflowError?

2010-12-05 Thread HB
Hi,
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?

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Danny Woods
On Dec 5, 9:52 pm, HB hubaghd...@gmail.com wrote:
 Hi,
 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?

Unlike Common Lisp, the empty list is not a false value in Clojure, so
your condition is always true.

If you change your test to (if (empty? col) ... ), all should be good.

Cheers,
Danny.

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Robert McIntyre
Your function never actually ends  because even the empty list
evaluates to true :)

rlm.dna-melting (if (rest '()) true false)
true

rlm.dna-melting (if (next '()) true false)
false

so, changing your list length function to use next will work

rlm.dna-melting (defn list-length [col] (if col (+ 1 (list-length
(next col))) 0))
#'rlm.dna-melting/list-length
rlm.dna-melting (list-length (range 5))
5

hope that helps,
--Robert McIntyre

On Sun, Dec 5, 2010 at 4:52 PM, HB hubaghd...@gmail.com wrote:
 Hi,
 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?

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

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Ken Wesson
On Sun, Dec 5, 2010 at 5:16 PM, Robert McIntyre r...@mit.edu wrote:
 Your function never actually ends  because even the empty list
 evaluates to true :)

 rlm.dna-melting (if (rest '()) true false)
 true

 rlm.dna-melting (if (next '()) true false)
 false

 so, changing your list length function to use next will work

 rlm.dna-melting (defn list-length [col] (if col (+ 1 (list-length
 (next col))) 0))
 #'rlm.dna-melting/list-length
 rlm.dna-melting (list-length (range 5))
 5

 hope that helps,
 --Robert McIntyre

Yeah, but

user= (list-length ())
1

:)

And the original code will still bomb on long enough lists. How about:

(defn list-length [coll]
  (let [ll (fn [n s]
 (if s
   (recur (inc n) (next s))
   n))]
(ll 0 (seq coll

user= (list-length ())
0
user= (list-length (range 5))
5
user= (list-length (range 1000))
1000

The inner function takes a second argument that is the count-so-far.
This is so that the recursion can be turned into a tail call. As you
can see, no stack overflow even on a very long input.

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread HB
What is the difference between rest and next?

I'm confused, should I use empty? or not? when to use it?

Robert,
Your code is working but if I use empty? , it returns 0 instead of the
actual count.
Why?

Why Clojure decided to handle an empty list as a not false? this is a
big (if not) departure from Common Lisp?

Thank you guys for your help and time.

On Dec 6, 12:16 am, Robert McIntyre r...@mit.edu wrote:
 Your function never actually ends  because even the empty list
 evaluates to true :)

 rlm.dna-melting (if (rest '()) true false)
 true

 rlm.dna-melting (if (next '()) true false)
 false

 so, changing your list length function to use next will work

 rlm.dna-melting (defn list-length [col] (if col (+ 1 (list-length
 (next col))) 0))
 #'rlm.dna-melting/list-length
 rlm.dna-melting (list-length (range 5))
 5

 hope that helps,
 --Robert McIntyre



 On Sun, Dec 5, 2010 at 4:52 PM, HB hubaghd...@gmail.com wrote:
  Hi,
  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?

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

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Alex Osborne
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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Nadeem Vawda
In Clojure, empty sequences are not considered logically false, so
your code continues going after reducing col to an empty list.  You
need to explicitly check whether the collection is empty, like so:

(defn list-length [col]
  (if (empty? col)
0
(+ 1 (list-length (rest col)

Cheers,
Nadeem

On Sun, Dec 5, 2010 at 11:52 PM, HB hubaghd...@gmail.com wrote:
 Hi,
 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?

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

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread HB
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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread HB
Ken  Alex,
Why you aren't calling empty? when you want to check if a collection
is empty?

Isn't (if s) supposed to return true if s is empty ?

On Dec 6, 12:27 am, Ken Wesson kwess...@gmail.com wrote:
 On Sun, Dec 5, 2010 at 5:16 PM, Robert McIntyre r...@mit.edu wrote:
  Your function never actually ends  because even the empty list
  evaluates to true :)

  rlm.dna-melting (if (rest '()) true false)
  true

  rlm.dna-melting (if (next '()) true false)
  false

  so, changing your list length function to use next will work

  rlm.dna-melting (defn list-length [col] (if col (+ 1 (list-length
  (next col))) 0))
  #'rlm.dna-melting/list-length
  rlm.dna-melting (list-length (range 5))
  5

  hope that helps,
  --Robert McIntyre

 Yeah, but

 user= (list-length ())
 1

 :)

 And the original code will still bomb on long enough lists. How about:

 (defn list-length [coll]
   (let [ll (fn [n s]
              (if s
                (recur (inc n) (next s))
                n))]
     (ll 0 (seq coll

 user= (list-length ())
 0
 user= (list-length (range 5))
 5
 user= (list-length (range 1000))
 1000

 The inner function takes a second argument that is the count-so-far.
 This is so that the recursion can be turned into a tail call. As you
 can see, no stack overflow even on a very long input.

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Ken Wesson
On Sun, Dec 5, 2010 at 6:55 PM, HB hubaghd...@gmail.com wrote:
 Ken  Alex,
 Why you aren't calling empty? when you want to check if a collection
 is empty?

 Isn't (if s) supposed to return true if s is empty ?

If coll is empty, (seq coll) and (next coll) are both nil, which is
logical false.

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Alex Osborne
HB hubaghd...@gmail.com writes:

 OMG, this is too much Clojure code for me to handle O.o
 Alex, you just killed me :)

Hehe, sorry.  Just thought it might be helpful to show the progression
of dealing with all the little edge cases.

It perhaps looks much more fiddly, but you're doing more there than
common lisp:  sequences are an abstraction, so you can use 
that function on any collection type, not just lists.

Laziness can also be incredibly useful (but maybe not for this
particular example).  I often find myself and colleagues having to
totally restructure report generating Ruby/Perl/Python scripts because
they eagerly loaded everything into memory.  Usually the natural way
they would have been written in Clojure would have avoided the problem.

Of course you don't get those benefits completely free.  A little extra
up front complexity which then makes things so much simpler when it
comes to polymorphism, concurrency or larger than memory data sets.

For that reason I don't see Clojure replacing say Ruby or Python for small
database backed webapps where you don't have to worry about that sort of
thing.  It's a different niche.

 Do you previous Lisp knowledge? or Clojure is your first Lisp? you are
 so good.

Clojure is the first lisp I really learned properly.  Before Clojure
I'd very briefly played with Common Lisp and some lisps as
configuration (Emacs, Sawfish etc), but never really got too far beyond
hello world.

I was however fairly fluent in C, Python, Java and Haskell which I think
probably helped a lot:

* C: data structures, how things work under the hood, concurrency
  (locks, semaphores, pthreads, openmp)

* Python: dynamic typing, first class functions, GC, REPL

* Java: JVM tools and standard library

* Haskell: functional programming, immutability, lazy evaluation,
  destructuring.


So learning Clojure for me was basically adding these on top:

* Lisp syntax

* Macros

* Clojure state management (vars, refs, atoms, agents etc)

* Concurrency features (pmap, future, promise etc)

* Clojure-style datatypes/protocols


I think people with a Common Lisp background might actually have a
harder time.  The syntax might make it feel similar, but Clojure is
really in many ways a very different language.

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


Re: Why I'm getting StackoverflowError?

2010-12-05 Thread Alex Osborne
HB hubaghd...@gmail.com writes:

 Ken  Alex,
 Why you aren't calling empty? when you want to check if a collection
 is empty?

Here's the definition of empty? from clojure/core.clj:

(defn empty?
  Returns true if coll has no items - same as (not (seq coll)).
  Please use the idiom (seq x) rather than (not (empty? x))
  [coll] (not (seq coll)))

So this:

(if (not (empty? coll)) ...)

is really:

(if (not (not (seq coll))) ...)

;-)

The other reason I do it that way, is that for a non-sequence collection
(like a hash table or Java array), seq will convert it into a sequence.
The premature optimizer in me likes to avoid that conversion happening
twice -- otherwise both the empty? and rest calls will call seq to
convert the collection into a sequence.

Hence this form:

(if-let [s (seq coll)] ...)

Which is just a shorthand for:

(let [s (seq coll)]
  (if s ...))

In reality it probably makes no practical difference of course.  I'm
just in the habit of it.

The best way is to use reduce and let it take care of all the details
for you. ;-)

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