[ERR5RS] Bindings in R5RS vs R6RS
Jonathan A Rees
jar at mumble.net
Sat Sep 15 18:01:47 PDT 2007
On Sep 15, 2007, at 3:39 PM, David Rush wrote:
...
> And to be fair to the immutability argument - I am unaware of any
> Scheme which truly implements mutable bindings for things like CAR,
> MAP, or APPEND. Under the covers of every toplevel are the internal
> names of the actual primitives which implement the ur-CAR, ur-MAP, and
> ur-APPEND functionality that is required to make *everything* work.
> However, this *fact* actually proves the earlier point, IMO. The names
> of the primitives are not relevant - the algebra provided by category
> of the functions and data *is*.
Scheme48 implements immutable bindings, but also has an interactive
model. I think you should know how it works, not as a "proposal" but
as a design point and for comparison.
A structure is a set of bindings exported from some environment. The
values can only be modified (set!) by code evaluated in that
environment. An evaluation environment not inside any local binding
constructs (lambda, let, etc.) has in effect two layers: An outer
immutable 'frame' that is the union of a bunch of structures, and an
inner frame in which define puts its bindings. You can set! the
latter. The latter can also shadow anything that's imported from a
structure.
For r5rs, there is a 'scheme' structure, which is not special in any
way, and that's the only one that's imported. set! of car is an error
if you haven't defined car. Try it.
The static compilation semantics is pretty clear: it is possible to
infer immutability of exported bindings, and then rely on them in
compiling client modules. So we get cross-module integration with
almost no kludgery and almost no declaration (you do have to set a
flag saying that you're on your own if you want to diddle with
integrated bindings, or something like that - sort of like 'sealing'
in found in some dynamic languages - there may be better ways to do
this).
This all works well enough that we were able to do embedded
programming in Scheme48 with no 'mode' change in the system. If you
didn't ask for EVAL or other trickery, then it didn't take up space
in the EPROM.
There is no clear or principled interaction semantics, but I think
there could be with some work. You can't set! imported bindings, but
you can always shadow them. If you haven't permitted integration then
this always does something perfectly clear and, importantly, in
keeping with R5RS. (Scheme48 is slavish to R5RS, or has been so far.)
To make interaction work, the system does allow additions to variable
export lists and structure import sets, and strives to make
everything appear to be totally dynamic.
I do agree that you want to be able to do meta-programming in Scheme,
since the meta-programming is going to happen in any case, and if the
right tools aren't given in Scheme then other tools will be found to
do the job, such as bash, make, sed, perl, etc. That should be
enough to terrify any implementation into supporting EVAL and all
other dynamic operations. Scheme48 doesn't really implement this
philosophy. But to really replace the ugly tools is a tall order. In
particular it doesn't work to have a global module namespace since
you often have to use one configuration (set of module versions) to
manipulate another.
Jonathan
More information about the Err5rs
mailing list