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

Re: slot shadowing

    Why Automatic Shadowing of Slots Is Essential
    Dave Touretzky, CMU
    In this note I will try to explain why automatic shadowing of slots is
    essential to a Common Lisp flavor system.  I have read the ObjectLisp
    document distributed at the IJCAI Common Lisp meeting in Los Angeles, which
    I attended, but I am not otherwise familiar with the CommonLoops or HP
    flavors proposals.  I hope people who do understand these proposals will
    respond to the points raised here.
Let me describe how these situations are handled in the HP proposal:

    Example 1:  Customizing a Flavor.  A user of a hairy window system wants to
    create his own flavor of window, called PORTHOLE, which is like an ordinary
    window in most respects.  But PORTHOLE has an instance variable N which the
    user can access and modify.  He defines PORTHOLE as a subtype of WINDOW, and
    writes methods GET-N and SET-N for accessing and setting N.  Unbeknownst to
    him, however, the window system is already using N as the name of a slot.
    Suggested behavior:  instances of PORTHOLE should have two slots named N,
    and one of them, WINDOW's N, should be shadowed for PORTHOLE's methods.
    Let P1 be an instance of PORTHOLE.  Sending P1 a GET-N message should access
    the N the user intended:  PORTHOLE's N.  Sending P1 a CLEAR-SCREEN message
    should access the N inherited from WINDOW, since the CLEAR-SCREEN method is
    itself inherited from WINDOW and the user knows nothing about the shadowing
    of WINDOW's N by his own use of the name.
The HP proposal behaves pretty much as you suggest.  Instances of PORTHOLE
would have two slots named N.  One slot is accessible to methods defined on
PORTHOLE, the other is accessible to methods defined on WINDOW.

    Example 2:  Replacing a Method.  Suppose a hacker who is familiar with the
    window system wants to create his own type of PORTHOLE, HACKPORT, that uses
    a different CLEAR-SCREEN method.  Since HACKPORT is an instance of PORTHOLE,
    references to N by a HACKPORT method will normally be interpreted as
    references to PORTHOLE's N rather than WINDOW's N.  So we need a way to
    reference the shadowed N in methods defined for PORTHOLE or HACKPORT.  I
    won't suggest a notation for this here.  However, the next example argues
    that we must reference shadowed slots by a point on their inheritance path,
    e.g.  by saying PORTHOLE's N; we can't just say something like SHADOWED-N
    and expect the reference to be resolved.
The HP proposal would not allow a HACKPORT method to access either slot N,
unless methods were provided to do so.  The methods to access HACKPORT's N
would be provided by HACKPORT.  The methods to access WINDOW's N would be
provided by WINDOW and passed on (inherited) by HACKPORT.  If these two sets
of methods have the same names, then HACKPORT would have to provide different
names for the methods it passes on from WINDOW, to avoid a conflict.  It would
do this by defining a method GET-WINDOW-N (any name can be used) whose
definition invokes the appropriate method defined by WINDOW (which it refers
to as WINDOW's N).  The package system could be used to create different names
for the methods, if desired.

    Example 3:  Combining Orthogonal Flavors.  A naive user has available
    to him two predefined flavors, WINDOW and STACK, about whose internals
    he knows nothing.  He wants to build a flavor called VISIBLE-STACK,
    which is a stack whose contents are constantly displayed in a window.
    He defines VISIBLE-STACK as a subtype of both WINDOW and STACK, not
    knowing that both these flavors contain instance variables named N.
    Suggested behavior:  Let S1 be an instance of VISIBLE-STACK.  Sending
    a POP-STACK message to S1 should access STACK's N, while sending a
    SET-FONT message to S1 should access WINDOW's N.  
The HP proposal has this behavior.

    Problem:  let METHA be a method defined for VISIBLE-STACK.  How should
    references to N be interpreted inside METHA?  If VISIBLE-STACK has its own
    instance variable named N, then this N should shadow both WINDOW's N and
    STACK's N.  But if there is no N defined at the level of VISIBLE-STACK, then
    references to N inside METHA should generate an error message:  "N is an
    ambiguous slot reference."
If VISIBLE-STACK defines an instance variable N, then METHA will access that
N.  Otherwise, a reference to N within METHA will access the global variable
N, or get an error if there is no global variable N.  As described above, for
METHA to access WINDOW's N or STACK's N, the appropriate methods must be
defined on WINDOW or STACK, and VISIBLE-STACK must declare its desire to
access those variables.

    Problem:  how do we write a new CLEAR-SCREEN method for VISIBLE-STACK?  We
    will need notation to explicitly specify that we want to access the
    shadowed WINDOW's N rather than the shadowed STACK's N.
METHA can access WINDOW's N and STACK's N if the appropriate methods are
defined on WINDOW or STACK.  These methods can be accessed without conflict as
WINDOW's N and STACK's N within VISIBLE-STACK.  They can't both be accessed as
variables, however, because of the name conflict.  (The syntax for method
invocation allows qualified names, the syntax for variable reference does
not.)  Furthermore, an error will be generated if VISIBLE-STACK attempts to
inherit BOTH methods, as the method names would conflict.