[plt-scheme] `shared' syntax confusing

From: Alex Shinn (alexshinn at gmail.com)
Date: Mon Nov 10 02:14:41 EST 2008


I was somewhat surprised that the expression

    (shared ((x (list* 1 2 3 x))) x)

did not patch the `x' in the body of the `list*'.

The manual is not particularly enlightening:

    (shared ([id expr] ...) expr)

    Like letrec, but when an expr next to an id is a cons,
    list, vector, quasiquoted expression, or make-structid
    from a define-struct, the expr can refer directly to any
    id, not just ids defined earlier. Thus, shared can be
    used to create cyclic data structures.

I think it's trying to say that if the binding `expr's are a
list whose car is one of the listed identifiers, then any of
the arguments may directly refer to any `id', but _not_ use
an `id' inside another expression.  Which is not quite
correct, because `expr' can contain directly nested
references to other constructors, so that

    (shared ((x (cons 1 (cons 2 x)))) x)
    => #0=(1 2 . #0#)

but not references nested inside other expressions

    (shared ((x (cons 1 (if #t x x)))) x)
    => (1 . #<undefined>)

Why the limitation?  It seems very unintuitive, and there
are useful graphs that can't be represented this way.

And if you are going to have this limitation, why is the
line drawn at the listed forms?  It's not just primitive
constructors, because `list' is allowed (which is just a way
to generate chains of pairs) but not the related `list*' or
`append.'  Without `append' you can't even define SRFI-1's
`circular-list' in terms of `shared'.


P.S. Wouldn't `let-shared' have been a more natural name?

Posted on the users mailing list.