Hi everybody, specially traits people at Bern,
I'm reading the very interesting Traits papers, and although I haven't finished reading, I can't resist to ask some questions and give some comments:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
-I don't completely like the Substraction mechanism (TDrawing - {#hash}). It seems to me that it leads to the same problem described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
-a final small comment: I like what I'm reading.
That's all for the time being. I'll try to finish reading the papers. I mean, if you want to answer "that is explained later in the other paper!!!", feel free to do it ;-)
Regards,
German Morales
Hi German
Thanks for your interest in traits and asking these interesting questions. Here are the answers:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
First of all, it is to say that combining multiple traits that require the same method do not cause a conflict. This means that the requirements are just unified and can then be satisfied by implementing the required selector.
Since you asked about aliasing of required selectors, I figure that you are imagining the case where you want to combine two traits A and B which both have a requirement foo, and you want tho satisfy these requirements with two different methods (i.e., A>>foo should not be the same as B>>foo).
Unfortunately, this is not possible in the current version of traits. I'm sure you don't like to hear that, and to tell you the truth, I don't like it myself and that's one of the reasons why I'm working on an extended traits model (i.e., traits v2) now :-).
Also traits v1 can therefore not be used in a situation as pointed out above, this limitation is actually less severe than you might think because it does not appear so often in practice. (Most of the times, requirements for different implementations also have different names). In addition, it is important to understand that also all the other forms of mixins in Smalltalk suffer from the exact same limitation. The cause of this problem is that Smalltalk does not provide any kind of encapsulation/visibility mechanisms, but I'll come back to this issue later.
However, a straight-forward implementation of encapsulation/visibility does not necessarily solve this problem. A good example is Java, which does not provide any solution for the above problem either. The crux is that the Java encapsulation/visibility mechanisms (i.e., public, protected, private) are not fine-grained enough for this kind of situation. This means that if you have two interfaces A and B which both require a method foo, these requirements get always unified and there is no way a class can implement a different version of foo for the two interfaces!
Basically, there are two different solutions to this problem:
a) Consistent renaming. This means that each usage of foo in A is renamed to let's say fooA and each usage of foo in B is renamed to let's say fooB)
b) A good encapsulation/visibility mechanism. This means that we could actually say that the requirements for foo in A and B are encapsulated and therefore don't conflict in the class that combines A and B.
The problem with a) is the fact that this kind of renaming, especially when applied extensively, can make it really hard to understand the resulting code (in fact, it completely invalidates the flattening property). And because I don't like having such "dangerous mechanisms" if not absolutely necessary I decided against it.
Solution b) is less problematic. However, in order to do it right, I want to introduce a visibility/encapsulation mechanism that can not only be used for traits, but for regular ST classes in general. (Finally, we have the exact same problem already in traditional Smalltalk, becaus it is not possible to reuse a name in a subclass without affecting the meaning of the superclass). Also this solution tends to have negative impact on the flattening property, but we believe that we have found a nice way so that it only has minimal impact on it!
However, introducing such a mechanism into ST is not all trivial. Especially because I would like to have backwards compatibility, and I don't at all like the keyword based approaches in other languages (i.e., private, public, protected, etc.). Thus, I decided against incorporating this mechanism into the first version of traits. It would simply have been too much and so I preferred going step by step: First having a very simple version that just introduces the idea of traits (v1), and then having a version that makes traits muh more powerful and also gets rid of some other limitations in ST (v2).
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
Also here I can exactly see what you mean. In fact, I was having the exact same thought and the current prototype implementation actually still allows to subtract whole subtraits rather than individual methods.
The reason why I finally decided to take this out is that writing somethin like
Circle = TCircle + (TDrawing - TEquality)
exposes details about the implementation of the trait TDrawing to the outside. This means that if the implementor of TDrawing would later on decide to implement #=, #hash and #~= directly in the trait TDrawing rather than in a subtrait TEquality, this code would brake also the semantics of TDrawing is exactly the same as before!
Nevertheless, I agree with you that a concept like that would be very interesting and definitely had some nice advantages over specifying the excluded selectors one by one. And again, I have good news for you: We already have a solution for this problem that provides all the advantages of the approach you suggested and still does not expose details about the trait implementetions.
In fact, one of the key concepts of trait v2 is that we intrdoduce a notion of first-class interfaces/roles. And the nicest thing is that this notion also solves the problem with encapsulation/visibility that I pointed out above.
-a final small comment: I like what I'm reading.
Thanks!
Well, after writing this email I'm more than ever eager to get started with implementing the extended traits model. I can't wait until I can play with it.
Cheers, Nathanael
-----Original Message----- From: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] On Behalf Of German Morales Sent: Dienstag, 25. Februar 2003 14:48 To: squeak-dev@lists.squeakfoundation.org Subject: [Traits] questions/comments
Hi everybody, specially traits people at Bern,
I'm reading the very interesting Traits papers, and although I haven't finished reading, I can't resist to ask some questions and give some comments:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
-a final small comment: I like what I'm reading.
That's all for the time being. I'll try to finish reading the papers. I mean, if you want to answer "that is explained later in the other paper!!!", feel free to do it ;-)
Regards,
German Morales
Well... it seems you have everything under control. I'll just sit and wait for v2.
If I have some time I'll try v1, but I read in the swiki that parts of it doesn't work, so don't take it as a promise.
Cheers,
German Morales
It seems that Nathanael Schärli wrote:
Hi German
Thanks for your interest in traits and asking these interesting questions. Here are the answers:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
First of all, it is to say that combining multiple traits that require the same method do not cause a conflict. This means that the requirements are just unified and can then be satisfied by implementing the required selector.
Since you asked about aliasing of required selectors, I figure that you are imagining the case where you want to combine two traits A and B which both have a requirement foo, and you want tho satisfy these requirements with two different methods (i.e., A>>foo should not be the same as B>>foo).
Unfortunately, this is not possible in the current version of traits. I'm sure you don't like to hear that, and to tell you the truth, I don't like it myself and that's one of the reasons why I'm working on an extended traits model (i.e., traits v2) now :-).
Also traits v1 can therefore not be used in a situation as pointed out above, this limitation is actually less severe than you might think because it does not appear so often in practice. (Most of the times, requirements for different implementations also have different names). In addition, it is important to understand that also all the other forms of mixins in Smalltalk suffer from the exact same limitation. The cause of this problem is that Smalltalk does not provide any kind of encapsulation/visibility mechanisms, but I'll come back to this issue later.
However, a straight-forward implementation of encapsulation/visibility does not necessarily solve this problem. A good example is Java, which does not provide any solution for the above problem either. The crux is that the Java encapsulation/visibility mechanisms (i.e., public, protected, private) are not fine-grained enough for this kind of situation. This means that if you have two interfaces A and B which both require a method foo, these requirements get always unified and there is no way a class can implement a different version of foo for the two interfaces!
Basically, there are two different solutions to this problem:
a) Consistent renaming. This means that each usage of foo in A is renamed to let's say fooA and each usage of foo in B is renamed to let's say fooB)
b) A good encapsulation/visibility mechanism. This means that we could actually say that the requirements for foo in A and B are encapsulated and therefore don't conflict in the class that combines A and B.
The problem with a) is the fact that this kind of renaming, especially when applied extensively, can make it really hard to understand the resulting code (in fact, it completely invalidates the flattening property). And because I don't like having such "dangerous mechanisms" if not absolutely necessary I decided against it.
Solution b) is less problematic. However, in order to do it right, I want to introduce a visibility/encapsulation mechanism that can not only be used for traits, but for regular ST classes in general. (Finally, we have the exact same problem already in traditional Smalltalk, becaus it is not possible to reuse a name in a subclass without affecting the meaning of the superclass). Also this solution tends to have negative impact on the flattening property, but we believe that we have found a nice way so that it only has minimal impact on it!
However, introducing such a mechanism into ST is not all trivial. Especially because I would like to have backwards compatibility, and I don't at all like the keyword based approaches in other languages (i.e., private, public, protected, etc.). Thus, I decided against incorporating this mechanism into the first version of traits. It would simply have been too much and so I preferred going step by step: First having a very simple version that just introduces the idea of traits (v1), and then having a version that makes traits muh more powerful and also gets rid of some other limitations in ST (v2).
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
Also here I can exactly see what you mean. In fact, I was having the exact same thought and the current prototype implementation actually still allows to subtract whole subtraits rather than individual methods.
The reason why I finally decided to take this out is that writing somethin like
Circle = TCircle + (TDrawing - TEquality)
exposes details about the implementation of the trait TDrawing to the outside. This means that if the implementor of TDrawing would later on decide to implement #=, #hash and #~= directly in the trait TDrawing rather than in a subtrait TEquality, this code would brake also the semantics of TDrawing is exactly the same as before!
Nevertheless, I agree with you that a concept like that would be very interesting and definitely had some nice advantages over specifying the excluded selectors one by one. And again, I have good news for you: We already have a solution for this problem that provides all the advantages of the approach you suggested and still does not expose details about the trait implementetions.
In fact, one of the key concepts of trait v2 is that we intrdoduce a notion of first-class interfaces/roles. And the nicest thing is that this notion also solves the problem with encapsulation/visibility that I pointed out above.
-a final small comment: I like what I'm reading.
Thanks!
Well, after writing this email I'm more than ever eager to get started with implementing the extended traits model. I can't wait until I can play with it.
Cheers, Nathanael
-----Original Message----- From: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] On Behalf Of German Morales Sent: Dienstag, 25. Februar 2003 14:48 To: squeak-dev@lists.squeakfoundation.org Subject: [Traits] questions/comments
Hi everybody, specially traits people at Bern,
I'm reading the very interesting Traits papers, and although I haven't finished reading, I can't resist to ask some questions and give some comments:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
-a final small comment: I like what I'm reading.
That's all for the time being. I'll try to finish reading the papers. I mean, if you want to answer "that is explained later in the other paper!!!", feel free to do it ;-)
Regards,
German Morales
Hi German
I coded the complete week with it so it does work! But not as well as we would like Stef
On Saturday, March 1, 2003, at 04:41 PM, German Morales wrote:
Well... it seems you have everything under control. I'll just sit and wait for v2.
If I have some time I'll try v1, but I read in the swiki that parts of it doesn't work, so don't take it as a promise.
Cheers,
German Morales
It seems that Nathanael Schärli wrote:
Hi German
Thanks for your interest in traits and asking these interesting questions. Here are the answers:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
First of all, it is to say that combining multiple traits that require the same method do not cause a conflict. This means that the requirements are just unified and can then be satisfied by implementing the required selector.
Since you asked about aliasing of required selectors, I figure that you are imagining the case where you want to combine two traits A and B which both have a requirement foo, and you want tho satisfy these requirements with two different methods (i.e., A>>foo should not be the same as B>>foo).
Unfortunately, this is not possible in the current version of traits. I'm sure you don't like to hear that, and to tell you the truth, I don't like it myself and that's one of the reasons why I'm working on an extended traits model (i.e., traits v2) now :-).
Also traits v1 can therefore not be used in a situation as pointed out above, this limitation is actually less severe than you might think because it does not appear so often in practice. (Most of the times, requirements for different implementations also have different names). In addition, it is important to understand that also all the other forms of mixins in Smalltalk suffer from the exact same limitation. The cause of this problem is that Smalltalk does not provide any kind of encapsulation/visibility mechanisms, but I'll come back to this issue later.
However, a straight-forward implementation of encapsulation/visibility does not necessarily solve this problem. A good example is Java, which does not provide any solution for the above problem either. The crux is that the Java encapsulation/visibility mechanisms (i.e., public, protected, private) are not fine-grained enough for this kind of situation. This means that if you have two interfaces A and B which both require a method foo, these requirements get always unified and there is no way a class can implement a different version of foo for the two interfaces!
Basically, there are two different solutions to this problem:
a) Consistent renaming. This means that each usage of foo in A is renamed to let's say fooA and each usage of foo in B is renamed to let's say fooB)
b) A good encapsulation/visibility mechanism. This means that we could actually say that the requirements for foo in A and B are encapsulated and therefore don't conflict in the class that combines A and B.
The problem with a) is the fact that this kind of renaming, especially when applied extensively, can make it really hard to understand the resulting code (in fact, it completely invalidates the flattening property). And because I don't like having such "dangerous mechanisms" if not absolutely necessary I decided against it.
Solution b) is less problematic. However, in order to do it right, I want to introduce a visibility/encapsulation mechanism that can not only be used for traits, but for regular ST classes in general. (Finally, we have the exact same problem already in traditional Smalltalk, becaus it is not possible to reuse a name in a subclass without affecting the meaning of the superclass). Also this solution tends to have negative impact on the flattening property, but we believe that we have found a nice way so that it only has minimal impact on it!
However, introducing such a mechanism into ST is not all trivial. Especially because I would like to have backwards compatibility, and I don't at all like the keyword based approaches in other languages (i.e., private, public, protected, etc.). Thus, I decided against incorporating this mechanism into the first version of traits. It would simply have been too much and so I preferred going step by step: First having a very simple version that just introduces the idea of traits (v1), and then having a version that makes traits muh more powerful and also gets rid of some other limitations in ST (v2).
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
Also here I can exactly see what you mean. In fact, I was having the exact same thought and the current prototype implementation actually still allows to subtract whole subtraits rather than individual methods.
The reason why I finally decided to take this out is that writing somethin like
Circle = TCircle + (TDrawing - TEquality)
exposes details about the implementation of the trait TDrawing to the outside. This means that if the implementor of TDrawing would later on decide to implement #=, #hash and #~= directly in the trait TDrawing rather than in a subtrait TEquality, this code would brake also the semantics of TDrawing is exactly the same as before!
Nevertheless, I agree with you that a concept like that would be very interesting and definitely had some nice advantages over specifying the excluded selectors one by one. And again, I have good news for you: We already have a solution for this problem that provides all the advantages of the approach you suggested and still does not expose details about the trait implementetions.
In fact, one of the key concepts of trait v2 is that we intrdoduce a notion of first-class interfaces/roles. And the nicest thing is that this notion also solves the problem with encapsulation/visibility that I pointed out above.
-a final small comment: I like what I'm reading.
Thanks!
Well, after writing this email I'm more than ever eager to get started with implementing the extended traits model. I can't wait until I can play with it.
Cheers, Nathanael
-----Original Message----- From: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] On Behalf Of German Morales Sent: Dienstag, 25. Februar 2003 14:48 To: squeak-dev@lists.squeakfoundation.org Subject: [Traits] questions/comments
Hi everybody, specially traits people at Bern,
I'm reading the very interesting Traits papers, and although I haven't finished reading, I can't resist to ask some questions and give some comments:
-I see how the conflict resolution is applied for provided methods, but not for required methods. The same aliases mechanism is applied?
-I don't completely like the Substraction mechanism (TDrawing
- {#hash}). It seems to me that it leads to the same problem
described in "Fragile hierarchies". For example, in the example of Circle composed with TCircle and TDrawing - {#hash, #= and #~=}, if later TEquality adds a new method #?=, Circle will have a conflict. Perhaps instead of: Circle = TCircle + (TDrawing - {#hash, #= and #~=}) I would prefer: Circle = TCircle + (TDrawing - TEquality) ???
-a final small comment: I like what I'm reading.
That's all for the time being. I'll try to finish reading the papers. I mean, if you want to answer "that is explained later in the other paper!!!", feel free to do it ;-)
Regards,
German Morales
Prof. Dr. Stéphane DUCASSE (ducasse@iam.unibe.ch) http://www.iam.unibe.ch/~ducasse/ "if you knew today was your last day on earth, what would you do different? ... especially if, by doing something different, today might not be your last day on earth" Calvin&Hobbes
squeak-dev@lists.squeakfoundation.org