Smells looking at collections

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

Smells looking at collections

Nicolás Paez
Hi, I was looking at collection packages and I found that the class Association inherits from Magnitude.
It is really strange for me because inheritance represent a "is-a" relation.

So I looked that the documentation of each of these classes:

Association: I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.

Magnitude: I'm the abstract class Magnitude that provides common protocol for objects that have
the ability to be compared along a linear dimension, such as dates or times.
Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
Character and LookupKey.

Based on this, I think this relation is conceptually WRONG.
If the idea is to reuse code then composition should be used instead of inheritance.

What do you think?

Saludos!
Nico.
blog: nicopaez.wordpress.com

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
On Fri, 22 Oct 2010, Nicolás Paez wrote:

> Hi, I was looking at collection packages and I found that the class
> Association inherits from Magnitude.
> It is really strange for me because inheritance represent a "is-a" relation.
>
> So I looked that the documentation of each of these classes:
>
> *Association:* I represent a pair of associated objects--a key and a value.
> My instances can serve as entries in a dictionary.
>
> *Magnitude:* I'm the abstract class Magnitude that provides common protocol
> for objects that have
> the ability to be compared along a linear dimension, such as dates or times.
> Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
> Character and LookupKey.
>
> Based on this, I think this relation is conceptually WRONG.
> If the idea is to reuse code then composition should be used instead of
> inheritance.
>
> What do you think?
This was the original hierarchy: Magnitude -> LookupKey -> Association.
Someone removed LookupKey from the chain. This was LookupKey's comment:

"I represent a key for looking up entries in a data structure. Subclasses
of me, such as Association, typically represent dictionary entries."


Levente

>
> Saludos!
> Nico.
> blog: nicopaez.wordpress.com
>
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Mariano Martinez Peck
Maybe I am so naive, but what are the advantages of such Inheritance?

The only thing I see is that in all your code of Association you can do "self " and access to all the behavior of Magnitude.
But it is not that difficult to use composition, and write "self aMagnitude"
replace aMagnitude for whatever name you want.

Cheers

mariano


2010/10/22 Levente Uzonyi <[hidden email]>
On Fri, 22 Oct 2010, Nicolás Paez wrote:

Hi, I was looking at collection packages and I found that the class
Association inherits from Magnitude.
It is really strange for me because inheritance represent a "is-a" relation.

So I looked that the documentation of each of these classes:

*Association:* I represent a pair of associated objects--a key and a value.
My instances can serve as entries in a dictionary.

*Magnitude:* I'm the abstract class Magnitude that provides common protocol
for objects that have
the ability to be compared along a linear dimension, such as dates or times.
Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
Character and LookupKey.

Based on this, I think this relation is conceptually WRONG.
If the idea is to reuse code then composition should be used instead of
inheritance.

What do you think?

This was the original hierarchy: Magnitude -> LookupKey -> Association. Someone removed LookupKey from the chain. This was LookupKey's comment:

"I represent a key for looking up entries in a data structure. Subclasses of me, such as Association, typically represent dictionary entries."


Levente



Saludos!
Nico.
blog: nicopaez.wordpress.com

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

jaayer
In reply to this post by Nicolás Paez




---- On Fri, 22 Oct 2010 04:56:28 -0700 Nicolás Paez  wrote ----

>Hi, I was looking at collection packages and I found that the class Association inherits from Magnitude.It is really strange for me because inheritance represent a "is-a" relation.
>
>
>So I looked that the documentation of each of these classes:
>
>
>Association: I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.
>
>
>Magnitude: I'm the abstract class Magnitude that provides common protocol for objects that have
>the ability to be compared along a linear dimension, such as dates or times.
> Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
>Character and LookupKey.
>
>
>
>Based on this, I think this relation is conceptually WRONG.
>If the idea is to reuse code then composition should be used instead of inheritance.
>
>
>
>
>What do you think?
>
>Saludos!
>Nico.
>blog: nicopaez.wordpress.com

There was a discussion here a few weeks ago concerning a Trait I proposed called TComparable. It is the protocol of Magnitude bundled separately as a Trait, so any class can behave like Magnitude without having to inherit from Magnitude or use composition. You need only add "uses: TComparable" to the class template and then override its abstract methods as needed, and instances of your class will now be comparable. Association could use TComparable rather than inheriting from Magnitude, and, if the build system permits, Magnitude itself could be rewritten to use TComparable. Stef. approved of the idea and expressed a desire to see it in upcoming versions of Pharo, but I am not sure what the current status is.


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
On Sat, 23 Oct 2010, jaayer wrote:

>



---- On Fri, 22 Oct 2010 04:56:28 -0700 Nicolás Paez  wrote ----

