Hi,
there is a lot of discussion going on about how traits should actually 
work in PHP.
Currently, one of the main challenges seams to be to agree on a suitable 
mechanism to avoid breaking traits and there behavior. 
Eventually, there seams to be a large discomfiture on the excluding of 
methods and the interweaving of methods from different traits.
I can agree on the opinion, that a unconditional exclude mechanism could 
accidentally break traits. 
But, I really do like the notion to be able to interweave traits and 
compose something new from it, which results in an overlapping construct 
using the appropriate methods for a concrete problem. Well, this implies 
traits are not units of black-boxed reuse. They do act really 
fine-grained and will require the knowledge about the used methods.
Therefore, remove/exclude is bad, we need to get rid of it. 
There are some thoughts about aliasing. It seams to be not the 
natural/closest solution. Renaming semantics would be more natural, but 
it implies an exclude of the old method, too. Thus, renaming could 
accidentally breaking a trait. Eventually, renaming needs to be avoided, 
too.
Ok, lets get a step back and recall what traits have to achieve.
Traits try to be a construct to allow the reuse of a group of semantical 
related methods. 
They do not try to replace inheritance or the delegation patter. They 
are still valid means to reuse "complex behavior and state" things. 
Instead, the way to go with traits should be to reuse a small, 
predominantly independent (but semantically related) number of methods 
not justifying to build a full fledged class from them. Use traits to 
build a class from them, which adds some additional semantics/behavior 
to the set of methods got from the traits and build a complete blue 
print for objects from it.
The main thing here seams to be that the current proposal does not 
fulfill the claim to combine the traits properly in the case of 
conflicts. Instead, there is a lot of potential to break the traits 
behavior.
Let's try to find a notation where the traits are combined and conflicts 
are solved upfront, before being applied to the class. (This is even the 
way the implementation works right now.)
To get rid of exclude and rename I would like to propose the following:
//Example from the RFC with the cross-over conflict to be solved 
trait A { 
public function smallTalk() { 
echo 'a'; 
} 
public function bigTalk() { 
echo 'A'; 
} 
}
trait B { 
public function smallTalk() { 
echo 'b'; 
} 
public function bigTalk() { 
echo 'B'; 
} 
}
//here the new notion of combing traits and resolving conflicts upfront 
class Talker { 
use A, B { 
B::smallTalk instead A::smallTalk; 
A::bigTalk instead B::bigTalk; 
A::bigTalk as talk; 
} 
}
The new use is defined as use with a list of traits to be included 
into the class. 
Since the exclude is not appropriated, conflicts could be solved a lot 
more explicitly with the new instead keyword. 
It has be read as: use B::smallTalk instead of A::smallTalk, which 
solves the conflict explicitly and avoids the need for an exclude 
operator with the power to exclude arbitrary methods. 
If more traits are combined it could look like A:foo instead B::foo, C::foo;
To be able to reuse a method which is excluded this way the as 
keyword can be used. 
Read it like this: use A::bigTalk as talk in the class.
Think with this, it is not possible to remove a method somehow. 
This could be even superior to the "hidding" thing and the notion of 
"trait-local" methods since everything/any part of the semantics is 
explicitly available in the notation. This has not been the case for 
other notations so far. The trait-local things are nice, but complex and 
I would prefer to avoid them, since the proposed traits have a very 
clean and simple semantics. May be we could introduce them as addition 
in a later release.
Kind Regards 
Stefan
Hi,
there is a lot of discussion going on about how traits should actually
work in PHP.Currently, one of the main challenges seams to be to agree on a suitable
mechanism to avoid breaking traits and there behavior.
Eventually, there seams to be a large discomfiture on the excluding of
methods and the interweaving of methods from different traits.I can agree on the opinion, that a unconditional exclude mechanism could
accidentally break traits.
But, I really do like the notion to be able to interweave traits and
compose something new from it, which results in an overlapping construct
using the appropriate methods for a concrete problem. Well, this implies
traits are not units of black-boxed reuse. They do act really
fine-grained and will require the knowledge about the used methods.Therefore, remove/exclude is bad, we need to get rid of it.
There are some thoughts about aliasing. It seams to be not the
natural/closest solution. Renaming semantics would be more natural, but
it implies an exclude of the old method, too. Thus, renaming could
accidentally breaking a trait. Eventually, renaming needs to be avoided,
too.Ok, lets get a step back and recall what traits have to achieve.
Traits try to be a construct to allow the reuse of a group of semantical
related methods.
They do not try to replace inheritance or the delegation patter. They
are still valid means to reuse "complex behavior and state" things.
Instead, the way to go with traits should be to reuse a small,
predominantly independent (but semantically related) number of methods
not justifying to build a full fledged class from them. Use traits to
build a class from them, which adds some additional semantics/behavior
to the set of methods got from the traits and build a complete blue
print for objects from it.The main thing here seams to be that the current proposal does not
fulfill the claim to combine the traits properly in the case of
conflicts. Instead, there is a lot of potential to break the traits
behavior.Let's try to find a notation where the traits are combined and conflicts
are solved upfront, before being applied to the class. (This is even the
way the implementation works right now.)To get rid of exclude and rename I would like to propose the following:
//Example from the RFC with the cross-over conflict to be solved
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}//here the new notion of combing traits and resolving conflicts upfront
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}The new
useis defined as use with a list of traits to be included
into the class.
Since the exclude is not appropriated, conflicts could be solved a lot
more explicitly with the newinsteadkeyword.
It has be read as: use B::smallTalk instead of A::smallTalk, which
solves the conflict explicitly and avoids the need for an exclude
operator with the power to exclude arbitrary methods.
If more traits are combined it could look likeA:foo instead B::foo, C::foo;To be able to reuse a method which is excluded this way the
as
keyword can be used.
Read it like this: use A::bigTalk as talk in the class.Think with this, it is not possible to remove a method somehow.
This could be even superior to the "hidding" thing and the notion of
"trait-local" methods since everything/any part of the semantics is
explicitly available in the notation. This has not been the case for
other notations so far. The trait-local things are nice, but complex and
I would prefer to avoid them, since the proposed traits have a very
clean and simple semantics. May be we could introduce them as addition
in a later release.
I like this mechanism. This really does seem to be what I would use. 
It also treats developers with a bit of respect that they understand 
what they are doing and as such doesn't need to provide a wasteful 
safety net. No magic.
A question though (and I don't have any sort of examples to explain 
this better, so I hope you all follow).
If there are common names to methods in multiple traits (assume third 
party libraries), and you one trait::method over another (A::bigTalk 
instead B::bigTalk;),  this will surely break the b trait? B trait may 
well use its own bigTalk method. Instead it is going to end up using 
A's bigTalk.
A "way" (more of an idea than a real solution and the syntax is wild 
here) would be to support a "namespace" concept.
trait DTalker { 
function dTalk() { 
echo 'D'; 
} 
} 
trait CTalker requires DTalker { 
function cTalk() { 
$this->dTalk(); 
} 
class Talker { 
use ATalker as A, BTalker as B, CTalker 
function usingTraits() { 
$this->A::bigTalk(); 
$this->B::smallTalk(); 
$this->CTalker::cTalk();
// Maybe these are all the same method.
$this->CTalker::DTalker::dTalk();
$this->CTalker::dTalk();
$this->dTalk();
} 
}
Traits as namespaces would solve the issue of conflict in the class 
Talker (you would have to explicitly say which trait the method came 
from.
I don't know if this can all be resolved at compile time. Surely the 
use of call_user_func() and others would impact somehow.
If trait C requires trait D, then this may lead to longer namespaces - 
but from my understanding the purpose of namespaces is to resolve 
collisions, so it cannot be avoided when there are collisions. (Though 
my example doesn't collide - but that's not the point).
I hope this makes some sense.
Richard.
--
Richard Quadling 
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 
"Standing on the shoulders of some very clever giants!"
Hi Richard,
Richard Quadling schrieb:
Traits as namespaces would solve the issue of conflict in the class
Talker (you would have to explicitly say which trait the method came
from.
Yes, this would solve the conflicts, but is this really handy?
Every explicit reference to a trait/class name has to be adjusted if the
name changes or if there are any incompatible changes in the hierarchies.
Explicit references by names is probably always a solution, but not the
best. The inventors of the trait idea tried to avoid it in favor to
avoid the fragility introduced by it.
I don't know if this can all be resolved at compile time. Surely the
use ofcall_user_func()and others would impact somehow.If trait C requires trait D, then this may lead to longer namespaces -
but from my understanding the purpose of namespaces is to resolve
collisions, so it cannot be avoided when there are collisions. (Though
my example doesn't collide - but that's not the point).I hope this makes some sense.
It would be a possible way, but personally I would not like to go there.
Kind Regards 
Stefan
Hi Richard,
Richard Quadling schrieb:
Traits as namespaces would solve the issue of conflict in the class
Talker (you would have to explicitly say which trait the method came
from.Yes, this would solve the conflicts, but is this really handy?
Every explicit reference to a trait/class name has to be adjusted if the
name changes or if there are any incompatible changes in the hierarchies.
Explicit references by names is probably always a solution, but not the
best. The inventors of the trait idea tried to avoid it in favor to
avoid the fragility introduced by it.I don't know if this can all be resolved at compile time. Surely the
use ofcall_user_func()and others would impact somehow.If trait C requires trait D, then this may lead to longer namespaces -
but from my understanding the purpose of namespaces is to resolve
collisions, so it cannot be avoided when there are collisions. (Though
my example doesn't collide - but that's not the point).I hope this makes some sense.
It would be a possible way, but personally I would not like to go there.
I can certainly understand your reluctance. It does make things look 
complicated.
But my first reasoning for suggesting it is that we are have 
namespaces in PHP6 primarily to reduce the conflicts between built in 
classes and userland classes/libraries.
By having an alternative aliasing mechanism for traits, we now have 2 
mechanisms to learn, both of which resolve names in some way. (For: 
traits aren't namespaces, Against: Trait conflict resolution certainly 
looks like it could be solved with namespaces).
Your primary argument against them of "has to be adjusted if the name 
changes" holds true with namespaces any way. In fact if 
method/class/interface/function X becomes 
method/class/interface/function Y, I have to change something anyway.
So, this is the norm, not the exception.
My second reasoning is that namespaces act as encapulation. They are 
still white-box. But encapsulated. So inside the trait all the methods 
can talk to each other quite happily (statically or otherwise).
It just works and is based upon existing ideas (assuming we are in a PHP6).
--
Richard Quadling 
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 
"Standing on the shoulders of some very clever giants!"
Am 25.02.2008 um 20:33 schrieb Stefan Marr:
Hi,
there is a lot of discussion going on about how traits should actually
work in PHP.Currently, one of the main challenges seams to be to agree on a
suitable
mechanism to avoid breaking traits and there behavior.
Eventually, there seams to be a large discomfiture on the excluding
of methods and the interweaving of methods from different traits.I can agree on the opinion, that a unconditional exclude mechanism
could accidentally break traits.
But, I really do like the notion to be able to interweave traits and
compose something new from it, which results in an overlapping
construct using the appropriate methods for a concrete problem.
Well, this implies traits are not units of black-boxed reuse. They
do act really fine-grained and will require the knowledge about the
used methods.
Yes. This is how I understood them. I really don't think we need all
this complicated stuff for potential what-if situations that arise
from people not understanding how to use Traits. You are completely
right that Traits should not be regarded as black boxes.
I think I said it in an earlier mail - this entire discussion about
conflict resolving with aliasing etc is pretty void because it's
always assumed that Traits change, or developers using them don't
(want to?) know the inner workings. Traits are mixed into classes
statically, using an explicit syntactical facility. That means we can
assume the developer in question knows what he is doing. That also
means we can expect him to check for potential conflicts/breakage and
resolve it up front, as you're suggesting further down in your mail.
Therefore, remove/exclude is bad, we need to get rid of it.
There are some thoughts about aliasing. It seams to be not the
natural/closest solution. Renaming semantics would be more natural,
but it implies an exclude of the old method, too. Thus, renaming
could accidentally breaking a trait. Eventually, renaming needs to
be avoided, too.Ok, lets get a step back and recall what traits have to achieve.
Traits try to be a construct to allow the reuse of a group of
semantical related methods.
They do not try to replace inheritance or the delegation patter.
They are still valid means to reuse "complex behavior and state"
things.
Instead, the way to go with traits should be to reuse a small,
predominantly independent (but semantically related) number of
methods not justifying to build a full fledged class from them. Use
traits to build a class from them, which adds some additional
semantics/behavior to the set of methods got from the traits and
build a complete blue print for objects from it.The main thing here seams to be that the current proposal does not
fulfill the claim to combine the traits properly in the case of
conflicts. Instead, there is a lot of potential to break the traits
behavior.Let's try to find a notation where the traits are combined and
conflicts are solved upfront, before being applied to the class.
(This is even the way the implementation works right now.)
Winner. +1.
To get rid of exclude and rename I would like to propose the
following://Example from the RFC with the cross-over conflict to be solved
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}//here the new notion of combing traits and resolving conflicts
upfront
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}The new
useis defined as use with a list of traits to be
included into the class.
Since the exclude is not appropriated, conflicts could be solved a
lot more explicitly with the newinsteadkeyword.
It has be read as: use B::smallTalk instead of A::smallTalk, which
solves the conflict explicitly and avoids the need for an exclude
operator with the power to exclude arbitrary methods.
If more traits are combined it could look likeA:foo instead B::foo, C::foo;
How about "B::smallTalk supersedes/replaces A::smallTalk" ?
David
Stefan Marr wrote:
<snip>To get rid of exclude and rename I would like to propose the following:
//Example from the RFC with the cross-over conflict to be solved
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}//here the new notion of combing traits and resolving conflicts upfront
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}
This is far better than the original proposal.
My only objection is that this introduces two new keywords, trait and 
instead.  In addition, this can get very awkward if multiple traits 
(more than 2) implement the same method name.  I would prefer a simple 
recycling of the "=" sign for both use cases (I'd also accept = for 
override, "as" for alias).
class Talker { 
use A, B, C, D { 
smallTalk = A::smallTalk; // this says that if B, C or D implement 
smallTalk, it is ignored 
talk = A::bigTalk; 
} 
}
To everyone - this is an aliasing procedure, not a renaming one, and 
won't affect internal methods of a trait (such as if B::whatever used 
B::smallTalk), as Richard Quadling incorrectly suggested.
Greg
My only objection is that this introduces two new keywords, trait and
instead. In addition, this can get very awkward if multiple traits
(more than 2) implement the same method name. I would prefer a simple
recycling of the "=" sign for both use cases (I'd also accept = for
override, "as" for alias).class Talker {
use A, B, C, D {
smallTalk = A::smallTalk; // this says that if B, C or D implement
smallTalk, it is ignored
talk = A::bigTalk;
}
}
Well this is not just a different syntax, but an entirely different
approach. In Stefan's proposal one had to explicitly handle every
conflict manually. in your proposal you do not have to do this. As
trait's specifically wanted to get away from automatic conflict
resolution when things overlap, I think that Stefan's proposal makes
more sense.
BTW Stefan: Whats the syntax for when you want to override a trait
method with one inside the class definition?
I guess one would use "self::" like so:
class Talker { 
use A, B { 
B::smallTalk instead A::smallTalk; 
self::bigTalk instead B::bigTalk, A::bigTalk; 
A::bigTalk as talk; 
}
function smallTalk() { 
} 
}
I also assume that we would mandate signature compatibility (which
IMHO should only throw an E_STRICT and not a fatal like what we
currently do for inheritance in PHP6)?
regards, 
Lukas
Lukas Kahwe Smith schrieb:
class Talker {
use A, B, C, D {
smallTalk = A::smallTalk; // this says that if B, C or D implement
smallTalk, it is ignored
talk = A::bigTalk;
}
}Well this is not just a different syntax, but an entirely different
approach. In Stefan's proposal one had to explicitly handle every
conflict manually. in your proposal you do not have to do this.
I share this objection. Maybe a somewhat handier solution of my proposal
would be the option to leave out the method name, but I'm not quite sure
whether it is really readable:
class Talker { 
use A, B, C, D { 
B::smallTalk instead A, C, D; //to be read like: use B::smallTalk 
// instead the implementations form A, C, D 
} 
}
BTW Stefan: Whats the syntax for when you want to override a trait
method with one inside the class definition?I guess one would use "self::" like so:
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
self::bigTalk instead B::bigTalk, A::bigTalk;
A::bigTalk as talk;
}function smallTalk() {
}
}
Hm, personally, I would leave this out. The notion is that class
definitions will override trait methods in any case (even/especially if
traits methods are conflicting). So it would be fine to have this one
implicit. This would also avoid construction attempts like: A::bigTalk
instead self::bigTalk, A::bigTalk;
Kind Regards 
Stefan
Hi,
I had a thought about recursion (and self referencing) inside trait defined 
functions and the possible issues that might occur due to explicit/implicit 
conflict resolution and or aliasing/renaming (i'm not completely 
following what the status quo is regarding conflict resolution and/or 
aliasing and/or renaming, but it seems all share issues to some degree)
if you wish to ensure that a trait's method specifically always calls 
a method also defined in the same trait maybe syntax like the following could 
be used:
trait Foo { 
	function A($x) { 
		if ($x > 0) trait::A($x--); 
	}
function B() {
	trait::A(2);
}
function C() {
	self::B();
}
}
here 'trait::' would tell the compiler to always use the actual method 
from the trait in question (no idea how this would work in the guts of the 
engine ... apologies for my ignorance :-) and 'self::' would refer to whatever 
the method in question is as defined in the flatten, resulting class ... 
so that 'self::B()' would call 'B()' as defined in the trait only if it wasn't 
aliased/renamed/overloaded in the flatten, resulting class using said trait.
again I'm a little lost as to where the concept is at/going with regard to 
aliasing/renaming/conflict-resolution ... but afaict the idea for 'trait::' 
possibly offers a way out of potential problems (for the developer of a trait) 
in any case.
thanks for listening ... sorry for the noise (if it is noise ... Stefan, Lukas please 
be the judge :-)
rgds, 
Jochem
Stefan Marr schreef:
Lukas Kahwe Smith schrieb:
class Talker {
use A, B, C, D {
smallTalk = A::smallTalk; // this says that if B, C or D implement
smallTalk, it is ignored
talk = A::bigTalk;
}
}Well this is not just a different syntax, but an entirely different
approach. In Stefan's proposal one had to explicitly handle every
conflict manually. in your proposal you do not have to do this.
I share this objection. Maybe a somewhat handier solution of my proposal
would be the option to leave out the method name, but I'm not quite sure
whether it is really readable:class Talker {
use A, B, C, D {
B::smallTalk instead A, C, D; //to be read like: use B::smallTalk
// instead the implementations form A, C, D
}
}BTW Stefan: Whats the syntax for when you want to override a trait
method with one inside the class definition?I guess one would use "self::" like so:
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
self::bigTalk instead B::bigTalk, A::bigTalk;
A::bigTalk as talk;
}function smallTalk() {
}
}
Hm, personally, I would leave this out. The notion is that class
definitions will override trait methods in any case (even/especially if
traits methods are conflicting). So it would be fine to have this one
implicit. This would also avoid construction attempts like: A::bigTalk
instead self::bigTalk, A::bigTalk;Kind Regards
Stefan
"Stefan Marr" php@stefan-marr.de wrote in message 
news:47C574A9.1050600@stefan-marr.de...
class Talker {
use A, B, C, D {
B::smallTalk instead A, C, D; //to be read like: use B::smallTalk
// instead the implementations form A, C, D
}
}
Excuse me for just raising a suggestion: 
How about "B::smallTask over A, C, D"? 
(Use "over" instead of "instead")
Lukas Kahwe Smith wrote:
My only objection is that this introduces two new keywords, trait and
instead. In addition, this can get very awkward if multiple traits
(more than 2) implement the same method name. I would prefer a simple
recycling of the "=" sign for both use cases (I'd also accept = for
override, "as" for alias).class Talker {
use A, B, C, D {
smallTalk = A::smallTalk; // this says that if B, C or D implement
smallTalk, it is ignored
talk = A::bigTalk;
}
}Well this is not just a different syntax, but an entirely different
approach. In Stefan's proposal one had to explicitly handle every
conflict manually. in your proposal you do not have to do this. As
trait's specifically wanted to get away from automatic conflict
resolution when things overlap, I think that Stefan's proposal makes
more sense.BTW Stefan: Whats the syntax for when you want to override a trait
method with one inside the class definition?I guess one would use "self::" like so:
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
self::bigTalk instead B::bigTalk, A::bigTalk;
A::bigTalk as talk;
}function smallTalk() {
}
}I also assume that we would mandate signature compatibility (which
IMHO should only throw anE_STRICTand not a fatal like what we
currently do for inheritance in PHP6)?
Hi,
OK, since none of my suggestions are acceptable, let me put it this way: 
I am full -1 for traits if it introduces 2 new keywords.  Find a 
solution that does not, and I will change my vote.
Greg
Hi Gregory and others,
Traits rox! I will never use them cause I think in different way, 
but for many people this will be a great feature.
Gregory, the comment you added here:
OK, since none of my suggestions are acceptable, let me put it this way:
Childish story! I want my toy!
I am fully +1 to traits, unfortunately I cannot spend enough time to help 
with a useful idea :)
Best Regards, Dimitar Isusov
Hello Lukas,
you still cannot ignore basic inheritance or reuse rules. Protocols have 
to be respected -> E_FATAL, fix your code.
marcus
Wednesday, February 27, 2008, 1:49:58 PM, you wrote:
My only objection is that this introduces two new keywords, trait and
instead. In addition, this can get very awkward if multiple traits
(more than 2) implement the same method name. I would prefer a simple
recycling of the "=" sign for both use cases (I'd also accept = for
override, "as" for alias).class Talker {
use A, B, C, D {
smallTalk = A::smallTalk; // this says that if B, C or D implement
smallTalk, it is ignored
talk = A::bigTalk;
}
}
Well this is not just a different syntax, but an entirely different
approach. In Stefan's proposal one had to explicitly handle every
conflict manually. in your proposal you do not have to do this. As
trait's specifically wanted to get away from automatic conflict
resolution when things overlap, I think that Stefan's proposal makes
more sense.
BTW Stefan: Whats the syntax for when you want to override a trait
method with one inside the class definition?
I guess one would use "self::" like so:
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
self::bigTalk instead B::bigTalk, A::bigTalk;
A::bigTalk as talk;
}
function smallTalk() {
}
}
I also assume that we would mandate signature compatibility (which
IMHO should only throw anE_STRICTand not a fatal like what we
currently do for inheritance in PHP6)?
regards,
Lukas
Best regards, 
Marcus
Stefan Marr wrote: 
<snip>
<snip>//Example from the RFC with the cross-over conflict to be solved
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}//here the new notion of combing traits and resolving conflicts upfront
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}
Ok, let me give an example code and ask a few questions about it:
trait A { 
public function smallTalk() { 
return 'a'; 
} 
public function bigTalk() { 
return strtoupper( $this->smallTalk() ); 
} 
} 
trait B { 
public function smallTalk() { 
return 'b'; 
} 
public function bigTalk() { 
return strtoupper( $this->smallTalk() ); 
} 
} 
class Talker { 
use A, B { 
B::smallTalk instead A::smallTalk; 
A::bigTalk instead B::bigTalk; 
A::bigTalk as talk; 
} 
} 
// now to the questions 
$talker = new Talker(); 
echo $talker->talk(); // What does this echo? My assumption is 'B'. 
echo $talker->bigTalk(); // How about this? 
echo $talker->smallTalk(); // This should be 'b'.
All the discussion seems to be on not breaking a traits methods and to 
call internal methods from the trait. If this is the case, then the 
answer to the second question would be 'A', which would not break the 
trait's internal method call, but it seems less obvious to me.
-- 
"Joshua Thompson" spam.goes.in.here@gmail.com 
<http://www.schmalls.com
Hi Joshua,
Joshua Thompson schrieb:
trait A {
public function smallTalk() {
return 'a';
}
public function bigTalk() {
return strtoupper( $this->smallTalk() );
}
}
trait B {
public function smallTalk() {
return 'b';
}
public function bigTalk() {
return strtoupper( $this->smallTalk() );
}
}
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}
// now to the questions
$talker = new Talker();
echo $talker->talk(); // What does this echo? My assumption is 'B'.
echo $talker->bigTalk(); // How about this?
echo $talker->smallTalk(); // This should be 'b'.
Yes, right, the following class_at_runtime thing is would is produced
from the class definition and represents the class at runtime:
class_at_runtime Talker { 
public function smallTalk() { 
return 'b'; 
}
public function bigTalk() { 
return strtoupper( $this->smallTalk() ); 
}
public function talk() { 
return strtoupper( $this->smallTalk() ); 
} 
}
All the discussion seems to be on not breaking a traits methods and to
call internal methods from the trait. If this is the case, then the
answer to the second question would be 'A', which would not break the
trait's internal method call, but it seems less obvious to me.
Yes, the trait is "broken" somehow. But IMHO that is the way traits
should work (in its basic variant). The opportunity here is to name it
not "break a trait" but interweave traits, instead. This will require a
notion of white-boxed reuse, which might not be everybody's intend.
If there is really the need for trait-local methods, I would really like
the local keyword, since private as a keyword has already a valid
semantics with traits.
Private states, this method is merged into the trait (in case it does
not conflict with another method from another trait and is excluded
therefore) and takes part in common inheritance, but is not inherited to
subclasses since it is private.
The local-keyword would be needed here:
//Example from the RFC with the cross-over conflict to be solved 
trait A { 
local function smallTalk() { 
echo 'a'; 
} 
public function bigTalk() { 
return strtoupper( $this->smallTalk() ); 
} 
}
trait B { 
local function smallTalk() { 
echo 'b'; 
} 
public function bigTalk() { 
return strtoupper( $this->smallTalk() ); 
} 
}
class Talker { 
use A, B { 
// the smallTalk methods do not need to be handled here, 
// since they are trait local and not visible to the class 
A::bigTalk instead B::bigTalk; 
B::bigTalk as talk;  // in my original example the is A but B 
// makes more sense 
} 
}
This would result in the following:
class_at_runtime Talker { 
function \0A\0smallTalk() { 
return 'a'; 
}
function \0B\0smallTalk() { 
return 'b'; 
}
public function bigTalk() __Origin:A { 
return strtoupper( $this->smallTalk() );   // here we will have to 
		// mess around with the method-lookup, to achieve a 
// complete "alpha-renaming" (even for call_user_f*) 
}
public function talk() __Origin:B { 
return strtoupper( $this->smallTalk() ); //same as above 
} 
}
This would result in:
$t = new Talker(); 
echo $t->bigTalk(); // echos A 
echo $t->talk();    // echos B
Maybe this is the way most users would be comfortable with, but it is a 
bit more complex and I think we would need here the "local"-keyword 
definitely.
Kind Regards 
Stefan
<snip> // now to the questions $talker = new Talker(); echo $talker->talk(); // What does this echo? My assumption is 'B'. echo $talker->bigTalk(); // How about this? echo $talker->smallTalk(); // This should be 'b'.
Wouldn't traits as namespaces solve this?
It seems like an ideal solution.
--
Richard Quadling 
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 
"Standing on the shoulders of some very clever giants!"
-----Original Message-----
From: Stefan Marr [mailto:php@stefan-marr.de]
Sent: Monday, February 25, 2008 11:33 AM
To: internals Mailing List; Marcus Boerger
Subject: [PHP-DEV] How to build a real Trait thing without exclusion
and renaming//here the new notion of combing traits and resolving conflicts
upfront
class Talker {
use A, B {
B::smallTalk instead A::smallTalk;
A::bigTalk instead B::bigTalk;
A::bigTalk as talk;
}
}
Hi Stefan,
I think the discussion is going in the right direction but personally I 
had to think really hard to figure out what this code was going to do :)
The following is a suggestion which takes into account some of the 
discussions we've had including points both Lukas and Marcus have made 
on this list. I have not thought through all of the implementation 
details but I am quite sure we could implement such behavior.
The following code shows a few things:
- local properties which can be used in self-contained functionality. 
 The storage is guaranteed to stay internal and will not clash with the
 aggregating class.
