[plt-scheme] Where to introduce the functionality: a function or a macro?

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Sun Dec 2 18:53:38 EST 2007

Grant Rettke wrote:
> The macro at the end of this email allows the user to define processes
> that can abort and continue using continuations.
> 
> Here is an example:
> 
> (define cond1 #f)
> (define cond2 #f)
> (define-process (foo-process arg1 arg2)
>   (printf "Starting the proceess with args: ~a ~a~n" arg1 arg2)
>   (mark)
>   (if cond1
>       {printf "Condition 1 met, proceding~n"}
>       {return "Condition 1 not, aborting"})
>   (mark)
>   (if cond2
>       {printf "Condition 2 met, proceding~n"}
>       {return "Condition 2 not, aborting"})
>   (let ([result (+ arg1 arg2)])
>     (begin
>       (mark)
>       (return result))))
> 
> 'mark' sets a point from which to continue and 'return' aborts the process.
> 
> 'mark' is implemented as a function. This behaves as expected, but I
> don't think that this is the right way to do it because when the
> continuation is called again, it will really continue at the end of
> the 'mark' function and then return to the expected place in the impl
> function. So this gets the desired behavior, but it really ought not
> continue from within the mark function.
> 
> How do I implement 'mark' so that the continuation will be set
> directly within the impl function?

The invocation of a procedure does not add to the continuation. Only the 
evaluation of non-tail expressions (procedure arguments, test expression 
of a conditional, etc) adds to the continuation. So the continuation 
captured by 'mark' doesn't include any part of the 'mark' procedure, 
because the continuation is captured (using 'let/cc') in tail position.

Ryan

> (define-syntax define-process
>   (lambda (stx)
>     (define gen-id ; Source: _TSPL_3rd_Ed_ by Kent Dybvig
>       (lambda (template-id . args)
>         (datum->syntax-object
>          template-id
>          (string->symbol
>           (apply
>            string-append
>            (map
>             (lambda (x)
>               (if (string? x) x
>                   (symbol->string (syntax-object->datum x))))
>             args))))))
>     (syntax-case stx ()
>       ((_) (raise-syntax-error #f "a process requires a name and at
> least one command" stx))
>       ((_ (name args ...)) (raise-syntax-error #f "a process requires
> at least one command" stx))
>       ((_ (name args ...) command commands ...)
>        (with-syntax ([constructor-name (gen-id (syntax name) "make-"
> (syntax name))]
>                      [return (syntax-local-introduce (syntax return))]
>                      [mark (syntax-local-introduce (syntax mark))])
>          (syntax
>           (define (constructor-name args ...)
>             (define (mark)
>               (let/cc resume-here (set! impl resume-here)))
>             (define (name)
>               (call/cc impl))
>             (define (impl return)
>               (begin
>                 command
>                 commands ...))
>             name)))))))
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.