On May 30, 2013, at 11:03 AM, Frank Shearar <frank.shearar@gmail.com> wrote:
Hi Stef,
Indeed you'd normally not double apply a trait. I want to do that here for explanatory purposes, to show that a field is the melding of two groups.
As it turns out, this double application merely highlights my underlying issues. My problems would still be there whenever I wanted to compose traits that shared requirements.
oki
I had understood the "symmetric composition annihilates conflicting methods" in "Traits: composable units of behaviour" to mean that the composition would not have such methods _at all_.
No. This sentence is strange. But
In Pharo, if you have two traits S and T, and a common method m, the composition S + T does contain m. If S and T implement m differently, the resulting m is "self traitConflict". If both S and T implement m as "self requirement", the resulting composition's m is also "self requirement".
for requirement this is special and not well implemented in Pharo. if you have a method T1>>m ^ 42 T2>>m ^ 66 T = T1 + T2 => you have to redefine m in T T = T1-m + T2 => you get m -> 66 Now you can also alias it: ie you give a new name to the method m You can read freezable traits because there is a nice explanation.
That surprised me, but it does actually make sense. It does mean that (S + T) != (S - m) + (T - m).
I do not know :) what I know is that (S + T) can have a conflict ion m while (S - m) + (T - m) ensure you do not have a conflict
What I'd also expected is that aliasing (say, S @ {#m -> #z}) would mean "the resulting composition does not understand m". But it does.
No this is just aliasing not renaming because we cannot resolve statically renaming in dynamic language.
So in my case, I had expected that TGroup @ {#identity->#zero. #* -> #+. #inverse->#negated} would result in a Trait that didn't define #identity or #inverse, and that TGroup @ {#identity->#one. #inverse->#reciprocal} would likewise not define #identity or #inverse.
Yes I see what you mean. May be this is an implementation problem. Because we could remove the origin of the bound methods
Then resulting composition would have no conflicts, and would simply understand #(#* #+ #negated #reciprocal #one #zero).
Yes this is probably a bug of the implemantation. I do not remember what we wrote in the papers
frank
On 30 May 2013, at 7:51, stephane ducasse <stephane.ducasse@free.fr> wrote:
Hi frank
normally it does not make sense to use two times the same trait. So I do not really understand how it could work.
So now when you have two traits T1 T2
minus lets you erase selectively one message x from T1 if it is also available in T2 and without having to redefine it into the composite.
Stef
I have a Trait TGroup that requires #*, #identity and #inverse. I want to construct a TField by composing TGroup with itself. One TGroup will form the operations #*, #one, and #reciprocal while the other will form #+, #zero and #negated.
I don't want #identity or #inverse, because these apply to one operation, and it makes TField's API ambiguous. That's what TraitExclusion is for.
I had thought I could say
(TGroup @ {#identity->#zero. #* -> #+. #inverse->#negated} + TGroup @ {#identity->#one. #inverse->#reciprocal}) - {#identity. #inverse}
but TraitComposition >> #- says that exclusion binds tighter than +. So in effect the above composition is the same as
TGroup @ {#identity->#zero. #* -> #+. #inverse->#negated} + (TGroup @ {#identity->#one. #inverse->#reciprocal} - {#identity. #inverse})
In short, to remove the undesirable #identity and #inverse I have to exclude from both sides of the composition:
TGroup @ {#identity->#zero. #* -> #+. #inverse->#negated} - {#identity. #inverse} + TGroup @ {#identity->#one. #inverse->#reciprocal} - {#identity. #inverse}
My question is this: what is the reason for - binding more tightly than +? Why is it _not_ desirable to have - distribute over +?