_Tail_ _tail_ This collection provides one file: _tail.ss_: special forms for preserving and destroying tail position This library provides a syntax for capturing a continuation and binding it to a variable that, when applied, evaluates its subexpression in tail position with respect to its parent expression. It also contains a utility for evaluating an expression in a guaranteed non-tail context. ====================================================================== > (let-tail-continuation k body1 body2 ...) > (let/tc k body1 body2 ...) A syntax for capturing a continuation a binding it to the syntactic form `k' that accepts a single argument expression. The distinguishing feature of _let/tc_ is that an application of a_let/tc_-bound continuation is a syntactic form that evaluates its argument in tail position with respect to the entire _let/tc_ expression. Note that this means the argument expression is evaluated in the captured continuation, i.e., after the jump occurs. This has important consequences for side effects performed by the argument expression. See the examples for a demonstration. The syntactic form `k' is in scope for the evaluation of the body expressions. It accepts exactly one argument expression. Note also that continuations captured by _let/tc_ receive exactly one value if invoked via the syntactic form `k', but may receive any number of values if evaluation of the body does not invoke the captured continuation. > (push-begin e1 e2 ...) A syntax for evaluating a sequence of expressions, like Scheme's primitive BEGIN, but without preserving tail context. In particular, the last expression of _push-begin_ is NOT in tail position with respect to the containing expression. The value of a _push-begin_ expression, like BEGIN, is the value of the last expression in the sequence. The expressions of a _push-begin_ may evaluate to multiple values (or no values). ====================================================================== EXAMPLES ------------------------------------------------------------- (define (current-continuation-mark-list key-v) (continuation-mark-set->list (current-continuation-marks) key-v)) (define (countdown n) (with-continuation-mark 'countdown n (let/ec return (if (zero? n) (return (current-continuation-mark-list 'countdown)) (return (countdown (sub1 n))))))) > (countdown 10) (0 1 2 3 4 5 6 7 8 9 10) (define (countdown* n) (with-continuation-mark 'countdown n (let/tc return (if (zero? n) (return (current-continuation-mark-list 'countdown)) (return (countdown* (sub1 n))))))) > (countdown 10) (0) ;; The argument to a let/tc continuation is evaluated after the jump ;; occurs. > (with-continuation-mark 'jump 'after (let/ec k (with-continuation-mark 'jump 'before (k (current-continuation-mark-list 'jump))))) (before) > (with-continuation-mark 'jump 'after (let/tc k (with-continuation-mark 'jump 'before (k (current-continuation-mark-list 'jump))))) (after) > (with-handlers ([exn? (lambda (exn) 'uncaught)]) (let/ec k (with-handlers ([exn? (lambda (exn) 'caught)]) (k (error 'stop))))) caught > (with-handlers ([exn? (lambda (exn) 'uncaught)]) (let/tc k (with-handlers ([exn? (lambda (exn) 'caught)]) (k (error 'stop))))) uncaught