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. 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_. 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". That surprised me, but it does actually make sense. It does mean that (S + T) != (S - m) + (T - m). What I'd also expected is that aliasing (say, S @ {#m -> #z}) would mean "the resulting composition does not understand m". But it does. 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. Then resulting composition would have no conflicts, and would simply understand #(#* #+ #negated #reciprocal #one #zero). 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 +?