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

Re: A Proposal for Environments in Scheme



This is my response to comments made by Jinx and Juan.  I will try to simply
respond to their comments in this message; under separate cover I hope to send
out a more general message about module facilities.

Jinx asked whether or not the confusion generated by multiple inheritance (in
particular, the loss of the illusion of lexical scoping) is worthwhile.  Juan
correctly points out that this can be a modularity problem.  I believe that
there are circumstances in which the ability to share some names transparently
between compilation units is useful and desirable.  For example, suppose that
the implementation of a particular interface is quite large, comprising more
than one compilation unit.  It is awkward and, I contend, unreasonable to insist
that code in one compilation unit must explicitly reference through the
interface those items that are provided by a different compilation unit (I am
assuming here that such code can refer to items in the same compilation unit
without going through the interface).  Here is an illustration:

   Interface `Foo', a list of names:
   
     A
     B
     C
   
   Implementation of `Foo' (compilation unit one):
   
     (define A
        ...
        reference to B
        ...
        reference to C
        ...
        reference to X
        ...)
     
     (define B
        ...)
     
     (define X    ; an item private to this compilation unit
        ...)
   
   Implementation of `Foo' (compilation unit two):
   
     (define C
        ...)
     
     (define Y    ; an item private to this compilation unit
        ...)

I hope that no one would disagree that the reference to B in A should look any
different from the reference to X; that is, both are in the same scope as A and
so should be referenced transparently.  I would like to argue that references to
B and C could also be similar, by virtue of their shared presence in the
interface.  Naturally, A cannot refer to Y, since it is neither in the same
compilation unit nor exported to the interface.

Consider the environment in which compilation unit one should be evaluated.  I
would like (in some cases) for its environment to inherit both from the normal
language environment and from the environment represented by the interface.  One
way to get this would be to have the interface environment inherit from the
language environment.  This has the problem that the interface now ``contains''
too many names, more than the abstraction supports.  The only alternative is
multiple inheritance.

----------

Jinx has strong objections against read syntax and so does not like our ideas
for structured identifiers.  As far as I can tell, his difficulty is that
expressions like
		(set! a:b:c 17)
look like they should work, but they don't.  A simple response to this objection
is that perhaps such expressions should be defined to work.  Another response is
to remove the environment-set! primitive from the language and, perhaps, thus
remove the temptation to believe that such an expression might be correct in the
first place.

Jinx also asks ``What is wrong with (: a b1 b2 ... bk)?''  Well, I tried looking
at some code written using this and using modules to the degree that I'm used to
in Cedar (that is, module references are very common, averaging about one for
every three lines of code).  I still find this too verbose.

Juan objects to structured names at all, regardless of their syntax, stating
that their use tends to decrease modularity by wiring in a particular
organization of modules.  I claim that they only wire in a particular
organization of *interfaces* and that this is precisely the purpose of
interfaces.  Interfaces represent the contract between a provider and a client
and as such, it is intended that the client depend upon them.

In an example, Juan objects to the name MATH:SQRT because it specifies where I
want to find the square-root function.  Not only is that exactly my intention,
but it might be that I am using two different procedures named SQRT, one from
the MATH interface and one from some other interface.  The two might have very
different meanings and so qualified names are the only reasonable way to keep
them straight.  In general, I want to use qualified names for *everything except
the features of the language itself*.

Juan also says that it is impossible to abstract over or shadow a qualified
name.  Precisely; that is not their purpose.  Such abstraction and shadowing is
meaningless and thus I am relieved that it is impossible.

----------

Both Jinx and Juan object to what they call the ``absolute'' nature of the file
syntax/semantics I proposed.  I think that they are partially right, in that a
file (or, more generally, expression) should not attempt to specify anything
about the implementations of the interfaces it imports.  However, I do believe
that it should specify the interfaces themselves.  That is, the code should make
clear of what interfaces (and of what versions of them) it is a client and,
further, for what interfaces (in what versions) it is attempting to be a
(perhaps partial) provider.  It is then the responsibility of the user of this
code to supply proper implementations of the imported interfaces and to make the
code available as a provider of the exported ones.

	Pavel