>Hi, I was looking at collection packages and I found that the class Association inherits from Magnitude.It is really strange for me because inheritance represent a "is-a" relation.
>
>
>So I looked that the documentation of each of these classes:
>
>
>Association: I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.
>
>
>Magnitude: I'm the abstract class Magnitude that provides common protocol for objects that have
>the ability to be compared along a linear dimension, such as dates or times.
> Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
>Character and LookupKey.
>
>
>
>Based on this, I think this relation is conceptually WRONG.
>If the idea is to reuse code then composition should be used instead of inheritance.
>
>
>
>
>What do you think?
>
>Saludos!
>Nico.
>blog: nicopaez.wordpress.com
There was a discussion here a few weeks ago concerning a Trait I proposed called TComparable. It is the protocol of Magnitude bundled separately as a Trait, so any class can behave like Magnitude without having to inherit from Magnitude or use composition. You need only add "uses: TComparable" to the class template and then override its abstract methods as needed, and instances of your class will now be comparable. Association could use TComparable rather than inheriting from Magnitude, and, if the build system permits, Magnitude itself could be rewritten to use TComparable. Stef. approved of the idea and expressed a desire to see it in upcoming versions of Pharo, but I am not sure what the current status is.


That's a nice solution, but it means that Traits have to be in the Kernel.
I have three problems with Traits:
1) they are stateless
2) they are different from classes
3) incomplete tools support (this may be fixed in Pharo, but I doubt it
is)


Levente

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by Nicolás Paez
This is in 1.2 :)


Stef


On Oct 23, 2010, at 4:55 PM, jaayer wrote:

>
>
>
>
> ---- On Fri, 22 Oct 2010 04:56:28 -0700 Nicolás Paez  wrote ----
>
>> Hi, I was looking at collection packages and I found that the class Association inherits from Magnitude.It is really strange for me because inheritance represent a "is-a" relation.
>>
>>
>> So I looked that the documentation of each of these classes:
>>
>>
>> Association: I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.
>>
>>
>> Magnitude: I'm the abstract class Magnitude that provides common protocol for objects that have
>> the ability to be compared along a linear dimension, such as dates or times.
>> Subclasses of Magnitude include Date, ArithmeticValue, and Time, as well as
>> Character and LookupKey.
>>
>>
>>
>> Based on this, I think this relation is conceptually WRONG.
>> If the idea is to reuse code then composition should be used instead of inheritance.
>>
>>
>>
>>
>> What do you think?
>>
>> Saludos!
>> Nico.
>> blog: nicopaez.wordpress.com
>
> There was a discussion here a few weeks ago concerning a Trait I proposed called TComparable. It is the protocol of Magnitude bundled separately as a Trait, so any class can behave like Magnitude without having to inherit from Magnitude or use composition. You need only add "uses: TComparable" to the class template and then override its abstract methods as needed, and instances of your class will now be comparable. Association could use TComparable rather than inheriting from Magnitude, and, if the build system permits, Magnitude itself could be rewritten to use TComparable. Stef. approved of the idea and expressed a desire to see it in upcoming versions of Pharo, but I am not sure what the current status is.
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by jaayer
>
> There was a discussion here a few weeks ago concerning a Trait I proposed called TComparable. It is the protocol of Magnitude bundled separately as a Trait, so any class can behave like Magnitude without having to inherit from Magnitude or use composition. You need only add "uses: TComparable" to the class template and then override its abstract methods as needed, and instances of your class will now be comparable. Association could use TComparable rather than inheriting from Magnitude, and, if the build system permits, Magnitude itself could be rewritten to use TComparable. Stef. approved of the idea and expressed a desire to see it in upcoming versions of Pharo, but I am not sure what the current status is.
>
>
> That's a nice solution, but it means that Traits have to be in the Kernel. I have three problems with Traits:
> 1) they are stateless
> 2) they are different from classes
> 3) incomplete tools support (this may be fixed in Pharo, but I doubt it is)

1) we build some code to see if we really need state and this is not that obvious and adding state is not trivial
2) well, this is difficult to get the money for the butter and the butter - we are trying.
3) again if nobody does anything and we just all cry on ourselves then nothing will happen.

So for now identifying traits and learning is the way. Then we can refactor, redesign
Stef
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
On Sat, 23 Oct 2010, Stéphane Ducasse wrote:

>>
>> There was a discussion here a few weeks ago concerning a Trait I proposed called TComparable. It is the protocol of Magnitude bundled separately as a Trait, so any class can behave like Magnitude without having to inherit from Magnitude or use composition. You need only add "uses: TComparable" to the class template and then override its abstract methods as needed, and instances of your class will now be comparable. Association could use TComparable rather than inheriting from Magnitude, and, if the build system permits, Magnitude itself could be rewritten to use TComparable. Stef. approved of the idea and expressed a desire to see it in upcoming versions of Pharo, but I am not sure what the current status is.
>>
>>
>> That's a nice solution, but it means that Traits have to be in the Kernel. I have three problems with Traits:
>> 1) they are stateless
>> 2) they are different from classes
>> 3) incomplete tools support (this may be fixed in Pharo, but I doubt it is)
>
> 1) we build some code to see if we really need state and this is not that obvious and adding state is not trivial
Not trivial? Maybe not, but only a little bit harder than trivial.