- methods are by default hidden to the aggregating class and bound to 
 the trait (as Marcus pointed out the method name would be mangled with
 the trait's name)
- You can expose any method you want either by doing a "use TraitA *" 
 for all methods or by explicitly exposing methods to a specific method
 in the class. Note: This is the equivalent of aliasing. The original
 mangled method in the Trait doesn't disappear but you can override it
 with a new method.
Unlike what some have said that this is better solved with MI or 
Delegation as opposed to Traits I don't subscribe to that. I believe 
this suggestion still gives you the benefits of copy&paste ala Traits 
but adds more structure, a more useful ability to encapsulate 
functionality which is very often the case when Trait like functionality 
is needed (stateful traits), and most important, I think it's easy to 
understand and read.
trait MyDebug { 
	local $counter = 1;
function showTrace() {
	printf("Called this %d time(s)\n", $this->counter++);
 `debug_backtrace()`;
}
}
trait MyTicks { 
	local $counter = 0;
function logIncrement() {
	// Log when we incremented the counter
}
function incTicks() {
	$this->logIncrement();
	return $this->counter++;
}
}
class MyClock { 
	use MyDebug *; 
	use MyTicks { 
		timeInTicks = inTicks; 
		// Don't want to see logIncrement() 
	}
function display() {...}
}
Andi
Andi Gutmans wrote:
Hi Stefan,
I think the discussion is going in the right direction but personally I
had to think really hard to figure out what this code was going to do :)The following is a suggestion which takes into account some of the
discussions we've had including points both Lukas and Marcus have made
on this list. I have not thought through all of the implementation
details but I am quite sure we could implement such behavior.The following code shows a few things:
- local properties which can be used in self-contained functionality.
The storage is guaranteed to stay internal and will not clash with the
aggregating class.- methods are by default hidden to the aggregating class and bound to
the trait (as Marcus pointed out the method name would be mangled with
the trait's name)- You can expose any method you want either by doing a "use TraitA *"
for all methods or by explicitly exposing methods to a specific method
in the class. Note: This is the equivalent of aliasing. The original
mangled method in the Trait doesn't disappear but you can override it
with a new method.Unlike what some have said that this is better solved with MI or
Delegation as opposed to Traits I don't subscribe to that. I believe
this suggestion still gives you the benefits of copy&paste ala Traits
but adds more structure, a more useful ability to encapsulate
functionality which is very often the case when Trait like functionality
is needed (stateful traits), and most important, I think it's easy to
understand and read.trait MyDebug {
local $counter = 1;function showTrace() {
printf("Called this %d time(s)\n", $this->counter++);
debug_backtrace();
}
}trait MyTicks {
local $counter = 0;function logIncrement() {
// Log when we incremented the counter
}function incTicks() {
$this->logIncrement();
return $this->counter++;
}
}class MyClock {
use MyDebug *;
use MyTicks {
timeInTicks = inTicks;
// Don't want to see logIncrement()
}function display() {...}
}Andi
I was working on a detailed RFC of something along these lines. I didn't 
include the local keyword, instead I went the route of stateful traits 
and forced the definition of which scope in the class. I also tried to 
keep the number of keywords to 1 (trait).
I will keep working on it, and hopefully post it tomorrow for review.
-- 
"Joshua Thompson" spam.goes.in.here@gmail.com 
<http://www.schmalls.com
-----Original Message-----
From: Joshua Thompson [mailto:spam.goes.in.here@gmail.com]
Sent: Wednesday, February 27, 2008 6:54 PM
To: internals@lists.php.net
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingI was working on a detailed RFC of something along these lines. I
didn't
include the local keyword, instead I went the route of stateful traits
and forced the definition of which scope in the class. I also tried to
keep the number of keywords to 1 (trait).I will keep working on it, and hopefully post it tomorrow for review.
OK but I wouldn't get too caught up on the number of keywords although 
we obviously don't want too many.
By the way one thing I left out of my proposal (mistakenly) was that 
local can also be used on a function so that "use TraitA *" wouldn't 
include it in the aggregating class.
Andi
Hi,
Joshua Thompson schrieb:
Andi Gutmans wrote:
The following code shows a few things:
- local properties which can be used in self-contained functionality.
The storage is guaranteed to stay internal and will not clash with the
aggregating class.
Yes, it is a nice to have.
- methods are by default hidden to the aggregating class and bound to
the trait (as Marcus pointed out the method name would be mangled with
the trait's name)
Hm, ok. It is the pessimistic counterpart to my proposal. In general,
I'm much more optimistic and would prefer to teach developers to use
proper naming to avoid conflicts. But if there is no other way to go, it
is ok.
I was working on a detailed RFC of something along these lines. I didn't
include the local keyword, instead I went the route of stateful traits
and forced the definition of which scope in the class. I also tried to
keep the number of keywords to 1 (trait).I will keep working on it, and hopefully post it tomorrow for review.
Looking forward to read it :)
Kind Regards 
Stefan
Hello Stefan,
Thursday, February 28, 2008, 8:30:48 AM, you wrote:
Hi,
Joshua Thompson schrieb:
Andi Gutmans wrote:
The following code shows a few things:
- local properties which can be used in self-contained functionality.
The storage is guaranteed to stay internal and will not clash with the
aggregating class.
Yes, it is a nice to have.
- methods are by default hidden to the aggregating class and bound to
the trait (as Marcus pointed out the method name would be mangled with
the trait's name)
Hm, ok. It is the pessimistic counterpart to my proposal. In general,
I'm much more optimistic and would prefer to teach developers to use
proper naming to avoid conflicts. But if there is no other way to go, it
is ok.
I did a lot of tutorials and sessions on object oriented PHP and I have 
learned one thing we have to make it easy  and limit the ability to use 
stuff wrong. In other words we have to be pessimistic. Otherwise we end up 
in a mess.
I was working on a detailed RFC of something along these lines. I didn't
include the local keyword, instead I went the route of stateful traits
and forced the definition of which scope in the class. I also tried to
keep the number of keywords to 1 (trait).I will keep working on it, and hopefully post it tomorrow for review.
Looking forward to read it :)
Same here
Best regards, 
Marcus
Hi!
trait MyDebug {
local $counter = 1;
IIRC we don't have keyword "local". Why not "private" or "static"?
class MyClock {
use MyDebug *;
use MyTicks {
timeInTicks = inTicks;
This looks like code which does assignment. How I am supposed to 
understand from it that a new method for MyClock API is born?
In any case, why you need timeInTicks at all? If you need it public, why 
not write an accessor? It'd be better OO anyway, since MyClock's clients 
can't know about MyTicks's details or even its existence.
Stanislav Malyshev, Zend Software Architect 
stas@zend.com   http://www.zend.com/ 
(408)253-8829   MSN: stas@zend.com
-----Original Message-----
From: Stanislav Malyshev [mailto:stas@zend.com]
Sent: Wednesday, February 27, 2008 7:07 PM
To: Andi Gutmans
Cc: php@stefan-marr.de; internals Mailing List
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingHi!
trait MyDebug {
local $counter = 1;IIRC we don't have keyword "local". Why not "private" or "static"?
I wouldn't get too caught up on the naming at this point but rather the 
functionality.
class MyClock {
use MyDebug *;
use MyTicks {
timeInTicks = inTicks;This looks like code which does assignment. How I am supposed to
understand from it that a new method for MyClock API is born?In any case, why you need timeInTicks at all? If you need it public,
why
not write an accessor? It'd be better OO anyway, since MyClock's
clients
can't know about MyTicks's details or even its existence.
This is just an example of being able to alias a method from a trait. 
Assuming two traits would use the same name this would give you the 
ability to include it under a different name. 
The point is we can alias but we can not remove.
Andi
This is just an example of being able to alias a method from a trait.
Assuming two traits would use the same name this would give you the
ability to include it under a different name.
The point is we can alias but we can not remove.
That's what I am asking - why alias? You have perfectly good name for 
each one - A::whatever and B::whatever - which are unique. Why you need 
any more aliases?
Stanislav Malyshev, Zend Software Architect 
stas@zend.com   http://www.zend.com/ 
(408)253-8829   MSN: stas@zend.com
-----Original Message-----
From: Stanislav Malyshev [mailto:stas@zend.com]
Sent: Wednesday, February 27, 2008 11:21 PM
To: Andi Gutmans
Cc: php@stefan-marr.de; internals Mailing List
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingThis is just an example of being able to alias a method from a
trait.
Assuming two traits would use the same name this would give you the
ability to include it under a different name.
The point is we can alias but we can not remove.That's what I am asking - why alias? You have perfectly good name for
each one - A::whatever and B::whatever - which are unique. Why you
need
any more aliases?
The idea of Traits (whether you agree with it or not) is about a more 
flexible way of assembling classes and reusing pieces of functionality. 
The paradigm is different from inheritance/interfaces so the 
A::whatever/B::whatever is really not relevant in this context unless I 
have completely misunderstood you but I don't think I have.
Andi
Hello Stanislav,
as much as what you say is true, it forces you to type a lot which is 
error prone. So when you want to make a function public then you need to do: 
function whatever() { 
A::whatever(); 
} 
And actually you have to repeat the protocol and there the fun begins. Not 
to begin even discussing the overhead of an additional userspace method 
call that does not do anything. Aliasing is pretty helpful. But as Andi 
said you might disagree.
marcus
Thursday, February 28, 2008, 8:21:22 AM, you wrote:
This is just an example of being able to alias a method from a trait.
Assuming two traits would use the same name this would give you the
ability to include it under a different name.
The point is we can alias but we can not remove.
That's what I am asking - why alias? You have perfectly good name for
each one - A::whatever and B::whatever - which are unique. Why you need
any more aliases?Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Best regards, 
Marcus
Hello Andi,
I agree with Stas about 'local' and actually his reasoning is why I 
simply suggested 'private'. That also has the advantage that people already 
know what it does.
marcus
Thursday, February 28, 2008, 5:14:17 AM, you wrote:
-----Original Message-----
From: Stanislav Malyshev [mailto:stas@zend.com]
Sent: Wednesday, February 27, 2008 7:07 PM
To: Andi Gutmans
Cc: php@stefan-marr.de; internals Mailing List
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingHi!
trait MyDebug {
local $counter = 1;IIRC we don't have keyword "local". Why not "private" or "static"?
I wouldn't get too caught up on the naming at this point but rather the
functionality.
class MyClock {
use MyDebug *;
use MyTicks {
timeInTicks = inTicks;This looks like code which does assignment. How I am supposed to
understand from it that a new method for MyClock API is born?In any case, why you need timeInTicks at all? If you need it public,
why
not write an accessor? It'd be better OO anyway, since MyClock's
clients
can't know about MyTicks's details or even its existence.
This is just an example of being able to alias a method from a trait.
Assuming two traits would use the same name this would give you the
ability to include it under a different name.
The point is we can alias but we can not remove.
Andi
Best regards, 
Marcus
That's fine. I'm not attached to any name just the concept :)
-----Original Message-----
From: Marcus Boerger [mailto:helly@php.net]
Sent: Thursday, February 28, 2008 6:42 AM
To: Andi Gutmans
Cc: Stas Malyshev; php@stefan-marr.de; internals Mailing List
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingHello Andi,
I agree with Stas about 'local' and actually his reasoning is why I
simply suggested 'private'. That also has the advantage that people
already
know what it does.marcus
Thursday, February 28, 2008, 5:14:17 AM, you wrote:
-----Original Message-----
From: Stanislav Malyshev [mailto:stas@zend.com]
Sent: Wednesday, February 27, 2008 7:07 PM
To: Andi Gutmans
Cc: php@stefan-marr.de; internals Mailing List
Subject: Re: [PHP-DEV] How to build a real Trait thing without
exclusion and renamingHi!
trait MyDebug {
local $counter = 1;IIRC we don't have keyword "local". Why not "private" or "static"?
I wouldn't get too caught up on the naming at this point but rather
the
functionality.class MyClock {
use MyDebug *;
use MyTicks {
timeInTicks = inTicks;This looks like code which does assignment. How I am supposed to
understand from it that a new method for MyClock API is born?In any case, why you need timeInTicks at all? If you need it
public,
why
not write an accessor? It'd be better OO anyway, since MyClock's
clients
can't know about MyTicks's details or even its existence.This is just an example of being able to alias a method from a
trait.
Assuming two traits would use the same name this would give you the
ability to include it under a different name.
The point is we can alias but we can not remove.Andi
Best regards,
Marcus