On Mon, Sep 3, 2012 at 1:58 PM, Stephen Compall
<stephen.comp...@gmail.com> wrote:
>> I would have hoped that would be guaranteed
>
> Nevertheless, by declaring "pred must be free of side-effects",
> `take-while' is refusing to make that promise, among many others.

It seems like a leap to go from pred being free of side-effects to
refusing to make *that* promise. If the reason that pred must be free
of side-effects that take-while is *thereby* free to call pred on the
elements of coll in arbitrary order then actually only *some*
side-effects need to be banned. (Maybe you want to track how many
times pred has been called---that's a side effect but it shouldn't
interfere with pred's being called more than strictly necessary for
take-while to get the right answer, since, after all, if pred is
called more than is strictly necessary, that's exactly what you wanted
to know.) And in refusing to make that promise, take-while is also
doing *more* than just requiring that pred be free of (some)
side-effects, it's also saying that take-while *itself* (i.e., *not*
'first') reserves the right to have the side-effecty function of
forcing the computation of *arbitrary* amounts of a lazy sequence.

Side note: the concept of *pred*, specifically, being free of
side-effects seems underdetermined. Is (fn [f] (even? (f))) free of
side-effects? It is iff f is. What if I pass in, not the pure function
f, but rather the impure function (memoize f)? (memoize f) isn't
*visibly* side-effecty to its caller (the way some Haskell people are
willing to sell their souls and say, "well, you can use
unsafePerformIO as long as *you* know it's safe..."), but it isn't
side-effect-free sensu stricto.

> In general, you may not assume that more elements of a lazy sequence
> than you need will not be computed.  I exempt `reductions', `iterate',
> and any sequences derived from those in my own practice; you may be more
> or less comfortable with such exemptions.
>
> user=> (first (map print [1 2 3 4]))
> 1234nil
> user=> (first (map print '(1 2 3 4)))
> 1nil

I'm aware of seq chunking; it seems tangential to the main concern
here. The following two questions are distinct:

- will calling "first" on a lazy seq cause more than just its first
element to be computed?
- will take-while cause more of a lazy seq to be realized than is
present in its output *because it calls pred on arbitrary elements of
the seq*?

Of course take-while might cause more of a lazy seq to be realized
than is present in its output because of seq chunking. But I'd *hope*
that it wouldn't exacerbate that by reserving the right to work like,
say, this, where n is the largest number of elements of a seq calling
first might compute:

1. Realize the first 1000n elements of a seq, retaining them in memory.
2. Call pred on those elements in reverse order.
3. If pred was true for all of them, realize the next 1000n elements,
etc., otherwise return a lazy seq of the first stretch of elements for
which pred returned true.

That admittedly would be insane, but if pred is free of side-effects
(and computing the elements of the collection is also free of
side-effects) it would be correct.

-- 
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks,
which may be sweet, aromatic, fermented or spirit-based. ... Family
and social life also offer numerous other occasions to consume drinks
for pleasure." [Larousse, "Drink" entry]

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