> 2) well, this is difficult to get the money for the butter and the butter - we are trying.

If you can compose classes the way you can add a trait to a class now
with class and optional method level instance+class variable mapping, then
you're done. It would be a lot simpler to use it _and_ it would also be a
lot easier to implement it. Especially the tools part.

> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.

Tools are a must. No tools - no users.

>
> So for now identifying traits and learning is the way. Then we can refactor, redesign

Well, Traits are in Squeak since 2006, IIRC they were available a few
years earlier. So in the last X (at least 4) years the only good
candidate to become a Trait was Magnitude.


Levente

> Stef



> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by Stéphane Ducasse
>>>
> Not trivial? Maybe not, but only a little bit harder than trivial.

We are open to suggestions believe me :)
>
>> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>
> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.

I'm interested to hear more about that.
Tell us more. The problem we faced was
        - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
        - initialization of instances variables at the trait level and the composition at the class levele

>
>> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>
> Tools are a must. No tools - no users.

Exact.

>> So for now identifying traits and learning is the way. Then we can refactor, redesign
>
> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.

Come on.
I will not answer to such statement because I'm positive thinking.

Stef
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
On Sun, 24 Oct 2010, Stéphane Ducasse wrote:

>>>>
>> Not trivial? Maybe not, but only a little bit harder than trivial.
>
> We are open to suggestions believe me :)
>>
>>> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>>
>> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.
>
> I'm interested to hear more about that.
> Tell us more. The problem we faced was
> - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
If you mean that a CompiledMethod of a trait cannot be added to the
class' method dictionary, than that's not an issue. The current Trait
implementation was changed, because shared CompiledMethods caused other
problems.
If you mean that the same bytecodes can't be used, than that's neither a
problem, because you can and should be compile the method again. Sharing
trailer bytes may cause problems.
So adding a method from a trait to a class is simply recompiling it in the
class' context. Instance variables should be used by name during
compilation. If there's a name collision then use the instance variable
map I mentioned above.

> - initialization of instances variables at the trait level and the composition at the class levele

You can always rename a trait's method in your class. So if the trait has
an #initialize method, then simply rename it to #initializeFooBar and send
it from the class' #initialize method.


Levente

>
>>
>>> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>>
>> Tools are a must. No tools - no users.
>
> Exact.
>
>>> So for now identifying traits and learning is the way. Then we can refactor, redesign
>>
>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>
> Come on.
> I will not answer to such statement because I'm positive thinking.
>
> Stef
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Johan Brichau-2
In reply to this post by Stéphane Ducasse

On 24 Oct 2010, at 08:42, Stéphane Ducasse wrote:

>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.


PolyMorphic also uses traits.
There are non-core projects that also use them, for example WebTester.

I can also name several occassions in the development of our application, where we considered using traits to avoid code duplication. The only reason we didn't was because of a need for portability to GS. But if I understood correctly, it's quite possible that GS will support them in the future.

Traits are being added to many other languages as well (e.g. traitsjs.org). It would be a shame to remove them from Squeak/Pharo Smalltalk now.

just my 2 cents,
Johan
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

jfabry

On 24 Oct 2010, at 14:48, Johan Brichau wrote:

>
> On 24 Oct 2010, at 08:42, Stéphane Ducasse wrote:
>
>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>
>
> PolyMorphic also uses traits.
> There are non-core projects that also use them, for example WebTester.

AspectMaps us them as well. They made it possible to really clean up my implementation, so I am happy with them (even though there are packaging issues).

> Traits are being added to many other languages as well (e.g. traitsjs.org). It would be a shame to remove them from Squeak/Pharo Smalltalk now.


+1

--
Johan Fabry  
[hidden email] - http://dcc.uchile.cl/~jfabry
PLEIAD Lab - Computer Science Department (DCC) - University of Chile




_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
In reply to this post by Johan Brichau-2
On Sun, 24 Oct 2010, Johan Brichau wrote:

>
> On 24 Oct 2010, at 08:42, Stéphane Ducasse wrote:
>
>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>
>
> PolyMorphic also uses traits.

Where can I find it?

> There are non-core projects that also use them, for example WebTester.

I don't see any trait in the latest version, though I used SqueakSource's
web interface.

>
> I can also name several occassions in the development of our application, where we considered using traits to avoid code duplication. The only reason we didn't was because of a need for portability to GS. But if I understood correctly, it's quite possible that GS will support them in the future.
>
> Traits are being added to many other languages as well (e.g. traitsjs.org). It would be a shame to remove them from Squeak/Pharo Smalltalk now.

