[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Dynamic binding -- objection and counter-proposal



    Date: Wed, 6 Dec 89 10:27:45 -0800
    From: pavel.parc@arisia.xerox.com

    |--------|-------------------------------------------------------------------|
    |        |                                                                   |
    |        | I object to including a description of dynamic binding, similar   |
    |   X    | to that in the recent message to RRRS-Authors, in an appendix to  |
    |        | R4RS.                                                             |
    |        |                                                                   |
    |--------|-------------------------------------------------------------------|

    Additional comments:

I've always thought that dynamic binding was an ugly hack.  Besides, it
leads to some really weird bugs.  Here's my favorite dynamic-binding bug
story:

In the Lisp Machine Chaosnet protocol, opening a file across the net
involves, of course, an exchange of certain information about the file,
some of which (I don't know the details) is in the form of Lisp list
printed into an ASCII string.  One machine receives this string from the
other and does, effectively, a READ-FROM-STRING on it.  The string
commonly contains the sequence "NIL", which is intended, of course, to
represent the symbol NIL, a.k.a. ().

It is possible to create a package (you all know what packages are,
yes?) that does not inherit from the GLOBAL package; it is also possible
to make that be the default package, by setting the system variable
*PACKAGE*.  In fact, I was doing this at one point (I had a good
reason which doesn't matter here).

Here's where the fun comes.  If one reads the characters "NIL" when
*PACKAGE* is bound to a package such as I describe, one does not get the
"official" NIL ("the chosen NIL" as Bernie Greenberg used to call it),
but rather a *different* symbol named NIL in said package.  So when I
had set *PACKAGE* to such a package, the Chaosnet file code would blow
up because it would be getting these non-NIL symbols in places where it
didn't expect them!  This is as obscure and far-flung a
cross-interaction as I've ever seen in the (mostly pretty well
modularized) LispM system.

Now one can point out that the obvious fix is for the Chaosnet code to
bind *PACKAGE* to some package known to be reasonable around the call to
READ.  But I contend that a system should be designed so that such bugs
never happen in the first place.  And it seems to me that the obvious
mechanism for accomplishing this is only our old friend, lexical
scoping.

Consider this scenario: we have a system function READ-GEN that takes
arguments like BASE, READTABLE (or whatever we call it), etc. and
returns a procedure suitable for binding to READ; i.e. one might write
something like

  (let ((read (read-gen 10 scheme-readtable ...)))
    (read some-stream))

That is, we make it possible for READ, in different **LEXICAL!!**
contexts, to read using different parameters.  Simple enough, yes?

All that remains to make this usable, seems to me, is to give us a way
to establish bindings, such as this one for READ, outside entire sets of
top-level definitions.  That, as I understand it, is a primary purpose
of a module system.  At least, I hope that when we get around to
designing our module system, we'll support this kind of thing.
(Actually, I think what we really want is generator procedures that
generate entire modules from a single list of parameters; but this
discussion can wait.)

Let's back up for a moment and look at the larger picture.  In my
experience as a ZetaLisp/Common Lisp programmer, almost all uses of
special variables fall into the following classes:

 -- Those which are never bound except at top level; these are
    effectively constants.

 -- Those which are bound so frequently that, I would argue the programmer
    should have added one or more extra arguments to the relevant
    procedures.

 -- The kind described above, where one wants to establish certain
    default values for parameters of modules; I think all the
    language-defined special variables of Common Lisp, for instance,
    fall into this category.

Anyone who wants to convince me that dynamic binding should be in a
language will have to show me an example of a case that does not fall in
one of these categories and which I cannot find some other way to handle
that I like better.  But I warn you that I've been thinking about this
for a long time and I've never seen one.

-- Scott