[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Begin flattening documentation bug (CC)
To: norman@parc.xerox.COM
From: KenD@Newton.apple.com (Ken Dickey)
Subject: BEGIN "flattening" definition bug
Cc: rrrs-authors@ai.mit.edu
Norman,
As you know, I hate to pollute the global namespace and
would like to be able to lexically hide what I consider to
be local names. This lead me to a problem I mentioned to
you with "begin flattening" which I believe indicates a
deeper problem.
The form that I proposed is:
;;(define-values (name ...)
;; body-form ...
;; values-form)
This allows me to write:
(define-values (MAKE-INSTANCE INSTANCE?)
(let ( (instance-tag "instance") ) ;; unique tag
(values
; make-instance
(lambda (dispatcher) (cons instance-tag dispatcher))
; instance?
(lambda (obj) (and (pair? obj) (eq? (car obj) instance-tag)))
) ) )
rather than the equivalent:
(define make-instance 'bogus)
(define instance? 'bogus)
(let ( (instance-tag "instance") )
(set! MAKE-INSTANCE
(lambda (dispatcher) (cons instance-tag dispatcher)))
(set! INSTANCE?
(lambda (obj) (and (pair? obj) (eq? (car obj) instance-tag))))
)
A cheap implementation of this is:
(define-syntax DEFINE-VALUES
(syntax-rules ()
((define-values (<name> ...) <body> ...)
; =>
(define-values helper (<name> ...) () (<name> ...) <body> ...)
)
((define-values helper () (<temp> ...) (<name> ...) <body> ...)
; =>
(begin
(define <name> #f) ...
(call-with-values
(lambda () <body> ...)
(lambda (<temp> ...)
(set! <name> <temp>) ...
) )
))
((define-values helper (<var1> <var2> ...) <temp>s
(<name> ...) <body> ...)
; =>
(define-values helper (<var2> ...) (<temp> . <temp>s)
(<name> ...) <body> ...)
)
))
Which expands as you expect from the example above.
The problem is that the enclosing (begin ...) form is not
flattened. This results in the definitions being made in
a local rather than in the global namespace. [Operationally,
some Scheme implementations do the definitions in a lexically
local namespace, some in the global namespace!]
This is because R4RS (section 5.2) specifies that begin
flattening only occurs with definitions. I.e.
(begin <definition>+)
gets flattened, but
(begin <definition>+ <expression>+)
does not.
It is my opinion that BEGIN is a sequencing construct and
unlike LAMBDA, LET, LET*, and LETREC, should *not*
introduce a new lexical contour. As it stands, any macro
which introduces definitions and some other computation
will have the above problem.
Any chance that this can be fixed in R^5? In any case, the
wording should be clarified such that all Scheme
implementations have the same behavior.
Thanks,
-Ken