I'm not saying that trait-like composition is bad, I only say that there's
a better approach.


Levente

>
> just my 2 cents,
> Johan
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Johan Brichau-2

On 24 Oct 2010, at 20:06, Levente Uzonyi wrote:

>> PolyMorphic also uses traits.
>
> Where can I find it?

Sorry, I meant Polymorph.

The PolyMorph-Widgets category in any Pharo image has them: TEasilyThemed, TEnableInHalo (or something like that).

>> There are non-core projects that also use them, for example WebTester.
>
> I don't see any trait in the latest version, though I used SqueakSource's web interface.

There's just one (WtTClickable) right now.



_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by Stéphane Ducasse
your 2 cts are really welcome.

On Oct 24, 2010, at 7:49 PM, Johan Brichau wrote:

>
> On 24 Oct 2010, at 08:42, Stéphane Ducasse wrote:
>
>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>
>
> PolyMorphic also uses traits.
> There are non-core projects that also use them, for example WebTester.
>
> I can also name several occassions in the development of our application, where we considered using traits to avoid code duplication. The only reason we didn't was because of a need for portability to GS. But if I understood correctly, it's quite possible that GS will support them in the future.
>
> Traits are being added to many other languages as well (e.g. traitsjs.org). It would be a shame to remove them from Squeak/Pharo Smalltalk now.
>
> just my 2 cents,
> Johan
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by Stéphane Ducasse
>>
>>>
>>>> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>>>
>>> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.
>>
>> I'm interested to hear more about that.

so can you explain what you meant because I did not understand it.


>> Tell us more. The problem we faced was
>> - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
>
> If you mean that a CompiledMethod of a trait cannot be added to the class' method dictionary, than that's not an issue. The current Trait implementation was changed, because shared CompiledMethods caused other problems.

no this is not what I meant

> If you mean that the same bytecodes can't be used, than that's neither a problem, because you can and should be compile the method again. Sharing trailer bytes may cause problems.
> So adding a method from a trait to a class is simply recompiling it in the class' context.

this is what we wanted to avoid.
Also because you may have to recompile all the other methods of the class hierarchy because if a trait add an instance
variable then you should recompile the subclasses when a trait get added with a state in the superclass.

> Instance variables should be used by name during compilation. If there's a name collision then use the instance variable map I mentioned above.

what is that the instance variable map?
take the time to write an example

>> - initialization of instances variables at the trait level and the composition at the class levele
>
> You can always rename a trait's method in your class. So if the trait has an #initialize method, then simply rename it to #initializeFooBar and send it from the class' #initialize method.

Yes this is what the javascript implementation does but this is not that nice but may be there is no better solution.

So indeed we could think about adding state.



>
>
> Levente
>
>>
>>>
>>>> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>>>
>>> Tools are a must. No tools - no users.
>>
>> Exact.
>>
>>>> So for now identifying traits and learning is the way. Then we can refactor, redesign
>>>
>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>>
>> Come on.
>> I will not answer to such statement because I'm positive thinking.
>>
>> Stef
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Levente Uzonyi-2
On Sun, 24 Oct 2010, Stéphane Ducasse wrote:

>>>
>>>>
>>>>> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>>>>
>>>> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.
>>>
>>> I'm interested to hear more about that.
>
> so can you explain what you meant because I did not understand it.

Okay, here is an example of my class composition idea. It works like
Traits, but it supports state and there's no distinction between a trait
and a class. Let's say I have a class named BidirectionalLink which can be
used as a link in a linked list (with a head element). This will be used
as a stateful trait. It's definition is like this:

Object subclass: #BidirectionalLink
  instanceVariableNames: 'next previous'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'ClassCompositionExample'

It has a few methods:

BidirectionalLink >> next
  ^next

BidirectionalLink >> next: aBidirectionalLink
  next := aBidirectionalLink

BidirectionalLink >> previous
  ^previous

BidirectionalLink >> previous: aBidirectionalLink
  previous := aBidirectionalLink

BidirectionalLink >> unlink
  previous next: next.
  next previous: previous

BidirectionalLink >> linkAfter: aBidirectionalLink
  previous := aBidirectionalLink.
  next := aBidirectionalLink next.
  aBidirectionalLink next: self.
  next previous: self

I have an existing class, let's call it ODatedEntry :). It has the
following definition:

ECSelectorEntry subclass: #ODatedEntry
  instanceVariableNames: 'date'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Ocompletion'

As you can see, it inherits some state and behavior from ECSelectorEntry.
My goal is to use the instances of this class in a linked list. So these
objects should implement the same protocol with the same behavior as
BidirectionalLink. I can't make it a subclass of BidirectionalLink,
because I also need the behavior and state from ECSelectorEntry and we
don't have multiple inheritance. So I'll compose the two classes. First I
add the necessary instance variables to the class. Let's call them
nextEntry and previousEntry:

