"Vinay D.E" <devi...@gmail.com> writes:

> I am a newbie and was doing some exercises when I ran across something that 
> I don't understand.
> I am trying to count the number of elements in an array less than 100.
>
> My first attempt didn't work. The counter returns 0
>
> (let [a (atom 0)
>       i (take-while (fn[x] (swap! a inc) (< x 100))  [1 2 3 4 5])]
>   [@a i])  => [0 (1 2 3 4 5)]

The primary concrete problem is laziness, but fundamentally this sort of
mutable-imperative algorithm doesn't play nice with Clojure's core
features.

The sequence returned by `take-while` is lazy, and none of the function
applications required to generate that sequence actually happen until
something forces evaluation of the sequence elements.  So when you get
the result of `[@a i]` what happens is:

  (1) `@a` is evaluated; nothing else has actually happened yet, so the
      result is still the initial value of `0`.

  (2) `i` is evaluated; now the sequence is forced and generated, and as
      a side-effect the atom is updated.

Instead of depending on mutating side-effects to do these sorts of
calculations, most of the Clojure standard library assumes that you'll
be working with (largely) pure functions which operate primarily in
terms of their parameters and return values.  As an aside, you probably
wanted `filter` instead of `take-while` even for what you were trying to
do in the first place -- you should be able to figure out the difference
from the docs.  So, using pure functions, we can something as simple as:

  (count (filter #(< x 100) input-sequence))

HTH,

-Marshall

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