> ... So far, in Scheme, I know that (foo ...)
> is a form that does something, and to find out what it does, I
> need to know what FOO does. If something does not show up at the
> first position in a list, it's a variable reference ...
This is true only if you never enclose an expression in a macro call. If
you never do, and you never use variable transformers yourself, you won't
have any worries.
On the other hand, if you do enclose an expression in a macro call, say
(M e), and the two forms x and (foo ...) appear somewhere in e, you have
no idea what either does unless you understand what M does. Even in R5RS
with just syntax-rules, M may replace (foo ...) or x with arbitrary code,
throw x back in as the first subform of some other form, or do anything
else it wants to do with them.
In particular, one can create, in R5RS, a define-class syntactic form that
does (almost) exactly what one would use a variable transformer for. That
is, the R5RS transformer can convert the instance variable references and
assignments within each method body to the appropriate instance accessor
and mutator calls. For example, it can convert the (+ x y) in:
(define-class point
(ivar x y)
(method mdist-from-origin () (+ x y)))
to
(+ (instance-ref self 0) (instance-ref self 1))
I say "almost" because it can replace the references only with a code walk,
and a code walk can't be done reliably without knowing all of the forms
that may appear in the body of the method, which is generally impossible
unless interleaved with expansion. For example, if it doesn't know that
(frob x) expands to (quote x) then it won't know not to transform the x in
(frob x) to an instance-ref call.
Variable transformers let programmers get macros like define-class right.
As a bonus, it also makes such macros more transparent.
> Ditto here, this extension serves mostly to obscure code. It is
> not much of a problem to write (set! (id) e) or even (set! (class
> id) e), and be explicit in what you're doing here (using SRFI-17
> or something similar).
This is basically addressed above, but I'll point out one more thing.
An abstraction that redefines what (set! id e) does can already be defined
(in R5RS) without the code walk required for references, by creating a
local binding for set!. For example, the define-class form can transform
the method body (set! x v) in
(define-class rememberer
(ivar x)
(method remember! (v) (set! x v))
(method recall () x))
to
(let-syntax ([set! (syntax-rules (x)
[(_ x e) (instance-set! self 0 e)])])
(set! x v))
Variable transformers allow the same thing to be done more transparently.
Kent Dybvig