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

Modules vs. dynamic binding



    Date: Tue, 12 Dec 89 06:38:57 est
    From: cph@zurich.ai.mit.edu (Chris Hanson)

    Scott, this technique you propose is a useful one, but I don't believe
    it provides a replacement for dynamic binding.  The problem with the
    technique is that the procedure `read' cannot be embedded in another
    program unless the embedding program is also parameterized in a
    similar way (by "embedded" I mean that the variable `read' is bound in
    some closing environment of the embedding program).

    To properly take advantage of this technique (as you point out), every
    embedding program must be parameterized, and furthermore the
    parameters of the embedded program must also be parameters of the
    embedding program.

I don't think the latter is true at all.  Many programs will use READ,
for instance, but will not want to inherit the various parameters of the
reader from programs in which they are embedded.  In fact, the original
motivating example I gave was of just such a case.

						    Clearly nobody wants
    to write all of that specialization by hand, and yes, all this "late
    binding" can be hidden by a module system; but what about the program
    that occasionally specializes itself as it runs?  Does the module
    system know how to create new programs on the fly, or is it restricted
    to describing more static relationships?

Remember that "creating a new program" amounts to evaluating (i.e.,
closing) a set of lambda-expressions.  It's a familiar, primitive, and
efficient operation (at least, it had better be).

	  Ultimately this "module system" becomes an integral part of the
    language -- it has introduced a new kind of binding with "dynamic"
    characteristics.

No, that's exactly what it hasn't done.  It is using the same old kind
of binding that we all know and love to accomplish the same ultimate
purpose as dynamically bound parameters, but in a different way. 

		      What are the semantics of this binding?  Is it
    different from what we now think of as "dynamic binding"?  Is this
    really a new idea or just a new implementation of an old idea?

I will vigorously defend myself against any intimation that I am saying
anything new.  :-)  But no, it is neither of those things.  It is, at
best, a new application of an existing implementation of an old idea.

    Another solution to this problem was invented by John Lamping a few
    years ago: he introduced another kind of variable that could be bound
    after the program was constructed.  These variables can be considered
    to be "holes" in the program, which can be filled in at any time by a
    virtual-copy process that produced a new program in which a particular
    set of "holes" was filled.  Program fragments can be combined into
    larger program fragments, independent of whether they have "holes";
    "matching holes" in two program fragments become identified in the
    combined fragment.  With this solution, `read' would have such a
    variable for its radix, and this variable would be unspecified when
    `read' was defined.  You could then embed `read' in some big program,
    and just before you were ready to run it, you could specialize the
    embedding program with the desired radix.

This sounds complicated and inelegant by comparison with what I propose.

    Lamping's solution has some major advantages over what you propose:

      * The embedding program doesn't have to know anything about what
	"holes" `read' has.

I consider that a disadvantage -- a serious one.  Indeed, it is
precisely one of those properties of the dynamic-binding approach that I
am complaining about.

      * The values being supplied to the "holes" can be collected
	together in an environment and supplied all at once.  A "default
	environment" can easily be created, and the user can override
	particular bindings in that environment by shadowing.

This is a good idea, and I would certainly want to incorporate it.

      * It is clearly a change to the language itself rather than a
	system that at least nominally is not a fundamental part of the
	language.

Again, I consider this a disadvantage.

    But are either of these solutions really so different from dynamic
    binding?  You claim that dynamic binding is destructive to modularity,
    but with the implementation proposed by Pavel the designer must
    clearly state the intention that a particular parameter may be
    dynamically bound, so the parameter is clearly part of the program's
    abstraction boundary (if you can get your hands on it).

I don't see that.  I don't see what's to stop me from defining a bunch
of variables at top-level to be bound to Dynamics (or whatever they wind
up being called) and then just using them like special variables.
Granted, such parameters are logically part of the program's
abstraction; my observation is that in practice, they don't wind up
being specified as such.  That's part of my complaint.

    I think this topic is an interesting one that falls between the
    cracks: it's a little too dynamic for modules, and not dynamic enough
    for procedural arguments.  I'd like to see some work done on
    understanding this; I suspect that Lamping's work is a good first step
    (implementing his language efficiently is quite challenging).

(Implementing my proposal efficiently is quite straightforward.)

    On the other hand, I have a strong feeling that dynamic binding is the
    best solution to this problem for Scheme -- a better solution may
    require changes that are fundamental enough that the result may no
    longer be "Scheme-like".

That may well be true; although the funny thing is, the longer I think
and talk about this, the more convinced I am that my proposal is
entirely appropriate for Scheme.  I don't always convince myself so
effectively!

-- Scott