[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Scheme-reports] Formal Comment: what is the required behavior of 'lazy'?
10 minutes ago, Alex Shinn wrote:
> On Fri, Jun 29, 2012 at 10:15 AM, Eli Barzilay <eli@x> wrote:
> > A few minutes ago, Alex Shinn wrote:
> >> On Fri, Jun 29, 2012 at 9:32 AM, Eli Barzilay <eli@x> wrote:
> >> > Yesterday, Alex Shinn wrote:
> >> >> On Thu, Jun 28, 2012 at 1:39 AM, Eli Barzilay <eli@x> wrote:
> >> >> > A few minutes ago, Alex Shinn wrote:
> >> >> >> On Thu, Jun 28, 2012 at 1:12 AM, Eli Barzilay <eli@x> wrote:
> >> >> >> > With both present, there is an easy way to remember which one to
> >> >> >> > choose: `lazy'.
> >> >> >>
> >> >> >> `delay' is useful for many other things besides streams, where
> >> >> >> `lazy' would not be applicable.
> >> >> >
> >> >> > For example...?
> >> >>
> >> >> Do you honestly doubt that the concept of delayed
> >> >> evaluation has uses outside of a stream?
> >> >>
> >> >> In the most basic case it serves as a simple cache:
> >> >>
> >> >> (let ((x (delay <expr>)))
> >> >> ...
> >> >> (if ... (force x) ...)
> >> >> ...
> >> >> (if ... (force x) ...))
> >> >>
> >> >> Lazy doesn't work here.
> >> >
> >> > *Some* `lazy's do. I missed the fact that you've crippled `lazy'.
> >> > (It's an odd decision that not only makes it a more limited tool, it also
> >> > contradicts a dynamically typed language.)
> >> I'm only aware of one definition of `lazy' - the one from srfi-45
> >> and used by srfi-41. If there is an alternative definition I'd like
> >> to know.
> > It's one that does not require to be used with a promise.
> > $ racket
> > Welcome to Racket v5.2.1.
> > -> (lazy 1)
> > #<promise:stdin:1:0>
> > -> (force ^)
> > 1
> > -> (force (lazy (lazy 2)))
> > 2
> (I assume Racket's repl binds ^ to the last result)
> The standard effectively allows but does not require this extension
> to lazy.
I don't know how that's the case -- I don't remember the exact wording
(and don't have the document now), but I remember it saying that
`lazy' should be used only on promises. That's the crippling that I
was referring too, and if that's not the case it would be a good idea
to clarify that.
> However, that's not really the point here. Lazy is still
> semantically difference from delay, because forcing a delay does not
> repeatedly force the result.
Yes, that is a difference between them. I should revise my comment
then and say that `lazy' is good for many situations where you want to
delay some computation, and therefore you don't care about
differentiating a promise for a value from a promise holding a promise
for the same value.
> The transformation described by Wadler for converting a strict
> language into a lazy one naturally uses delay and force as a pair,
> and results in some compositions of delay and force, in addition to
> isolated delays.
That's not the only way to implement a lazy language -- and IIRC, the
conversion used in that paper is suitable for a strict language that
has some lazy definitions in it, and it suffers from over-strictness
in the bodies of lazy functions unless these bodies have only calls to
lazy functions themselves. In any case, Lazy Racket implements
laziness in a somewhat different way, but neither implementation
should be related to the meaning of the `lazy' form. The bottom line
in terms of understanding it is that `lazy' composes well with other
promises and effectively creates an alias of the input promise. By
"an alias" I mean that the resulting promise is indistinguishable from
the original one: specifically, there is no loss of tail-position-ness
and there is no potential memory leakage due to such a loss. A name
like "composable promise" is therefore much more mnemonic of the form,
if I was shooting for a meaningful name. In this light, where
compositionality is the main feature of `lazy', and this
compositionality is lost when you use (delay (force ...)), it is clear
(or should be clear, IMO) why `delay-force' is a bad name. It refers
to what it is "like" in a sort-of-*but* kind of way, which makes it a
bad analogy to a broken implementation.
> Lazy was introduced because existing implementations leak space in
> the delay+force compositions.
(Leak space is the byproduct of losing tail-ness.)
> However, the distinction is still useful, gives a finer grain of
> control over when promises are forced, and allows for cleaner type
Yes, "cleaner type inference" was the motivation that made the srfi
author stick to the requirement, and my earlier comment is that this
kind of cleanliness is not needed in a dynamically typed language. It
wouldn't hurt to add it, of course, but the resulting cost is that you
need to keep track of whether your expression will be a promise or an
actual value, and based on that you need to choose `lazy' or `delay'
-- this means that coding with the requirement for only promises in a
`lazy' form is harder, and contradicts the rest of the language.
Furthermore, the only purpose of `eager' in the srfi is to accomodate
the types: in a case where you need to "lift" a value to a promise but
you don't want the overhead of a redundant promise. In an
implementation that allows `lazy' over values, there is simply no need
for such a construct -- which is another way which simplifies the
> Moreover, replacing delay with a permissive lazy would break
> existing programs.
(Yes, with double-delays.)
> Thus we need both in the standard, and the naming we've provided
> shows the relation clearly between the two while preserving
> consistency with R5RS and Wadler's paper.
See above about my unmoved opinion on the name, and more than that, I
don't see how `delay-force' is supposed to be more consistent with
R5RS. `lazy' is doing something different from `delay' and that's it.
The current name is like calling a numeric identity function
> I understand we can't make everyone happy here, but I don't the the
> WG should spend time revisiting this naming yet again. If you'd
> like to file a formal comment it will stand as a more visible
> objection, otherwise we'll try to be clear in the non-normative
> rationales that there was contention on this name.
Do whatever you want with this. I do not intend to make a formal
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!
Scheme-reports mailing list