cloning/invocation

Jecel Assumpcao Jr jecel at merlintec.com
Wed Aug 28 21:20:03 UTC 2002


On Tuesday 27 August 2002 18:23, Marcel Weiher wrote:
> Not if it can be hidden, just like you hide *not* making the copy.  I
> wonde why you see one as changing semantics, and its inverse as not
> changing the semantics.

We are talking about an object with a mutable part (prototype for 
temporary variables and arguments) and an immutable part (bytecode, 
sources, literals, etc). Either making a full copy or a partial copy 
that shares the immutable part will give you results that behave in the 
exactly the same way.

Not making a copy at all will give you a different behavior. In 
particular:

> >  Without a copy, two
> > different invocations of a method would share temporary variables
> > and arguments.
>
> Oh, please!  Every C function, Pascal procedure/function, Smalltalk
> method, etc. manages to do this without making a copy of the method,
> simply by externalizing the mutable state.

You have to properly initialize the stack frame. How do you do that? By 
copying some values from the code or some other area.

          int foo ( char c ) {
                int count = 0; max = 99;
                
                while ( count < max ) { .... }
          }

Some initial code in "foo" must copy 0 and 99 to the right places on the 
stack.

> >  With a copy, each one has a separate state.
>
> You don't need a copy for that, just a proper lookup algorithm.

Two different invocations of "foo" will allocate different memory 
addresses for "count" and "max", and each one will copy 0 and 99 to 
those memory addresses. We can make them not copy by doing

            static count = 0; max = 99;

but now the two invocations will step on each other's toes.

> > Of course, the declarative "invoke with arguments" will almost
> > certainly
> > have implicitly in its semantics some form of copying.
>
> No, it is creating a new method context, and leaving the method
> alone. Nothing is being copied.
>
> >  I am just  stating explicitly that this is what is happening.
>
> Well, then you are explicitly wrong about this ;-)

I hope that the C example will make what I am trying to say clearer.

> Yes.  I am fully behind the importance of interactive object
> construction, but I am convinced it doesn't go far enough.  In fact,
> I want to make it even better than it is.

So do I. In the message that started this thread I was proposing making 
changes to Self that I thought might make it better.

> Simple from an implementation point of view (all handled via one
> mechanism).  But I disagree that this is simple for the user.  Before
> I give my reasoning, let me first reiterate that I agree that
> constructing objects (once) is simple for users, the question is
> where to go from there.  Let me also try to clarify what I mean by
> "simple": reducing the cognitive load for a given construct as much
> as possible.

Ok.

> With copying and modifications, you have to remember and be aware of
> the history of an object to know what it is like now.  This makes the
> whole thing more complex.  Once again, I believe there is a reason we
> *write* method invocation (procedure calls) as:
>
> (1)	result := someObject  method: arg1 more:arg2.
>
> and not:
>
> (2)	method := MethodProtype copy.
> 	method setArg1: arg1.
> 	method setArg2: arg2.
> 	method invoke.
>
> This seems 'obviously' more complex to me.

I would like the system to have both. A base-level programmer would 
write (1) while a meta-level programmer could do something like (2).

> However, we do use object instance this way (2).  As far as I can
> see, self says that (2) is really the unifying mechanism, but
> provides both syntax and implementation-optimizations to use (1)
> where
> possible/necessary.

You are right. Just like the exact same syntax

                          obj x

will return a non cloned object if "x" is a data slot but will cause all 
the cloning we have been talking about if "x" is a method slot. Two 
different semantics for the same syntax. It is an imperfect shortcut, 
but nobody seems to have a problem with it.

> My current approach is to say that (1) is the unifying mechanismmm
> and potentially use (2) internally where necessary (though I'd rather
> it were not necessary).  Objects, which can be constructed with all
> the fun of self-style, can be turned into parametrized objects (which
> have some class-like characteristics) by turning some of their
> instance variables into parameters.  They are then incomplete, and
> know that they're incomplete.  The user also knows that and exactly
> how they are incomplete.  To be used, a parametrized object must be
> provided with a context that provides the bindings for the
> parameters.

That sounds good. In fact, if you allow lexical scoping you can actually 
get by without inheritance as in Beta or E. I am trying to convince a 
friend who is designing a language inspired on Tim Budd's Leda to go in 
this direction. My own proposal was in a different direction, but that 
doesn't mean I consider it better.

> >  Compare this with the model
> > presented in the Blue Book (which can also be seen in the
> > Interpreter class in Squeak).
>
> Ahh, but this really is an implementation...

Not necessarily, and that is one reason we are having such a hard time 
understanding each other.

> >  You will probably tell me that the "normal"
> > Smalltalker doesn't have to learn about stack pointers, method
> > headers, context objects, etc. Then I will say that the normal
> > Selfish programmer doesn't have to know that activation objects are
> > obtained from cloning method objects!
>
> ...whereas you've said that cloning is the "model" you present, and
> that the implementation doesn't actually do this.

Exactly. There are levels upon levels. At the very top level we can 
think of a user typing expressions in a workspace and doing "print it". 
He can have a model like you described either in Smalltalk or in Self.

If there is a bug, then he will be thrown into the debugger and a lower 
level model will be needed to cope with it. That would be the cloning 
in Self and the Blue Book in Smalltalk.

The real implementation can use an even lower level model which can be 
very different from the previous one. It isn't in Squeak, but it is in 
VisualWorks, StrongTalk or even Smalltalk V. And it is likely to be a 
different model in future versions of Squeak (see Anthony Hannan's work 
in that direction).

And of course, this implementation might run on a processor that 
pretends to execute x86 instructions. And so on. Levels upon levels 
until we finally get to the turtles ;-)

> Anyway, this is all too low-level for me anyhow, and method
> invocation is not really what I am talking about.  It is making
> dealing with objects more like method-invocation (or function
> evaluation, procedure call) rather than vice versa, making method
> invocations more like munging objects.

As I wrote above, I am big fan of languages which take this idea 
seriously even if I didn't adopt it myself.

Cheers,
-- Jecel



More information about the Squeak-dev mailing list