ECSelectorEntry subclass: #ODatedEntry
         instanceVariableNames: 'date nextEntry previousEntry'
         classVariableNames: ''
         poolDictionaries: ''
         category: 'Ocompletion'

Then do the composition:

ECSelectorEntry subclass: #ODatedEntry
  uses: BidirectionalLink
         instanceVariableNames: 'date nextEntry previousEntry'
         classVariableNames: ''
         poolDictionaries: ''
         category: 'Ocompletion'

Now this doesn't work, because ODatedEntry doesn't have instance variables
named next and previous, but the methods of BidirectionalLink would like
to use them. Of course I could have used those names in the previous step
and (with a working implementation) this would just work out of the box. But
the example is about the instance variable mapping. Let's say ~ is the
composition operator which defines variable mapping for a class or a
method. Then I can write the following:

ECSelectorEntry subclass: #ODatedEntry
         uses: BidirectionalLink ~ { #nextEntry -> #next. #previousEntry -> #previous }
         instanceVariableNames: 'date nextEntry previousEntry'
         classVariableNames: ''
         poolDictionaries: ''
         category: 'Ocompletion'

This means: take all methods from BidirectionalLink, but replace the
variable named next with nextEntry and previous with previousEntry.
So now ODatedEntry understands #next, #next:, #previous, #unlink, etc.

This is the basic concept. There are some open questions, like:
- what happens when a composed method (or a method sent by a composed
method, etc) has a super send?
- will the class also get the methods of the superclasses of the "trait"?
- how does it work on the class side?
- what about class variables?
- what if I don't want to use all methods, just a few?

>
>
>>> Tell us more. The problem we faced was
>>> - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
>>
>> If you mean that a CompiledMethod of a trait cannot be added to the class' method dictionary, than that's not an issue. The current Trait implementation was changed, because shared CompiledMethods caused other problems.
>
> no this is not what I meant
>
>> If you mean that the same bytecodes can't be used, than that's neither a problem, because you can and should be compile the method again. Sharing trailer bytes may cause problems.
>> So adding a method from a trait to a class is simply recompiling it in the class' context.
>
> this is what we wanted to avoid.
> Also because you may have to recompile all the other methods of the class hierarchy because if a trait add an instance
> variable then you should recompile the subclasses when a trait get added with a state in the superclass.
My idea is that traits don't add instance variables. The user of the
trait maps the trait's variables to their own by name. So if a trait gets
a new variable, then only the trait and subclasses have to be recompiled.
The recompilation is postponed until a method of the trait which uses the
new instance variable is added to a class.

>
>> Instance variables should be used by name during compilation. If there's a name collision then use the instance variable map I mentioned above.
>
> what is that the instance variable map?
> take the time to write an example

See above.


Levente

>
>>> - initialization of instances variables at the trait level and the composition at the class levele
>>
>> You can always rename a trait's method in your class. So if the trait has an #initialize method, then simply rename it to #initializeFooBar and send it from the class' #initialize method.
>
> Yes this is what the javascript implementation does but this is not that nice but may be there is no better solution.
>
> So indeed we could think about adding state.
>
>
>
>>
>>
>> Levente
>>
>>>
>>>>
>>>>> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>>>>
>>>> Tools are a must. No tools - no users.
>>>
>>> Exact.
>>>
>>>>> So for now identifying traits and learning is the way. Then we can refactor, redesign
>>>>
>>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>>>
>>> Come on.
>>> I will not answer to such statement because I'm positive thinking.
>>>
>>> Stef
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [hidden email]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Eliot Miranda-2
Hi Levente,

    in my experience playing with the Dan and Alan Borning's multiple inheritance implementation getting things to work was one thing, reasonably straighforward, but getting tool support right (file-out format so that things filed back in correctly, etc) was another, an dth ebulk of the work. Looking at your proposal below I see no problem getting it to work but see lots of problems integrating it, e.g. with Monticello, etc.  Traits is already integrated with Monticello, supported with tests, etc.  As such it is a much less risky or effortful proposition than a new scheme.  So with that in mind are there important functional benefits of your scheme's direct state access as compared with traits that use accessors to access state that each user of a trait must implement?  i.e. what are the key benefits you see in direct inst var access?

best
Eliot

2010/10/24 Levente Uzonyi <[hidden email]>
On Sun, 24 Oct 2010, Stéphane Ducasse wrote:



2) well, this is difficult to get the money for the butter and the butter - we are trying.

If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.

I'm interested to hear more about that.

so can you explain what you meant because I did not understand it.

Okay, here is an example of my class composition idea. It works like Traits, but it supports state and there's no distinction between a trait and a class. Let's say I have a class named BidirectionalLink which can be used as a link in a linked list (with a head element). This will be used as a stateful trait. It's definition is like this:

