On traits composition

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
42 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: How about... something completely different? (Re: Re: On traits composition)

Igor Stasenko
2009/12/9 Göran Krampe <[hidden email]>:

> Hi!
>
> Igor Stasenko wrote:
>>
>> 2009/12/9 Göran Krampe <[hidden email]>:
>>>
>>> Given Andreas' statement above - wouldn't it be *much* cooler to evolve
>>> Smalltalk along the axis of composition instead of the axis of
>>> inheritance?
>>>
>>> I have always thought that having better mechanisms for delegation would
>>> be
>>> awesome, and would in most ways be much more powerful than inheritance
>>> (in
>>> whichever form).
>>>
>>> For example, what if one could declare that for class Foo (having ivars
>>> x,
>>> y, z) any message that would result in a DNU would instead be "delegated"
>>> to
>>> ivar x (and then y if no lookup is found in x either).
>>>
>>> This would be equivalent to tons of messages in Foo like:
>>>
>>> Foo>>name
>>>       ^(x respondsTo: #name) ifTrue: [x name] ifFalse: [y name]
>>>
>>> (well, kinda, you get the picture - but also, taking care of x/y
>>> returning
>>> "self" in which case we probably should return the "Foo self" instead
>>> etc)
>>
>>
>> Hmm, how is it different to inheritance?
>> I mean, you can achieve similar effect by making
>> an instance of Foo class superclass to be x, and x superclass to be y.
>
> There are several differences I think. And do note I only made a "loose"
> sketch of the idea, not going into details like for example, "should Foo
> really delegate *everything* it doesn't respond to or just a specified
> protocol etc?".
>
> A few differences off the top of my head:
>
> - Since we delegate to ivars it is fully dynamic. We can change x and y
> dynamically. Sure, you can claim that we can change the class hierarchy
> dynamically too - but hey.
>
> - We have the distinction of "selves". Ted mentions "self" (the part) and
> "whole" (the composition).
>
> - We have encapsulation. Composition is black box reuse, inheritance is
> glass box :). In other words, x can not touch ivars of Foo and so on.
>
> And probably more.
>
If you seen my other post about prototypes, i think its easily doable with them.

Consider a following sample code:

proto := PrototypeFactory new.
proto inheritTrait: TPoint.
proto prototype initialize.
proto inheritTrait: TColor
proto prototype initialize.

now you can send getters or setters like #x , #y , #red, #green, #blue etc.
In such composition you will get

TPoint (x,y)
TColor(red,green,blue)
proto

so, a proto, as a top-level receiver doesn't having any of slots (and
hence does not carrying any state), but its prototypes do.
But it still can transparently access them without much overhead.

Then, at any moment you could allocate own private slot
proto slotAt: #x put: 10

and now it will look like:

TPoint (x,y)
TColor(red,green,blue)
proto(x)

and #x accessor will shadow the TPoint's accessor, providing an access
to prototype-local slot.
So, it shows us that you can choose freely, who is going to be the
state holder.
A same initialization, but made little different:

proto := PrototypeFactory new.
proto inheritTrait: TPoint.
proto initialize.
proto inheritTrait: TColor
proto initialize.

will give you:

TPoint
TColor
proto(x,y, red,green,blue)

granted, that correspoding #initialize methods of above traits
allocating the slots.

I am sure, i'm not Discovering an America here for any who dealt with
prototype-based stuff before :)

Is this a kind(s) of delegation you having in mind?

> regards, Göran
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Re: How about... something completely different?

Igor Stasenko
In reply to this post by Eliot Miranda-2
2009/12/9 Eliot Miranda <[hidden email]>:

>
>
> On Wed, Dec 9, 2009 at 10:36 AM, Igor Stasenko <[hidden email]> wrote:
>>
>> 2009/12/9 Eliot Miranda <[hidden email]>:
>> >
>> >
>> > On Wed, Dec 9, 2009 at 9:15 AM, Colin Putney <[hidden email]>
>> > wrote:
>> >>
>> >> On 8-Dec-09, at 11:02 PM, Igor Stasenko wrote:
>> >>
>> >>> In this respect, interesting, how to avoid a pitfal of circular
>> >>> delegation.
>> >>>
>> >>> x -> y -> x
>> >>>
>> >>> if i send a message to x, and got DNU, it is automatically delegated
>> >>> to
>> >>> y,
>> >>> but in same way as x could delegate to y, y could delegate to another
>> >>> object , and finally some of them
>> >>> in delegation chain could delegate back to x. Circle is closed, and VM
>> >>> will loop forever trying to lookup a method not implemented in any of
>> >>> objects in such delegation chain.
>> >>
>> >> Yup, that's certainly a possibility. The only remedy is "don't do
>> >> that."
>> >> Consider it a bug, in the same way that we currently consider infinite
>> >> recursion a bug.
>> >
>> > and if the concern is a loop in the VM's lookup then all it has to do is
>> > remember the object or class it started the lookup in and abort (go
>> > straight
>> > to sending DNU) if it meets the same one again.
>>
>> Care to add it to Cog as a precaution against future hacks? :)
>
> Good suggestion.  <scottish>Now sends are faster this kind of check is much
> cheaper</scottish>

well, it is costly..

Consider a following:
a -> b -> c -> .... x -> y -> z -> x

so, you will have a loop not poining back to initial lookup class, but
to one in the chain,
which means that every time you going to superclass for lookup, you
need to check it against match will all elements in current lookup
chain.
I think it would be cheaper to prevent such chains be created (by
validating the inheritance once one of the class created, or once
superclass of particular class going to be set).
But the downside of such solution , that its image-based, because in
VM you can't really tell whether particular ivar update will affect
the lookup mechanism or not.

>>
>> >>
>> >> Colin
>> >>
>> >
>> >
>> >
>> >
>> >
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

123