[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Scheme-reports] Automatic delay-force

Here's a possible simplification to R7RS: delay-force can be made
implicit in delay without losing any expressiveness.

Delay-force exists to optimize a specific pattern: (delay (force
...)). Since delay is a macro, it can recognize this pattern, and
apply the optimization automatically. If I understand syntax-rules
literals correctly, this can even be done portably. Instead of being
defined like this:

  (define-syntax delay
    (syntax-rules ()
      ((delay x) (%make-promise (lambda () x)))))

  (define-syntax delay-force
    (syntax-rules ()
      ((delay-force x) (%make-tail-promise (lambda () x)))))

it could be defined like this:

  (define-syntax delay
    (syntax-rules (force)
      ((delay (force x)) (%make-tail-promise (lambda () x)))
      ((delay x) (%make-promise (lambda () x)))))

This makes (delay (force ...)) equivalent to (delay-force ...): it
automatically applies the delay-force optimization everywhere it's
possible, without requiring users to identify and change the call
sites. Thus there is no need for a separate delay-force macro, and it
can be removed.

This would presumably be specified as a space guarantee for (delay
(force ...)), like the guarantee for tail calls but applying more
narrowly. Or it could be omitted from the spec and left to the
discretion of implementors, like all other optimizations.

If constant-space lazy iteration is available only through explicit
delay-force, it makes some sense to standardize it, since it would
otherwise be impossible for portable code to get this behavior on
implementations that support it. But if it's available as an
optimization, portable code can take advantage of it on
implementations that have it, whether or not it's standardized, so the
case for standardizing it is weaker. Its use cases may not be
important enough to include it in the small standard, especially as it
makes the implementation of promises more complex and nonobvious.

If this optimization is included in the standard, delay would be the
only standard macro to recognize a bound identifier (as opposed to
recognizing unbound ones like =>). I don't know if this is

Automatic delay-force is slightly at odds with the extended version of
lazy that Eli Barzilay has argued for, which accepts non-promises as
well as promises (i.e. it lazily coerces its argument to a promise).
Such an operator is useful because it allows users to introduce
laziness without having to keep track of whether it was already
present. But no one wants to write their routine laziness as (delay
(force ...)), so the optimization doesn't make lazy unnecessary.

Scheme-reports mailing list