Object subclass: #BidirectionalLink
       instanceVariableNames: 'next previous'
       classVariableNames: ''
       poolDictionaries: ''
       category: 'ClassCompositionExample'

It has a few methods:

BidirectionalLink >> next
       ^next

BidirectionalLink >> next: aBidirectionalLink
       next := aBidirectionalLink

BidirectionalLink >> previous
       ^previous

BidirectionalLink >> previous: aBidirectionalLink
       previous := aBidirectionalLink

BidirectionalLink >> unlink
       previous next: next.
       next previous: previous

BidirectionalLink >> linkAfter: aBidirectionalLink
       previous := aBidirectionalLink.
       next := aBidirectionalLink next.
       aBidirectionalLink next: self.
       next previous: self

I have an existing class, let's call it ODatedEntry :). It has the following definition:

ECSelectorEntry subclass: #ODatedEntry
       instanceVariableNames: 'date'
       classVariableNames: ''
       poolDictionaries: ''
       category: 'Ocompletion'

As you can see, it inherits some state and behavior from ECSelectorEntry. My goal is to use the instances of this class in a linked list. So these objects should implement the same protocol with the same behavior as BidirectionalLink. I can't make it a subclass of BidirectionalLink, because I also need the behavior and state from ECSelectorEntry and we don't have multiple inheritance. So I'll compose the two classes. First I add the necessary instance variables to the class. Let's call them nextEntry and previousEntry:

ECSelectorEntry subclass: #ODatedEntry
       instanceVariableNames: 'date nextEntry previousEntry'
       classVariableNames: ''
       poolDictionaries: ''
       category: 'Ocompletion'

Then do the composition:

ECSelectorEntry subclass: #ODatedEntry
       uses: BidirectionalLink
       instanceVariableNames: 'date nextEntry previousEntry'
       classVariableNames: ''
       poolDictionaries: ''
       category: 'Ocompletion'

Now this doesn't work, because ODatedEntry doesn't have instance variables named next and previous, but the methods of BidirectionalLink would like to use them. Of course I could have used those names in the previous step and (with a working implementation) this would just work out of the box. But the example is about the instance variable mapping. Let's say ~ is the composition operator which defines variable mapping for a class or a method. Then I can write the following:

ECSelectorEntry subclass: #ODatedEntry
       uses: BidirectionalLink ~ { #nextEntry -> #next. #previousEntry -> #previous }
       instanceVariableNames: 'date nextEntry previousEntry'
       classVariableNames: ''
       poolDictionaries: ''
       category: 'Ocompletion'

This means: take all methods from BidirectionalLink, but replace the variable named next with nextEntry and previous with previousEntry.
So now ODatedEntry understands #next, #next:, #previous, #unlink, etc.

This is the basic concept. There are some open questions, like:
- what happens when a composed method (or a method sent by a composed method, etc) has a super send?
- will the class also get the methods of the superclasses of the "trait"?
- how does it work on the class side?
- what about class variables?
- what if I don't want to use all methods, just a few?



Tell us more. The problem we faced was
       - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users

If you mean that a CompiledMethod of a trait cannot be added to the class' method dictionary, than that's not an issue. The current Trait implementation was changed, because shared CompiledMethods caused other problems.

no this is not what I meant

If you mean that the same bytecodes can't be used, than that's neither a problem, because you can and should be compile the method again. Sharing trailer bytes may cause problems.
So adding a method from a trait to a class is simply recompiling it in the class' context.

this is what we wanted to avoid.
Also because you may have to recompile all the other methods of the class hierarchy because if a trait add an instance
variable then you should recompile the subclasses when a trait get added with a state in the superclass.

My idea is that traits don't add instance variables. The user of the trait maps the trait's variables to their own by name. So if a trait gets
a new variable, then only the trait and subclasses have to be recompiled. The recompilation is postponed until a method of the trait which uses the new instance variable is added to a class.


Instance variables should be used by name during compilation. If there's a name collision then use the instance variable map I mentioned above.

what is that the instance variable map?
take the time to write an example

See above.


Levente


       - initialization of instances variables at the trait level and the composition at the class levele

You can always rename a trait's method in your class. So if the trait has an #initialize method, then simply rename it to #initializeFooBar and send it from the class' #initialize method.

Yes this is what the javascript implementation does but this is not that nice but may be there is no better solution.

So indeed we could think about adding state.





Levente



3) again if nobody does anything and we just all cry on ourselves then nothing will happen.

Tools are a must. No tools - no users.

Exact.

So for now identifying traits and learning is the way. Then we can refactor, redesign

Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.

Come on.
I will not answer to such statement because I'm positive thinking.

Stef
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Igor Stasenko
In reply to this post by Stéphane Ducasse
On 24 October 2010 23:45, Stéphane Ducasse <[hidden email]> wrote:

