[plt-scheme] `shared' syntax confusing
Hi,
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'.
--
Alex
P.S. Wouldn't `let-shared' have been a more natural name?