[plt-scheme] `shared' syntax confusing

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Nov 10 14:58:45 EST 2008

At Tue, 11 Nov 2008 02:24:20 +0900, Alex Shinn wrote:
> What about post-processing the values instead of predicting
> the shape?  The following seems to work fine for me:
>   (define-syntax shared
>     (syntax-rules ()
>       ((shared ((var expr) ...) body ...)
>        (shared-build () ((var expr) ...) body ...))))
>   (define-syntax shared-build
>     (syntax-rules ()
>       ((shared-build ((var tmp expr) ...) ((var2 expr2) rest ...) body ...)
>        (shared-build ((var tmp expr) ... (var2 tmp2 expr2)) (rest ...) body 
> ...))
>       ((shared-build ((var tmp expr) ...) () body ...)
>        (let ((tmp (make-placeholder #f)) ...)
>          (let ((var #f) ...)
>            (set! var (let-syntax
>                          ((var (make-set!-transformer
>                                 (lambda (stx)
>                                   (syntax-case stx (set!)
>                                     ((set! id val) #'(set! id val))
>                                     (id #'tmp)))))
>                           ...)
>                        expr)) ...
>            (placeholder-set! tmp var) ...
>            (set! var (make-reader-graph var)) ...
>            body ...)))))

There are trade-offs in what you can express with this approach and the
one we're using.

Your approach would automatically work with `list*' --- or with any
function that does not inspect its arguments and constructs a result
using only pairs, vectors, and boxes.

But it exposes the intermediate placeholder value, as in

 (define-struct a (x))
 (shared ([a (make-a a)])
   (a-x a))

Also, it doesn't take advantage of the ability to mutate some values,
such as vectors, as in

 (shared ([a (vector (make-a a))])

or mutable structs, as in

 (define-struct b (x) #:mutable)
 (shared ([b (make-b b)])
   (b-x b))

I can't say whether either of these drawbacks is actually a significant
problem. The `shared' in `scheme/base' is designed to produce
`#<undefined>', though, where it might otherwise have to expose
placeholders (to avoid expose implementation details), and it works
with examples that exploit mutation (mainly to preserve compatibility
with the pre-4.0 `shared', which always used mutation).

In any case, I've added `list*' and `append' support to `shared' in
`scheme/base'. (For both of our approaches, `append' works only with
graph references within its final argument.)


Posted on the users mailing list.