>>>
>>>>
>>>>> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>>>>
>>>> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.
>>>
>>> I'm interested to hear more about that.
>
> so can you explain what you meant because I did not understand it.
>
>
>>> Tell us more. The problem we faced was
>>>      - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
>>
>> If you mean that a CompiledMethod of a trait cannot be added to the class' method dictionary, than that's not an issue. The current Trait implementation was changed, because shared CompiledMethods caused other problems.
>
> no this is not what I meant
>
>> If you mean that the same bytecodes can't be used, than that's neither a problem, because you can and should be compile the method again. Sharing trailer bytes may cause problems.
>> So adding a method from a trait to a class is simply recompiling it in the class' context.
>
> this is what we wanted to avoid.

Why? I think it having many benefits comparing to 'compiled once' idea.
We're slowly moving towards multiple environemnts, right?
So, what if i may want to use same trait in two different
environments, and one of its methods
using #Foo variable, which depending on environment could be one or
another class,
or be a classvar with different value.

It could be quite powerful thing for testing purposes. Suppose you
wanna test something against new implementation of old class.
Then you don't need to waste a time and replace Foo -> Bar, you just
need to put it in use in different environment,
where Foo implemented differently.

There are other things.. Suppose my class using different compiler
(#compilerClass). It means that any methods in class should be
compiled using that compiler. And trait methods should obey the same
rule without exception.

> Also because you may have to recompile all the other methods of the class hierarchy because if a trait add an instance
> variable then you should recompile the subclasses when a trait get added with a state in the superclass.
>
Yes, same as if you adding an extra ivar to existing class, which
having subclasses.
Nothing really scary.

>> Instance variables should be used by name during compilation. If there's a name collision then use the instance variable map I mentioned above.
>
> what is that the instance variable map?
> take the time to write an example
>
>>>      - initialization of instances variables at the trait level and the composition at the class levele
>>
>> You can always rename a trait's method in your class. So if the trait has an #initialize method, then simply rename it to #initializeFooBar and send it from the class' #initialize method.
>
> Yes this is what the javascript implementation does but this is not that nice but may be there is no better solution.
>
> So indeed we could think about adding state.
>
>
>
>>
>>
>> Levente
>>
>>>
>>>>
>>>>> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>>>>
>>>> Tools are a must. No tools - no users.
>>>
>>> Exact.
>>>
>>>>> So for now identifying traits and learning is the way. Then we can refactor, redesign
>>>>
>>>> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>>>
>>> Come on.
>>> I will not answer to such statement because I'm positive thinking.
>>>
>>> Stef
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [hidden email]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>



--
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Smells looking at collections

Stéphane Ducasse
In reply to this post by Levente Uzonyi-2
Eliot the main interest is in not having the responsibility to initialize the state of traits by the composite.
Now since we know that doing for real is difficult this is why with did Nile: we build from scratch a real lib using traits
and we wanted to see if we wanted state. The results were not really positive.

Now also what people may not know is that the implementation of traits we have was a complete rewrite of the one
of nathanael because proto are good but are proto. We try to keep xp for the research. Now I would like to take the time to rethink traits
and its implementation.

Stef


On Oct 25, 2010, at 4:07 AM, Eliot Miranda wrote:

> Hi Levente,
>
>     in my experience playing with the Dan and Alan Borning's multiple inheritance implementation getting things to work was one thing, reasonably straighforward, but getting tool support right (file-out format so that things filed back in correctly, etc) was another, an dth ebulk of the work. Looking at your proposal below I see no problem getting it to work but see lots of problems integrating it, e.g. with Monticello, etc.  Traits is already integrated with Monticello, supported with tests, etc.  As such it is a much less risky or effortful proposition than a new scheme.  So with that in mind are there important functional benefits of your scheme's direct state access as compared with traits that use accessors to access state that each user of a trait must implement?  i.e. what are the key benefits you see in direct inst var access?
>
> best
> Eliot
>
> 2010/10/24 Levente Uzonyi <[hidden email]>
> On Sun, 24 Oct 2010, Stéphane Ducasse wrote:
>
>
>
> 2) well, this is difficult to get the money for the butter and the butter - we are trying.
>
> If you can compose classes the way you can add a trait to a class now with class and optional method level instance+class variable mapping, then you're done. It would be a lot simpler to use it _and_ it would also be a lot easier to implement it. Especially the tools part.
>
> I'm interested to hear more about that.
>
> so can you explain what you meant because I did not understand it.
>
> Okay, here is an example of my class composition idea. It works like Traits, but it supports state and there's no distinction between a trait and a class. Let's say I have a class named BidirectionalLink which can be used as a link in a linked list (with a head element). This will be used as a stateful trait. It's definition is like this:
>
> Object subclass: #BidirectionalLink
>        instanceVariableNames: 'next previous'
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'ClassCompositionExample'
>
> It has a few methods:
>
> BidirectionalLink >> next
>        ^next
>
> BidirectionalLink >> next: aBidirectionalLink
>        next := aBidirectionalLink
>
> BidirectionalLink >> previous
>        ^previous
>
> BidirectionalLink >> previous: aBidirectionalLink
>        previous := aBidirectionalLink
>
> BidirectionalLink >> unlink
>        previous next: next.
>        next previous: previous
>
> BidirectionalLink >> linkAfter: aBidirectionalLink
>        previous := aBidirectionalLink.
>        next := aBidirectionalLink next.
>        aBidirectionalLink next: self.
>        next previous: self
>
> I have an existing class, let's call it ODatedEntry :). It has the following definition:
>
> ECSelectorEntry subclass: #ODatedEntry
>        instanceVariableNames: 'date'
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'Ocompletion'
>
> As you can see, it inherits some state and behavior from ECSelectorEntry. My goal is to use the instances of this class in a linked list. So these objects should implement the same protocol with the same behavior as BidirectionalLink. I can't make it a subclass of BidirectionalLink, because I also need the behavior and state from ECSelectorEntry and we don't have multiple inheritance. So I'll compose the two classes. First I add the necessary instance variables to the class. Let's call them nextEntry and previousEntry:
>
> ECSelectorEntry subclass: #ODatedEntry
>        instanceVariableNames: 'date nextEntry previousEntry'
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'Ocompletion'
>
> Then do the composition:
>
> ECSelectorEntry subclass: #ODatedEntry
>        uses: BidirectionalLink
>        instanceVariableNames: 'date nextEntry previousEntry'
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'Ocompletion'
>
> Now this doesn't work, because ODatedEntry doesn't have instance variables named next and previous, but the methods of BidirectionalLink would like to use them. Of course I could have used those names in the previous step and (with a working implementation) this would just work out of the box. But the example is about the instance variable mapping. Let's say ~ is the composition operator which defines variable mapping for a class or a method. Then I can write the following:
>
> ECSelectorEntry subclass: #ODatedEntry
>        uses: BidirectionalLink ~ { #nextEntry -> #next. #previousEntry -> #previous }
>        instanceVariableNames: 'date nextEntry previousEntry'
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'Ocompletion'
>
> This means: take all methods from BidirectionalLink, but replace the variable named next with nextEntry and previous with previousEntry.
> So now ODatedEntry understands #next, #next:, #previous, #unlink, etc.
>
> This is the basic concept. There are some open questions, like:
> - what happens when a composed method (or a method sent by a composed method, etc) has a super send?
> - will the class also get the methods of the superclasses of the "trait"?
> - how does it work on the class side?
> - what about class variables?
> - what if I don't want to use all methods, just a few?
>
>
>
> Tell us more. The problem we faced was
>        - offset access = you cannot reuse bytecode of a trait because the order of the offset can be different in each trait users
>
> If you mean that a CompiledMethod of a trait cannot be added to the class' method dictionary, than that's not an issue. The current Trait implementation was changed, because shared CompiledMethods caused other problems.
>
> no this is not what I meant
>
> If you mean that the same bytecodes can't be used, than that's neither a problem, because you can and should be compile the method again. Sharing trailer bytes may cause problems.
> So adding a method from a trait to a class is simply recompiling it in the class' context.
>
> this is what we wanted to avoid.
> Also because you may have to recompile all the other methods of the class hierarchy because if a trait add an instance
> variable then you should recompile the subclasses when a trait get added with a state in the superclass.
>
> My idea is that traits don't add instance variables. The user of the trait maps the trait's variables to their own by name. So if a trait gets
> a new variable, then only the trait and subclasses have to be recompiled. The recompilation is postponed until a method of the trait which uses the new instance variable is added to a class.
>
>
> Instance variables should be used by name during compilation. If there's a name collision then use the instance variable map I mentioned above.
>
> what is that the instance variable map?
> take the time to write an example
>
> See above.
>
>
> Levente
>
>
>        - initialization of instances variables at the trait level and the composition at the class levele
>
> You can always rename a trait's method in your class. So if the trait has an #initialize method, then simply rename it to #initializeFooBar and send it from the class' #initialize method.
>
> Yes this is what the javascript implementation does but this is not that nice but may be there is no better solution.
>
> So indeed we could think about adding state.
>
>
>
>
>
> Levente
>
>
>
> 3) again if nobody does anything and we just all cry on ourselves then nothing will happen.
>
> Tools are a must. No tools - no users.
>
> Exact.
>
> So for now identifying traits and learning is the way. Then we can refactor, redesign
>
> Well, Traits are in Squeak since 2006, IIRC they were available a few years earlier. So in the last X (at least 4) years the only good candidate to become a Trait was Magnitude.
>
> Come on.
> I will not answer to such statement because I'm positive thinking.
>
> Stef
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
12