Eliminating assignments and variable syntax (accessors)

Alan Lovejoy sourcery at pacbell.net
Thu Aug 5 05:23:21 UTC 1999


> ** Original Sender: Marcel Weiher <marcel at system.de>
>
> > From: Alan Lovejoy <sourcery at pacbell.net>
> >
> > > ** Original Sender: Marcel Weiher <marcel at system.de>
> > >
> > > Exactly!  The difference to now is that right now I'd have to
> > > manually modify the source code of all the methods doing access,   
> > > whereas with the change the system can do the recompilation
> > > automagically.
> >
> > It's bad enough that all methods have to be recompiled when the
> > slot definitions are changed.  Such recompilation is inelegant,
> > time consuming, brittle, and requires the compiler to be present
> > in order for methods to be added or removed (and also for
> > classes to be added or removed)--even when all added or changed
> > methods are already precompiled.  Think of the consequences
> > for moving behavior over the net!
> 
> I *have* thought about the consequences, and yes, they are bad.  The  
> only point of the exercise is that they are a *little less bad* than  
> today.  Today I have to rewrite, with the change the compiler can  
> recompile.  Which part of "a little better" don't you understand?

Well, I don't (yet) think your proposal is better (but who knows 
what I'll think tomorrow?).  Anyway, the crux of my objection to
your proposal is that it is too static (binding is too early).  I'm also 
worried that code will become harder to understand because one
would always have to check whether or not what looks like a message
send is actually just a simple access (direct to iVar or via method),
or is actually some non-trivial computation (this is the downside
of the Self-style syntax).  But I'm not sure whether the latter point is
important enough to outweigh the benefits of the symmetry of
the Self-style syntax.

> > > I never suggested this was a panacea, just that it is a *little*   
> > > better than what we have now.
> > >
> > > >  A worse problem
> > > > is what to do when an accessor is introduced **in a subclass**. 
> > > > Should that change the meaning of code in a superclass, or not? 
> > >
> > > Again, ask yourself what happens now.  There, you've got the  
> initial
> > > answer.
> >
> > What happens now is that is that no subclass can **inadvertently**  
> > change the meaning of a direct variable access or assignment simply 
> > by introducing an accessor or mutator method.  If the subclass decides 
> > that the object in the instance variable should not be subject to  
> external
> > modification, it might define an accessor that answers a copy of the 
> > value in the variable, thus breaking just about all existing code that 
> > thought it was accessing the value in the variable, not a copy thereof. 
> 
> Well, you obviously misunderstood what I said.  

Yes, I sure did.  I apologize.

When you said "what happens now" I was thinking "same as using an
accessor now," not "same as a direct variable reference now."

> I am saying that  
> such an accessor defined in a subclass will not change the compiled  
> direct access in the superclass, which is *exactly the same behaviour  
> as today*.
> 
> The one change that actually *does* occur is when a *superclass*  
> decides that the instance var should only be available through  
> accessor.  This will, in fact, change what the subclasses see and  
> disallow direct access, but that was exactly the idea.

Yes, this makes much more sense.  But it's still too static, the binding
happens too soon.

> The one problem I see is that now there would be now way for a  
> subclass to bypass a complex accessor/mutator defined in a superclass  
> and directly munge/access an instance variable without changing the  
> code of the superclass.  Then again, this restriction may be viewed  
> as a benefit.  (The workaround is to rename the instance var in the  
> superclass).

In effect, this make the instance variable private, and requires the
subclasses to access it via message send. I have to ponder this,
but it may be acceptable, perhaps even good.

> > > > Worse, suppose the accessor does lazy initialization, but  
> there are
> > > > references to the iVar where lazy initialization would be either 
> > > > incorrect or at least undesirable?
> > >
> > > Then you shouldn't use the basic-accessor to do the lazy  
> initialization.
> >
> > Which is a big change.  Currently, I can do lazy initialization  
> using an
> > accessor that has the same name as the variable.  This makes it  
> transparent
> > to the clients of the object whether I'm doing lazy initialization  
> or not
> > (it's none of their business, after all).
> 
> It's a trivial change because you just rename the instance variable  
> to some hidden name.  After all your clients shouldn't be looking at  
> the instance variable definitions at all, only at the message  
> protocol.  If they are looking at inst-vars, then that is wrong and  
> something I would be more than happy to break.

Having the name of accessor/mutator methods match the instance
variable is not something that clients of the object should care about, 
agreed. But it is something that the poor human programmers trying to 
understand the code will care about very much!

> > 2. We extend the syntax for accessing instance variables, so that  
> an instance
> > variable can be accessed by prepending an underscore (for example) to 
> > the name of the variable.  However, when a variable is accessed  
> this way,
> > a lookup is performed for a private method with the same name.  If none 
> > is found (dynamically, at run time), then the variable is accessed  
> directly.
> > Otherwise, the private method is executed instead.
> >
> > So the expression "_name" would be evaluated as follows:
> >
> > 1. Try to send the selector #_name.
> >
> > 2. If such a method is found, execute it and push the result.
> >
> > 3. If no such method is found, push the value of the instance variable  
> > "name."
> 
> If this is implemented at runtime as your description suggests, it  
> would make instance variable access extremely inefficient by  
> requiring a failed message send for inst-var access.  I don't see  
> anybody actually using this as it is syntactically ugly *and* highly  
> inefficient.  Furthermore, it *does* suffer from exactly the subclass  
> overriding problem you thought you had spotted in my proposal (which  
> mine actually doesn't).

Not all instance variable access, only for those instance variables
prepended with "_".  And the cost can be optimized away using a
polymorphic inline cache--or even better, using both a PIC and
the ammended proposal I posted last night.  Yes, it does permit
subclasses to dynamically override, but again the superclass can
control which variables will be subject to such fate by whether or
not a "_" is prepended to the iVar's name.  Yes, it doesn't have
the best aesthetics, but that's why I said that the underscore was
just an example, not a concrete proposal.

> If this is implemented at compile time, it is *exactly* my proposal  
> except for your addition of the underscore character, which I find  
> superfluous and which isn't possible anyhow in Smalltalk (apart from  
> that matching several of the objections you had to my proposal).

Well, yes.   Except that the underscore (or some other syntactic 
variation, suggestions welcome) can easily be added to the current
compiler, no problem, and is actually a less drastic syntactic change
than your proposal would be (for one thing, no existing code would
be affected or invalidated).

> > And the expression "_name := aString" would be evaluated as follows: 
> >
> > 1. Try to send the selector #_name: with "aString" as the argument. 
> >
> > 2. If such a method is found, execute it and push the result.
> >
> > 3. If no such method is found, assign "aString" to the instance
> > variable "name."
> 
> I think this is a really bad idea, because := has the connotation of  
> "munge this variable, now", which is exactly the type of operation  
> and connotation 'we' are trying to get rid of here.  I don't see what  
> the benefit could possibly be of keeping the notation, but changing  
> its meaning into something much more complicated including possible  
> message sends.
> 
> On the contrary, I for one would be extremely confused by having  
> something that looks like a simple assignment trigger a message send.  
>  OTOH, inlining a message send to self is really quite harmless.

I see no difference whatsoever.  Both syntaxes imply one thing, but
may actually result in something else.

My proposal has the added benefit of not making instance variable access
public just because you want to use a method to do the access.  In fact,
that's one of its two major points (the other being the late, dynamic binding).

I would not yet vote for my own proposal, by the way. To me, it's just 
a thought experiment that may eventually, after improvement, lead to 
something I would actually want to put into a programming language.
Or perhaps not--I don't know yet, the thought experiment is still
running.

--Alan





More information about the Squeak-dev mailing list