With just the primitives the R7RS gives us, it is not possible to implement such a requirement. I am currently thinking about what the right primitive concepts are to implement ‘(delay (force ...))’ without the crook ‘delay-force’ or its incarnations ‘stream-lambda’ or ‘stream-let’ in SRFI 41.

Here is a pair of new primitives that make it possible to implement promises properly without delay-force:

Syntax:
(with-tail-mark <key> <value> <expression>)

Procedure:
(call-with-tail-mark <key> <proc>)

The two primitives shall implement the following semantics:

(with-tail-mark <key1> <value> <expression>)

evaluates <key1> and <value>, and then <expression> in tail context, and yields the values yielded by <expression>.

(call-with-tail-mark <key2> <proc>)

is evaluated with the same continuation as (with-tail-mark <key1> <value> <expression>) and <key2> evaluates to the same object (in the sense of eq?) as <key1> evaluated to, <proc> is invoked in tail position with the object <value> evaluated to. Otherwise <proc> is invoked in tail position with #f.

In case, (call-with-tail-mark <key2> <proc>) is evaluated in the context of more than one with-tail-mark form whose keys evaluated to the same object, the innermost with-tail-mark takes precedence.

Examples:

(with-tail-mark 'foo 'bar (call-with-tail-mark 'foo values))

=> bar

(with-tail-mark 'foo 'bar (+ 1 (call-with-tail-mark 'foo values)))

=> #f

(with-tail-mark 'foo 'bar (with-tail-mark 'foo2 'bar2 (call-with-tail-mark 'foo values)))

=> bar

(with-tail-mark 'foo 'bar (with-tail-mark 'foo 'bar2 (call-with-tail-mark 'foo values)))

=> bar2

--

Marc