Hi,

On 16 Nov., 02:31, Ken Wesson <kwess...@gmail.com> wrote:

> Eh. I'd heard first and rest had replaced next. No?

No. This was a misinformation. To elaborate a bit more on the
differences pointed out by Sean:

next returns nil if there are no more items in the sequence, which is
nice to use in if and when statements to test for emptiness. However
in order to be able to return nil the sequence has to be realised.
Otherwise you can't know whether to return nil or not. So next is "non-
lazy of order 1" so to say. To allow full laziness lazy-seq was
introduced. It returns an object which doesn't know directly whether
it's empty, but it knows how to find out, when you ask for it. When
you know call empty? on the lazy-seq you realise the sequence and the
seq call hidden in empty will return most likely a Cons, where first
and rest are just field references, or nil of there are no elements in
the sequence. But you throw this away. Then you call first on the lazy-
seq. first itself calls seq and gets again the now cached Cons. Then
you call rest, which calls seq, which returns the cached Cons. A lot
of indirection going on. If you handle non-seqs like vectors or maps,
you have to replace that with multiple creations of very short-lived
objects. This is even more expensive.

So you can see, that by capturing the return value of the seq call you
can save quite a bit of indirection. Plus seq becomes the identity,
which should be fast.

I did some quick'n'dirty benchmarking and the improvement seems to be
12% for me. Not thaaaat much, but quite a bit for such trivial
changes.

user=> (bench (loop [s (take 10000 (range)) i 0]
                (if (empty? s)
                  i
                  (recur (rest s) (+ i (first s))))))
Evaluation count             : 8100
Execution time mean          : 7,393586 ms  95,0% CI: (7,391431 ms,
7,394906 ms)
Execution time std-deviation : 3,062580 ms  95,0% CI: (3,043205 ms,
3,086849 ms)

Found 2 outliers in 60 samples (3,3333 %)
        low-severe       2 (3,3333 %)
 Variance from outliers : 22,2178 % Variance is moderately inflated by
outliers
nil
user=> (bench (loop [s (seq (take 10000 (range))) i 0]
                (if s
                  (recur (next s) (+ i (first s)))
                  i)))
Evaluation count             : 9840
Execution time mean          : 6,502692 ms  95,0% CI: (6,499507 ms,
6,505352 ms)
Execution time std-deviation : 3,708928 ms  95,0% CI: (3,687700 ms,
3,731890 ms)
nil

Hope that helps.

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

Reply via email to