Re: [PHP-DEV] RFC: Traits for PHP
Hello Andi, I mentioned something along those lines as well. And I guess we both come from the side that a) we think the feature as such is useful and b) needs to be implemented in a way that we can use as much of the engine infrastructure as possible and c) not interfere with the way PHP works. That said we should not support hiding or dropping/removing of methods but simply making them private. Also we should make properties by default static to the the Trait, maybe disallowing implicit properties, so that we know the trait methods do bind the properties corredctly. Then for aliasing we can support public or protected aliases or just allowing to expose trait methods with a different visibility. This should not cause trouble as we can enforce conflict resolution. With such a feature set we are imo very flexible. marcus Thursday, February 21, 2008, 7:09:27 PM, you wrote: See below: -Original Message- From: Lukas Kahwe Smith [mailto:[EMAIL PROTECTED] Sent: Thursday, February 21, 2008 12:41 AM To: Andi Gutmans Cc: [EMAIL PROTECTED]; internals@lists.php.net; Marcus Börger; Johannes Schlüter; Sebastian Bergmann; Alexandre Bergel; Falko Menge; Sara Golemon; [EMAIL PROTECTED] Subject: Re: [PHP-DEV] RFC: Traits for PHP On 21.02.2008, at 03:26, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Of course this could be nice, but I think this is maybe the point where one should move to delegate? I don't think so. I think the value here is not copypaste but to be able to encapsulate some functionality which a class can be decorated with. Giving a basic storage mechanism to that would be very beneficial in a large amount of uses. Again, I am proposing private storage only which would be for internal use-only by the decorating methods. b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I am probably not seeing the obvious here, but how does making the function private solve the naming collisions? My concern about removing/aliasing functions is that you can really do some very funky stuff. It almost takes me back to the spaghetti code days where you can jump into code someplace in the middle. My proposal would make Traits a bit stricter and ensure that the original interface would still exist after it is aggregated. Either by honoring the interface and redefining methods which are consistent with the Trait or by leaving the original methods around as privates so that they can still reference each other. I think being able to remove a method which may need to be used by some internal method is a bit too chaotic. When you're inheriting large code bases it can become complicated to manage. I very much see the value of Traits but I think we should also consider making them a bit stricter. Btw, the private property discussion is different from the 2nd one. They are mutually exclusive. The latter idea would give more structure, still enforce a contract but should provide the same value. I am not convinced it's feasible on an implementation side but I think we should first consider it from a functional point of view. Andi Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Lukas, Thursday, February 21, 2008, 9:41:10 AM, you wrote: On 21.02.2008, at 03:26, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Of course this could be nice, but I think this is maybe the point where one should move to delegate? b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I am probably not seeing the obvious here, but how does making the function private solve the naming collisions? Private classes are from a users perspective bound to the implementing class. That would be the Trait. And from a compiler/executors point of view they are prefixed with the implementing class. That would be the Ttrait as well. So three functions f, one of Trait a, one of Trait b and one of the class C itself would all have different names and would all resolve. But sure they would scare the hell for any user so lets not do any of this. For the sake of clarification here comes anyway: Trait a { function f() {} } Trait b { function f() {} } class c { uses a, b; function f() {} } Reflection(c): function \0a\0f function a::f function \0b\0f function b::f function ffunction f All nicely callable using array syntax: class d extends c { function t() { call_user_func(array($this, a::f)): call_user_func(array($this, b::f)): call_user_func(array($this, f)): } } $o = new c: $o-test(); Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Marcus Boerger schrieb: Trait a { function f() {} } Trait b { function f() {} } class c { uses a, b; function f() {} } Reflection(c): function \0a\0f function a::f function \0b\0f function b::f function ffunction f All nicely callable using array syntax: class d extends c { function t() { call_user_func(array($this, a::f)): call_user_func(array($this, b::f)): call_user_func(array($this, f)): } } $o = new c: $o-test(); May be I don't get the point completly, but having this, every thing what traits are trying to solve is lost... IMHO Instead, you are playing with the devil (C++ multiple-inheritance). The main part of the trait idea is to be able to solve conflicts explicitly. Think this is the major contribution of traits and the things being discussed here right now are not THIS kind of traits anymore. Your other mail from today goes in the same direction. I don't feel comfortable with this :( I will put together some thoughts on how we could build real traits semantics with the intended benefits you might be a bit more comfortable with. But I absolutely think the proposals from the last days are going in the wrong direction. Instead of abusing the traits idea for this, it would be a valuable contribution to make a cut and drop the traits ideas for the sake of simplicity and use some mixin mechanism instead. I'll try to have a better real trait thing ready in this evening. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi! The main part of the trait idea is to be able to solve conflicts explicitly. Think this is the major contribution of traits and the things being discussed here right now are not THIS kind of traits anymore. What I still don't understand it's how you can solve these conflicts at all. I.e., suppose you have Counter API and DBConnection API on each of which you have clean() method - for Counter it resets it to zero and for DB it resets authentication details. How it is possible to resolve it in any way so that resulting class would support both APIs? -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Stanislav Malyshev schrieb: What I still don't understand it's how you can solve these conflicts at all. I.e., suppose you have Counter API and DBConnection API on each of which you have clean() method - for Counter it resets it to zero and for DB it resets authentication details. How it is possible to resolve it in any way so that resulting class would support both APIs? Would exactly do you mean with API? And how would you solve this problem without traits? Traits can not solve stuff like colliding methods with colliding semantics in interfaces. One solution would be to do the following: trait Counter { public function clean() { $this-setCntValue(0); } } trait DBConnection { public function clean() { // one problem we probably should not // discuss here is the naming, think it // should be named resetCredentials $this-setCredentials(null); } } class DBCounter { use Counter { !clean, cleanCounter = clean } use DBConnection { !clean, resetCredentials = clean } } This would be a class reusing the behavior implemented in both traits, and this is the contribution of the traits idea. With mixins this wouldn't be possible and C++ multiple-inheritance would introduce fragility. If DBCounter should implement ICounter and IDBConnection with each having a clean method, there is no meaningful possible implementation within a single class. Since the semantics of the two clean methods are not as near as it would be necessary. and a class DBCounter { use Counter { !clean, cleanCounter = clean } use DBConnection { !clean, resetCredentials = clean } public function clean() { $this-cleanCounter(); $this-resetCredentials(); } } would be a bit pointless, but possible... Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
-Original Message- From: Stanislav Malyshev [mailto:[EMAIL PROTECTED] Sent: Friday, February 22, 2008 9:21 AM To: Lukas Kahwe Smith Cc: Gregory Beaver; Marcus Boerger; [EMAIL PROTECTED]; Evert|Rooftop; internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP Hi! A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private How you are going to do that? I think it's possible to do this but I haven't had time to dive deeper in the past couple of days. In my opinion the benefits of doing Traits in this way would be significant. You would still get the benefits of the original Traits proposal but it would provide stronger encapsulation and less potential for breakage (on par with typical OO polymorphism). In addition I really believe that enabling state is extremely important to make this a commonly useful feature (either via private or via a local like Stefan suggested). I won't be back at work until Tuesday but I will try and find some time to figure out if this can be implemented. I am pretty sure it can if during compilation of the Trait we mangle the propertiesmethods similar to private propertiesmethods using the Trait's name; and then when we flatten into a class then for the methods we expose we make sure the mangled methods use the new method's op_array. This should not be too hard and as Traits flattening does not require the same semantics as inheritance I think it should be quite doable. Bed time over here but I wanted to drop a short note so you didn't think I dropped of the face of the planet in the midst of this interesting discussion :) Andi -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Gregory Beaver wrote: So, as you can see, all of the trait methods are available as regular methods except for A::a which is overridden by B::a. If the order were reversed, i.e. traits B, A then $a-a() would instead call A::a. I could see this becoming a problem when it plays along with namespaces. Let me modify your example a little bit to show what I mean. Some/Name/Space/A.php ?php namespace Some::Name::Space; trait A { function myfunc(){ echo 'myfunc';} function a(){ echo 'Some::Name::Space::A::a';} } ? Some/Other/Name/Space/A.php ?php namespace Some::Other::Name::Space; trait A { function a(){ echo 'Some::Other::Name::Space::B::a';} function another(){echo 'another';} } ? Blah.php ?php class Blah extends... implements... traits Some::Name::Space::A, Some::Other::Name::Space::A { } $a = new Blah(); $a-myfunc(); // myfunc $a-a(); // Some::Other::Name::Space::B::a $a-another(); // another $a-{'Some::Name::Space::A::a'}() // Some::Name::Space::A::a ? I think this could lead to some problems that namespacing is trying to solve. Also, what happens if you decide to refactor one of the traits and change its name or namespace. You would then have to search for every use of an autoaliased method. I think the original proposal is much better in this regard, because you only have to find the classes that use the trait. Another thing that bothers me about this idea is that the order that traits are added to a class determines which methods the class will have. This seems more and more like a mixin. I like the idea that the programmer has to make the choice over which implementation. It should be easy for the programmer to decide on one of these three: 1. Use one of the trait's implementations of the method and exclude all others (and possibly provide an alias to them). 2. Override the method in the class with a custom implementation. 3. Alias each of the methods and use them in the overridden method implementation. One more thing that I do not like about the auto aliasing is flattening. If I want to flatten all the traits into my class, I don't know of a way to make a method called {'Some::Name::Space::A::a'} inside the class in userspace (even though the interpreter can obviously handle it. -- Joshua Thompson [EMAIL PROTECTED] http://www.schmalls.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Andi Gutmans schrieb: I don't think so. I think the value here is not copypaste but to be able to encapsulate some functionality which a class can be decorated with. Giving a basic storage mechanism to that would be very beneficial in a large amount of uses. Again, I am proposing private storage only which would be for internal use-only by the decorating methods. if someone desperately needs that they could just write a method with a static variable. Not really because if you want a container shared across the methods it wouldn't be very feasible. I'm sure there are some hacks you can do but I just think it'd be a pretty common use case. Stefan, you have done a lot of research in this area and I assume have also looked at the most common use-cases where this functionality is used in other languages. What is your sense? I've mainly investigated the Squeak implementation which does not support stateful traits. Therefore, state has been access via required accessors implemented in the class using the trait. It is a quite practicable approach, even if it is very strict. But as already mentioned, there are ideas to allow state and trait-composition local properties. But here I've not seen any code using it and I am only aware of the pro and cons discussed in the paper (http://www.iam.unibe.ch/~scg/Archive/Papers/Berg07eStatefulTraits.pdf). My be anybody has connections to Scala guys using there Traits construct? Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, The above presents a problem if trait2 contains conflicting method names, but a simple way to solve it would be to automatically alias methods by prepending traitname:: ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? would create method trait2::a and we can alias it in the class body. Also, $a-{'trait2::a'}(); is legal syntax, so no problems there. Example: ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { function trait2::a as b; } ? This would be 100% obvious to me, and far clearer for reading since we would be explicitly saying we're aliasing a function. Could you please explain where in your proposal is the difference to the multiple inheritance available in C++? Think the auto-aliasing will lead to nothing else then multiple inheritance, with all its power and complexity. One of the main problems here is the fragility, already pointed out be Joshua in its response from today. Kind Regards -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP / Reflection
Hi, Markus Fischer schrieb: Hi, generally asking, how would Reflection act on traits? Can this be detected or will the information be lost after a class has been assembled? E.g. detect if a certain method comes from a trait and which one? think will work on the reflection part when details on the semantics has been finished. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 21/02/2008, David Zülke [EMAIL PROTECTED] wrote: PHP needs to stop worrying about the confusing newbies thing when discussing advanced features. We're not talking about a basic bread and butter language construct here. Other parts of PHP aren't beginner friendly either, and not all parts ever could, let alone should. Absolutelty. Parameter sequence or the names of functions being inconsistent. These cause more of a headache for newbies. is_(a/array/etc/null) vs isset Why? Sure you learn it but forever ask yourself why. And is the knowledge required to understand Unicode going to be easier to attain than for traits? -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498r=213474731 Standing on the shoulders of some very clever giants!
Re: [PHP-DEV] RFC: Traits for PHP
On 21/02/2008, Richard Lynch [EMAIL PROTECTED] wrote: I am not complaining. I think it's a FINE proposal. I'm suggesting an alternative solution which is simpler and easier to implement, with less confusion for new users. In fact, new users are often confused because the CAN'T do an include in the middle of a class -- A rule which, to some, seems arbitrary and illogical. And once they understand (if they do) why they cannot use include, they want to know how to do it anyway. Traits answer this quite nicely. All be it in a way which the idea of include would solve if it was done at parse/compile time. So, maybe something as simple as class_include 'file.inc'; where the name has to be a constant (parse error otherwise). But having said that traits LOOK nice. They look clever. Is it over complicated? If you don't know OOP, then maybe. But hell if everything was easy we would have monkeys doing it all for us. Traits look good. Many userland developers would use them. Many more would need to learn how to use them. Let's add them! It certainly would increase the amount of code reuse which MI theoretically is supposed to do. And then lets add accessibility to class properties without magic functions. Richard. -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498r=213474731 Standing on the shoulders of some very clever giants! -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP - Stateful Traits
On 21/02/2008, Stefan Marr [EMAIL PROTECTED] wrote: Hi, Andi Gutmans schrieb: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hope I got it right, since your example is a class? Ok, stateful traits are useful in the sense of having self-contained units of reuse. Personally, I prefer them over stateless traits. But, here we will get additional confusion. You don't like to handle with visibilities of properties? Fine :) One way to do stateful traits is described in http://www.iam.unibe.ch/~scg/Archive/Papers/Berg07eStatefulTraits.pdf But the way you have proposed is stricter and may be sufficient. To avoid confusion and misconception I would like to change your proposal a bit. Private does suggest a semantics like methods, and would require to apply the flattening on properties like on methods. Since we do not like to handle conflicts, this would have to be done a bit different, in my opinion. Let's change ``private`` to ``local``: trait TCounter { local $counter = 0; function getNextSerialNumber() { return $this-counter++; } } class Website { use TCounter; } The resulting composition would have a property resulting from the TCounter property, but is only accessible from a method of the specific trait, i.e., it is composition local. Just an additional though :) Kind Regards Stefan I think I see an issue with including properties. If a trait is partially included at different levels of a layered object base uses 2 methods of a trait. extended uses 2 more methods of the same trait another_base uses 1 method of the trait. another_extended_base uses the remaining methods of the trait. You would need to control the inclusion of the properties. -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498r=213474731 Standing on the shoulders of some very clever giants! -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Lukas, alright, 'foo as bar' is ok to me and does not even add a new keyword. Ignore or any more keywords are bad and I also think that the correct would be hide(ing). But as I further more explained it should really be something that only marks a method as private if at all. That can be done as: 'foo as private' since private is a keyword it cannot conflice anyway. marcus Wednesday, February 20, 2008, 9:52:56 PM, you wrote: On 20.02.2008, at 21:43, Stefan Marr wrote: If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I'm not comfortable with this notation, since it strengthens the impression that it is renaming. In my eyes it looks like this: trait_method = false means trait_method is moved to false, it is deleted, but this leads to the wrong impression of this: trait_method = new_name means trait_method is moved to new_name, and I am absolutely against this notion. Renaming implies in my opinion all references to this method might be adjusted (what is not possible at all) and the original method is lost. There are several problems with with lost method already discussed on this list, like not fulfilled requirements (the delete method thing). The aliasing notion has the benefit that a method has to be explicitly excluded to be removed. So the developer explicitly requests for a change that he will handle on its own. I agree that its important to make this concept clear in the syntax and that Marcus's proposal does not make it sufficiently clear. I do like Lars' proposal however: I have another syntax proposal: class Foo { consume TFoo { methodName as newMethodName; ignore otherMethod; } } maybe as should even be expanded to alias though the following does look like the english grammar police will get us: methodName alias newMethodName; regards, Lukas Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Marcus Boerger wrote: Hello Lukas, alright, 'foo as bar' is ok to me and does not even add a new keyword. Ignore or any more keywords are bad and I also think that the correct would be hide(ing). But as I further more explained it should really be something that only marks a method as private if at all. That can be done as: 'foo as private' since private is a keyword it cannot conflice anyway. I like this solution. I have been uncomfortable with the current trait suggestions because they occur in the body of the class, whereas extends/implements is outside. I think there is a way to handle this, however. class Blah extends ... implements ... traits trait1, trait2, trait3 { } The above presents a problem if trait2 contains conflicting method names, but a simple way to solve it would be to automatically alias methods by prepending traitname:: ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? would create method trait2::a and we can alias it in the class body. Also, $a-{'trait2::a'}(); is legal syntax, so no problems there. Example: ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { function trait2::a as b; } ? This would be 100% obvious to me, and far clearer for reading since we would be explicitly saying we're aliasing a function. So, I rescind my previous syntax suggestion in favor of the above. Greg -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 22.02.2008, at 15:45, Gregory Beaver wrote: Marcus Boerger wrote: Hello Lukas, alright, 'foo as bar' is ok to me and does not even add a new keyword. Ignore or any more keywords are bad and I also think that the correct would be hide(ing). But as I further more explained it should really be something that only marks a method as private if at all. That can be done as: 'foo as private' since private is a keyword it cannot conflice anyway. I like this solution. Yes to me it seems like we can solve the entire lack of encapsulation through aliasing/hiding by making the following changes to the original proposal: A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private here .. its what confused me in the first proposals of this approach by Marcus/Andi). The user of the trait can however explicitly make properties and methods from the trait visible to the class importing the trait. Also the trait using class can explicitly say that it wants to override a method/property in the scope of the trait. This way: 1) there is little chance of accidentally breaking a trait 2) changes within the trait should not break anything in the trait using class, unless the developer explicitly messed with the traits internals in the class using the trait. in that case however he can quickly spot the potentially problematic lines I have been uncomfortable with the current trait suggestions because they occur in the body of the class, whereas extends/implements is outside. I think there is a way to handle this, however. I dont agree here. traits are different. They do not affect what the class is. They change what it can do and as such the stuff should be defined next to properties and methods. ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? Here it gets worse. Now if I refactor things into a trait, I have to start changing all uses of those methods. @Greg: I think you are going in the wrong direction here. regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Fri, Feb 22, 2008 at 10:03 AM, Lukas Kahwe Smith [EMAIL PROTECTED] wrote: On 22.02.2008, at 15:45, Gregory Beaver wrote: Marcus Boerger wrote: Hello Lukas, alright, 'foo as bar' is ok to me and does not even add a new keyword. Ignore or any more keywords are bad and I also think that the correct would be hide(ing). But as I further more explained it should really be something that only marks a method as private if at all. That can be done as: 'foo as private' since private is a keyword it cannot conflice anyway. I like this solution. Yes to me it seems like we can solve the entire lack of encapsulation through aliasing/hiding by making the following changes to the original proposal: A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private here .. its what confused me in the first proposals of this approach by Marcus/Andi). The user of the trait can however explicitly make properties and methods from the trait visible to the class importing the trait. Also the trait using class can explicitly say that it wants to override a method/property in the scope of the trait. This way: 1) there is little chance of accidentally breaking a trait 2) changes within the trait should not break anything in the trait using class, unless the developer explicitly messed with the traits internals in the class using the trait. in that case however he can quickly spot the potentially problematic lines I have been uncomfortable with the current trait suggestions because they occur in the body of the class, whereas extends/implements is outside. I think there is a way to handle this, however. I dont agree here. traits are different. They do not affect what the class is. They change what it can do and as such the stuff should be defined next to properties and methods. ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? Here it gets worse. Now if I refactor things into a trait, I have to start changing all uses of those methods. @Greg: I think you are going in the wrong direction here. Fun that you mentionned that structure greg because I was thinking of something along those lines. Something very similar actually but the aliasing could look like this: trait One { function name() { return __TRAIT__; } function removeMe() {} } trait Two { function name() { return __TRAIT__; } } class Reel traits One, Two { override One::name with Two::name; remove Two::removeMe; } $object = new Reel(); echo $object-name(); // Echos Two of course. I find that rather clean and clear that you we are either overriding what with what and then removing a method. But as lukas mentionned, we may be stepping out of line here... regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- David, Re-read what you are replying. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Fri, Feb 22, 2008 at 10:32 AM, David Coallier [EMAIL PROTECTED] wrote: On Fri, Feb 22, 2008 at 10:03 AM, Lukas Kahwe Smith [EMAIL PROTECTED] wrote: On 22.02.2008, at 15:45, Gregory Beaver wrote: Marcus Boerger wrote: Hello Lukas, alright, 'foo as bar' is ok to me and does not even add a new keyword. Ignore or any more keywords are bad and I also think that the correct would be hide(ing). But as I further more explained it should really be something that only marks a method as private if at all. That can be done as: 'foo as private' since private is a keyword it cannot conflice anyway. I like this solution. Yes to me it seems like we can solve the entire lack of encapsulation through aliasing/hiding by making the following changes to the original proposal: A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private here .. its what confused me in the first proposals of this approach by Marcus/Andi). The user of the trait can however explicitly make properties and methods from the trait visible to the class importing the trait. Also the trait using class can explicitly say that it wants to override a method/property in the scope of the trait. This way: 1) there is little chance of accidentally breaking a trait 2) changes within the trait should not break anything in the trait using class, unless the developer explicitly messed with the traits internals in the class using the trait. in that case however he can quickly spot the potentially problematic lines I have been uncomfortable with the current trait suggestions because they occur in the body of the class, whereas extends/implements is outside. I think there is a way to handle this, however. I dont agree here. traits are different. They do not affect what the class is. They change what it can do and as such the stuff should be defined next to properties and methods. ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? Here it gets worse. Now if I refactor things into a trait, I have to start changing all uses of those methods. @Greg: I think you are going in the wrong direction here. Fun that you mentionned that structure greg because I was thinking of something along those lines. Something very similar actually but the aliasing could look like this: trait One { function name() { return __TRAIT__; } function removeMe() {} } trait Two { function name() { return __TRAIT__; } } class Reel traits One, Two { override One::name with Two::name; remove Two::removeMe; It is of course remove One::removeMe; } $object = new Reel(); echo $object-name(); // Echos Two of course. I find that rather clean and clear that you we are either overriding what with what and then removing a method. But as lukas mentionned, we may be stepping out of line here... regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- David, Re-read what you are replying. -- David, Re-read what you are replying. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi! A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private How you are going to do that? here .. its what confused me in the first proposals of this approach by Marcus/Andi). The user of the trait can however explicitly make properties and methods from the trait visible to the class importing the Looks like composition/delegation to me. Maybe that's what it should be? -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi! Fun that you mentionned that structure greg because I was thinking of something along those lines. Something very similar actually but the aliasing could look like this: trait One { function name() { return __TRAIT__; } function removeMe() {} } trait Two { function name() { return __TRAIT__; } } class Reel traits One, Two { override One::name with Two::name; remove Two::removeMe; } $object = new Reel(); echo $object-name(); // Echos Two of course. Two doesn't have removeMe. If you meant One::removeMe then why One is needed at all? You didn't use any method of it. -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Richard Quadling schrieb: On 21/02/2008, Richard Lynch [EMAIL PROTECTED] wrote: In fact, new users are often confused because the CAN'T do an include in the middle of a class -- A rule which, to some, seems arbitrary and illogical. And once they understand (if they do) why they cannot use include, they want to know how to do it anyway. Traits answer this quite nicely. All be it in a way which the idea of include would solve if it was done at parse/compile time. So, maybe something as simple as class_include 'file.inc'; We even would not need a new keyword, we could use include for this. The user would not really care if this is compile time or run time as long as the simple (and most useful) case Just Works IMHO. But having said that traits LOOK nice. They look clever. Is it over complicated? If you don't know OOP, then maybe. But hell if everything was easy we would have monkeys doing it all for us. I'm trying to suppress my reservations about new language constructs and was quite succesful: I started to like Traits. But the discussion about the semantics are close to making me reconsider: If you (the core developers and language designers) cannot agree on the semantics (stateless vs. stateful traits, etc.) I wonder how the user is going to feel about it. Traits look good. Many userland developers would use them. Many more The use case examples I've seen so far haven't been all that convincing to me but that's probably because of a different coding style. - Chris -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Lukas Kahwe Smith wrote: I have been uncomfortable with the current trait suggestions because they occur in the body of the class, whereas extends/implements is outside. I think there is a way to handle this, however. I dont agree here. traits are different. They do not affect what the class is. They change what it can do and as such the stuff should be defined next to properties and methods. ?php trait trait1 { function a(){}} trait trait2 { function a(){}} class Blah extends ... implements ... traits trait1, trait2, trait3 { } ? Here it gets worse. Now if I refactor things into a trait, I have to start changing all uses of those methods. @Greg: I think you are going in the wrong direction here. I think you may be confused, because your statement about refactoring is inaccurate - for most methods, there would be no change from the current proposal. In other words, in my example above, you could use trait1::a() simply as Blah::a, for instance: ?php $a = new Blah; $a-a(); ? Only if one wanted to access trait2::a() would one need to either alias via function trait2::a as b to use as $a-b() or explicitly refer to $a-{'trait2::a'}() To be absolutely clear, here is how it could work: ?php trait A { function myfunc(){ echo 'myfunc';} function a(){ echo 'A::a';} } trait B { function a(){ echo 'B::a';} function another(){echo 'another';} } class Blah extends... implements... traits A, B { } $a = new Blah(); $a-myfunc(); // myfunc $a-a(); // B::a $a-another(); // another $a-{'A::a'}() // A::a ? So, as you can see, all of the trait methods are available as regular methods except for A::a which is overridden by B::a. If the order were reversed, i.e. traits B, A then $a-a() would instead call A::a. The current proposal would cause the above to fail with a name conflict error rather than automatically aliasing. Here is another example with the overriding syntax: ?php trait A { function myfunc(){ echo 'myfunc';} function a(){ echo 'A::a';} } trait B { function a(){ echo 'B::a';} function another(){echo 'another';} } class Blah extends... implements... traits A, B { function B::a as private; function A::a as a; } $a = new Blah(); $a-myfunc(); // myfunc $a-a(); // A::a $a-another(); // another ? Greg -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 22.02.2008, at 23:31, Gregory Beaver wrote: I think you may be confused, because your statement about refactoring is inaccurate - for most methods, there would be no change from the current proposal. In other words, in my example above, you could use trait1::a() simply as Blah::a, for instance: ?php $a = new Blah; $a-a(); ? Only if one wanted to access trait2::a() would one need to either alias via function trait2::a as b to use as $a-b() or explicitly refer to $a-{'trait2::a'}() Ah ok, I thought that trait2::a was the only way to access the trait2 a() method. Ok then its not as problematic. However I do not really like that syntax much. Like I said I also do not like the use of the word private in this context. I find it totally confusing, since its not private in the PPP sense. And like I also said before, I am not convinced that traits belong outside of the curly brackets next to the class name and the interface the class may implement. That would make it appear like the trait defines the type of the class, which it should not. So I am still of the opinion that by default all properties/methods should be imported as encapsulated units and the developer can decide which parts of the trait should become visibile to the trait using class. regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 22.02.2008, at 18:20, Stanislav Malyshev wrote: Hi! A trait may contain methods and properties. When importing a trait into a class, all methods and properties are imported in a way that makes them only visible within the trait (I dont like the use of private How you are going to do that? I have no clue how to technically make this possible, but Andi appeared confident that it should be possible with reasonable effort. regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 21.02.2008, at 03:26, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Of course this could be nice, but I think this is maybe the point where one should move to delegate? b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I am probably not seeing the obvious here, but how does making the function private solve the naming collisions? regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
+1 Thanks for very detailed proposal. I think Traits for PHP is good idea. But I think, that use keword make some confusing, I propose have or hold instead. And ! not readable (imho) - I'd like not or except And aliasing syntax (bar=foo) looks good in my mind. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 20/02/2008, Stefan Marr [EMAIL PROTECTED] wrote: If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I'm not comfortable with this notation, since it strengthens the impression that it is renaming. In my eyes it looks like this: trait_method = false means trait_method is moved to false, it is deleted, but this leads to the wrong impression of this: trait_method = new_name means trait_method is moved to new_name, and I am absolutely against this notion. Kind Regards Stefan What would you all read this to be ... void := 'trait_method' 'new_name' := 'trait_method' array('new_name', 'trait_method') := 'trait_method' := is becomes equal. -- - Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498r=213474731 Standing on the shoulders of some very clever giants! -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
See below: -Original Message- From: Lukas Kahwe Smith [mailto:[EMAIL PROTECTED] Sent: Thursday, February 21, 2008 12:41 AM To: Andi Gutmans Cc: [EMAIL PROTECTED]; internals@lists.php.net; Marcus Börger; Johannes Schlüter; Sebastian Bergmann; Alexandre Bergel; Falko Menge; Sara Golemon; [EMAIL PROTECTED] Subject: Re: [PHP-DEV] RFC: Traits for PHP On 21.02.2008, at 03:26, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Of course this could be nice, but I think this is maybe the point where one should move to delegate? I don't think so. I think the value here is not copypaste but to be able to encapsulate some functionality which a class can be decorated with. Giving a basic storage mechanism to that would be very beneficial in a large amount of uses. Again, I am proposing private storage only which would be for internal use-only by the decorating methods. b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I am probably not seeing the obvious here, but how does making the function private solve the naming collisions? My concern about removing/aliasing functions is that you can really do some very funky stuff. It almost takes me back to the spaghetti code days where you can jump into code someplace in the middle. My proposal would make Traits a bit stricter and ensure that the original interface would still exist after it is aggregated. Either by honoring the interface and redefining methods which are consistent with the Trait or by leaving the original methods around as privates so that they can still reference each other. I think being able to remove a method which may need to be used by some internal method is a bit too chaotic. When you're inheriting large code bases it can become complicated to manage. I very much see the value of Traits but I think we should also consider making them a bit stricter. Btw, the private property discussion is different from the 2nd one. They are mutually exclusive. The latter idea would give more structure, still enforce a contract but should provide the same value. I am not convinced it's feasible on an implementation side but I think we should first consider it from a functional point of view. Andi -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 21.02.2008, at 19:09, Andi Gutmans wrote: I don't think so. I think the value here is not copypaste but to be able to encapsulate some functionality which a class can be decorated with. Giving a basic storage mechanism to that would be very beneficial in a large amount of uses. Again, I am proposing private storage only which would be for internal use-only by the decorating methods. if someone desperately needs that they could just write a method with a static variable. class foo { function bar($value = null) { if (!isset($var)) { static $var = 'bar'; } if (func_num_args() 0) { $var = $value; } return $var; } } $foo = new foo(); var_dump($foo-bar()); var_dump($foo-bar('foo')); var_dump($foo-bar()); ok its a hack .. but you can see how this could work. and you could even expand it to handle an arbitrary number of properties in a self contained method. all you need to do is find a name that doesnt clash. again i prefer to keep the feature as simple as possible without crippeling it the point of not being useful. regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
-Original Message- From: Lukas Kahwe Smith [mailto:[EMAIL PROTECTED] Sent: Thursday, February 21, 2008 10:32 AM To: Andi Gutmans Cc: [EMAIL PROTECTED]; internals@lists.php.net; Marcus Börger; Johannes Schlüter; Sebastian Bergmann; Alexandre Bergel; Falko Menge; Sara Golemon; [EMAIL PROTECTED] Subject: Re: [PHP-DEV] RFC: Traits for PHP On 21.02.2008, at 19:09, Andi Gutmans wrote: I don't think so. I think the value here is not copypaste but to be able to encapsulate some functionality which a class can be decorated with. Giving a basic storage mechanism to that would be very beneficial in a large amount of uses. Again, I am proposing private storage only which would be for internal use-only by the decorating methods. if someone desperately needs that they could just write a method with a static variable. Not really because if you want a container shared across the methods it wouldn't be very feasible. I'm sure there are some hacks you can do but I just think it'd be a pretty common use case. Stefan, you have done a lot of research in this area and I assume have also looked at the most common use-cases where this functionality is used in other languages. What is your sense? again i prefer to keep the feature as simple as possible without crippeling it the point of not being useful. This suggestion is actually geared towards the opposite of crippling (private property is actually an addition). I actually think this is something which would be a very common use case for our users. Btw, the 2nd part where I recommend brainstorming about a slightly stronger contract would actually also drive more towards simplicity. In any case, I think we all agree this is a good thing to have in PHP. I am not advocating the opposite but I would like to explore some of these use-cases and options for a slightly stricter contact. Andi -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
Ah, I thought you were talking about both. Non-public makes more sense for properties, but I thought you were talking about methods not having ppp either. No worries then. /de-lurk --Larry Garfield On Wed, 20 Feb 2008 23:19:23 -0800, Andi Gutmans [EMAIL PROTECTED] wrote: My email talked about properties not methods. Please re-read it :) Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 10:51 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP I am unclear on how this: trait ParseThingie { protected function parseThingie($thingie) {...} } trait ProcessThingie { protected function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } allows more opportunity for confusion and clashes than this: trait ParseThingie { public function parseThingie($thingie) {...} } trait ProcessThingie { public function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } (Presumably an un-qualified method would be public for traits just like for classes.) OK the above example is a bit of a strawman, but I don't know a non- strawman example here. :-) That's the clarification I'm asking for. On Thursday 21 February 2008, Andi Gutmans wrote: Because then you get into similar problems as with multiple inheritance when you have property clashes and other issues. The reason why private is beneficial and different because it will allow you to develop self contained functionality which can be attached to random classes. This can be quite useful for Timers, Counters, Containers, etc... Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 9:54 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP On Wednesday 20 February 2008, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hi Andi. Why no ppp on Traits? It seems useful to be able to pull in a utility function or functions that can be leveraged from other methods, like domain-specific parsers, without exposing them to the outside world. Is it an engine-level implementation issue, or a conceptual complexity issue? I don't really see a complexity issue on the developer level, at least for me. -- Larry Garfield AIM: LOLG42 [EMAIL PROTECTED]ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. - - Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- Larry Garfield AIM: LOLG42 [EMAIL PROTECTED]ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Mon, February 18, 2008 5:08 pm, David Coallier wrote: On Feb 18, 2008 5:37 PM, Richard Lynch [EMAIL PROTECTED] wrote: On Mon, February 18, 2008 1:27 pm, [EMAIL PROTECTED] wrote: ?php trait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; So it's just like an include for a re-used body of 'class' code. H. Why not just allow 'include' here instead? Oh come on.. :-) Forgive me if I'm missing something subtle/complex here, but I wonder if a Trait is really the right answer... Yes, the ability to add/exclude specific functions from two Traits is gone with a simple 'include'... But so is the complexity of yet another language construct... Please if you do not understand a concept, do not bash it or degrade it. Read the proposal, read about traits, read the thesis, read the patch, then if you still don't understand, give up, and if you do understand, you can complain. I am not complaining. I think it's a FINE proposal. I'm suggesting an alternative solution which is simpler and easier to implement, with less confusion for new users. In fact, new users are often confused because the CAN'T do an include in the middle of a class -- A rule which, to some, seems arbitrary and illogical. -- Some people have a gift link here. Know what I want? I want you to buy a CD from some indie artist. http://cdbaby.com/from/lynch Yeah, I get a buck. So? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Mon, February 18, 2008 7:45 pm, Rasmus Lerdorf wrote: The idea here is that we want to be able to cache opcodes, classes and functions and optimize them out of the runtime context so the executor can skip creating classes and functions on every single request. A lot of the traffic on this list over the past couple of months seems to ignore this basic premise. Features such as autoload and runtime object manipulation incur a huge performance hit in the sense that they change something that was free before and not only add the cost of the feature itself, but it also means the object in question now can no longer be cached and has to be created on every single request. This doesn't mean we can't consider such features, but people need to also consider the performance implications. Many users need opcode caches and performance is crucial... Many MORE don't, really :-) Perhaps those who need caches can devote the resources to simply not use dynamic constructs that will break their caching mechanism, for many of the features, rather than simply not letting the features exist for those who don't need caching that badly. Whether dynamic method construction or trait addition is such a feature is beyond me, of course, but it's worth considering whether the feature will make it ALWAYS slower, or only slower if one is silly enough to use it when one shouldn't. -- Some people have a gift link here. Know what I want? I want you to buy a CD from some indie artist. http://cdbaby.com/from/lynch Yeah, I get a buck. So? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Tue, February 19, 2008 8:29 am, Marcus Boerger wrote: For that reason allowing traits in favor of include inside a class body is much better. Once upon a time, there was a real difference between require and include -- where require was compile-time and include was run-time. PERHAPS it would be interesting to consider something not unlike the old 'require' which is compile-time include, with some kind of name that doesn't confuse users as much as require did back in the day. -- Some people have a gift link here. Know what I want? I want you to buy a CD from some indie artist. http://cdbaby.com/from/lynch Yeah, I get a buck. So? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP - Stateful Traits
Hi, Andi Gutmans schrieb: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hope I got it right, since your example is a class? Ok, stateful traits are useful in the sense of having self-contained units of reuse. Personally, I prefer them over stateless traits. But, here we will get additional confusion. You don't like to handle with visibilities of properties? Fine :) One way to do stateful traits is described in http://www.iam.unibe.ch/~scg/Archive/Papers/Berg07eStatefulTraits.pdf But the way you have proposed is stricter and may be sufficient. To avoid confusion and misconception I would like to change your proposal a bit. Private does suggest a semantics like methods, and would require to apply the flattening on properties like on methods. Since we do not like to handle conflicts, this would have to be done a bit different, in my opinion. Let's change ``private`` to ``local``: trait TCounter { local $counter = 0; function getNextSerialNumber() { return $this-counter++; } } class Website { use TCounter; } The resulting composition would have a property resulting from the TCounter property, but is only accessible from a method of the specific trait, i.e., it is composition local. Just an additional though :) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Andi Gutmans schrieb: I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Sounds a bit like what had been proposed in this paper: http://www.iam.unibe.ch/~scg/Archive/Papers/Duca07b-FreezableTrait.pdf The first point, yes exclusion and aliasing are only meant to handle conflicts, and should be used only in this context. Yeah you can break the trait with it, but you did it explicitly, think this should be made clear a bit more in the discussion about breaking interfaces. Nobody would request unset to be removed from the function set even though you can do this: $a = new A(); unset($a); $a-foo(); //damn... It is almost like excluding a method from a trait and be worried about the trait breaks. Isn't it? :) Benefits: - Keeps the old code from running predictably without breaking dependencies. Well, in the code I've read so far, exclusion has been used to cog/dovetail to traits which supplement each other very well. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. Hm, I would prefer to not add the type notion to traits. They are only units of reuse, not types IMHO. I need to put a bit more thought into this but it's an initial attempt to provide an additional point of view which may actually give some more structure to the proposal while still delivering the benefits of this idea. I think if this kind of idea could be fully baked it would solve the problems I have had in the past possibly without the more dangerous renaming/removing of functions. I have not looked into feasibility of this idea yet. Think user-changeable location of composed methods is quite possible, but for the cost of complexity. (Have a look at the paper for the complete idea of trait-local/freezed methods.) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Richard Lynch wrote: On Mon, February 18, 2008 7:45 pm, Rasmus Lerdorf wrote: The idea here is that we want to be able to cache opcodes, classes and functions and optimize them out of the runtime context so the executor can skip creating classes and functions on every single request. A lot of the traffic on this list over the past couple of months seems to ignore this basic premise. Features such as autoload and runtime object manipulation incur a huge performance hit in the sense that they change something that was free before and not only add the cost of the feature itself, but it also means the object in question now can no longer be cached and has to be created on every single request. This doesn't mean we can't consider such features, but people need to also consider the performance implications. Many users need opcode caches and performance is crucial... Many MORE don't, really :-) That's a bit like saying that most people don't need more money. While probably true, it certainly doesn't hurt to have much lower page latencies. Similarly, most people don't need to scale either, but that doesn't mean we should suddenly start tearing down our perfect shared nothing sandbox. If we design for good performance and scaling, the trickledown effect means that even horribly-written applications will be usable while the people who care about performance can get outstanding performance out of it. -Rasmus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Am 22.02.2008 um 00:16 schrieb Stefan Marr: Sounds a bit like what had been proposed in this paper: http://www.iam.unibe.ch/~scg/Archive/Papers/Duca07b-FreezableTrait.pdf The first point, yes exclusion and aliasing are only meant to handle conflicts, and should be used only in this context. Yeah you can break the trait with it, but you did it explicitly, think this should be made clear a bit more in the discussion about breaking interfaces. Nobody would request unset to be removed from the function set even though you can do this: $a = new A(); unset($a); $a-foo(); //damn... It is almost like excluding a method from a trait and be worried about the trait breaks. Isn't it? :) I agree. It's called asking for it. Since traits can only be added in dynamically, a programmer always knows what he is doing when excluding or aliasing a method in a trait. PHP needs to stop worrying about the confusing newbies thing when discussing advanced features. We're not talking about a basic bread and butter language construct here. Other parts of PHP aren't beginner friendly either, and not all parts ever could, let alone should. David -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Replies to a) and b) below: Andi Gutmans wrote: Hi Stefan, Thanks for writing such a good proposal. In general I think traits is a very interesting idea. I can think of a few cases in my life as a programmer where it could have helped me out. I think some comments re: the syntax/naming are good ones but I prefer not to get into naming in this email. I believe we can brainstorm re: naming when we figure out exactly what we want to do. I do support though finding a way which is simple for non-English speakers but not too simple like Perl:) Thinking back at the times when something like this would have been useful to me I think there are a couple of main points I'd like to brainstorm about: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. If you read the stateful traits paper Stefan linked to, you can see a precedent for how this has been implemented. By default the properties are private to the scope of the trait. The client class can also make an alias to the property and have access to this property through this private alias property. The client class can also merge multiple properties into one common properties. The problem with this is during flattening. When there is a conflicting property, all references have to be alpha-renamed in all the trait methods. This is a more costly operation as compared to the flattening of stateless traits. This may not be reason enough not to include it, but it should definitely be a consideration. b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I need to put a bit more thought into this but it's an initial attempt to provide an additional point of view which may actually give some more structure to the proposal while still delivering the benefits of this idea. I think if this kind of idea could be fully baked it would solve the problems I have had in the past possibly without the more dangerous renaming/removing of functions. I have not looked into feasibility of this idea yet. Anyway, good ideas and thanks for the very professional way you have brought this idea to the community. Let's try and nail down the behavior and then we can have the harder naming discussion :) Just saying harder because I've always considered naming the hardest part in software engineering... Andi Let me use a quote on aliasing from this paper http://www.iam.unibe.ch/~scg/Archive/Papers/Scha03aTraits.pdf: The new name is used to obtain access to a method that would otherwise be unreachable because it has been overridden. The point of aliasing is to give the client class a way to call the old method after it has been overridden. Generally, if two traits have the same method names, you would want to alias both of them, override the method, and use the aliases to compose the overridden method. The other option is to just choose one of the trait's method implementations and exclude all others. And if you are talking about making the old method that is aliased into a method that is private to just that trait, flattening would then require some kind of alpha-rename for even stateless traits in some cases. -- Joshua Thompson [EMAIL PROTECTED] http://www.schmalls.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Lars, What about abstract methods in traits? I think this could be handy to enforce the user class implement a data getter. trait Foo { public function doSomething() { return str_replace(foo, bar, $this-_getString()); } abstract protected _getString(); } class Consumer { use Foo; protected function _getString() { return foo; } } What do you think? I am sorry :) This part has been missing in the RFC. But is already implemented in the patch and supposed to work exactly like you has described it. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 20.02.2008, at 09:28, Stefan Marr wrote: Hi Lars, What about abstract methods in traits? I think this could be handy to enforce the user class implement a data getter. trait Foo { public function doSomething() { return str_replace(foo, bar, $this-_getString()); } abstract protected _getString(); } class Consumer { use Foo; protected function _getString() { return foo; } } What do you think? I am sorry :) This part has been missing in the RFC. But is already implemented in the patch and supposed to work exactly like you has described it. Maybe its best to first leave out interfaces/abstract etc. Start simple, see how things get used, get more comfortable with the feature and then see about potentially expanding it. regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Lars Strojny schrieb: What about abstract methods in traits? I do not think that this would make sense. Traits are about reusing code. Abstract methods do not hold concrete code. -- Sebastian Bergmann http://sebastian-bergmann.de/ GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] Thank you for your attention and I'm looking forward to hear your comments :) What about abstract methods in traits? I think this could be handy to enforce the user class implement a data getter. trait Foo { public function doSomething() { return str_replace(foo, bar, $this-_getString()); } abstract protected _getString(); } class Consumer { use Foo; protected function _getString() { return foo; } } What do you think? cu, Lars signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
Hi Lukas, Am Mittwoch, den 20.02.2008, 09:44 +0100 schrieb Lukas Kahwe Smith: [...] Maybe its best to first leave out interfaces/abstract etc. Start simple, see how things get used, get more comfortable with the feature and then see about potentially expanding it. I totally agree also I would like to have abstract methods in traits (and don't beat me, I would like interface now too, for conceptual integrity but the implemented interfaces should not derived by the using classes). But: let us try to include a simple version of traits, without abstract methods and trait interfaces in 5.3, get a huge amount of feedback from the community and than think about implementing the more complex stuff. I would like to see the following featureset: * Method renaming (method = newMethod) * Method hiding (method = null, method = false, both might work) * No interfaces * No abstract methods * No visibility modifications The last three point could be done for 5.4. cu, Lars signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
Hi Derick, 1. can traits be put in a file of their own (I assume so actually) 2. can traits be autoloaded? yes, since traits are zend_class_entrys with ce_flags set to ZEND_ACC_TRAIT in the current implementation, they will follow the same rules for definition and autoloading like classes. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Mon, 18 Feb 2008, [EMAIL PROTECTED] wrote: Thank you for your attention and I'm looking forward to hear your comments And thank you for this very detailed proposal, I wish most other feature proposals were like this. I like the concept, it seems to solve some of the problems we had to hack around now as well. I've two quick questions for you: 1. can traits be put in a file of their own (I assume so actually) 2. can traits be autoloaded? regards, Derick -- Derick Rethans http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
On 19 February 2008 21:03, [EMAIL PROTECTED] advised: Hi Marcus, Hi Troels, The biggest issue I see is finding a syntax everyone likes. Well, lets try some variations. [2a] ! is not readable -- except use Trait { except foo1, foo2; bar = foo1 } [2b] ! is not readable -- without use Trait { without foo1; without foo2; bar = foo1; } [Aa] Aliasing is not obvious use Trait { bar is foo1; //aliasMethod is method } [Ab] Aliasing is not obvious use Trait { bar from foo1; //aliasMethod from method } I may be completely off base with this suggestion, but how about something as simple as not and as (which also has the advantage of not requiring new keywords!): use Trait { not foo1 } use Trait { foo1 as bar } Although I can see how this might be considered a touch ugly: use Trait { not foo1; foo1 as bar } -- Mike Ford, Electronic Information Services Adviser, JG125, The Headingley Library, James Graham Building, Leeds Metropolitan University, Headingley Campus, LEEDS, LS6 3QS, United Kingdom Email: [EMAIL PROTECTED] Tel: +44 113 812 4730 Fax: +44 113 812 3211 To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP / Reflection
Hi, generally asking, how would Reflection act on traits? Can this be detected or will the information be lost after a class has been assembled? E.g. detect if a certain method comes from a trait and which one? lG -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP / Reflection
Hi Markus, Am Mittwoch, den 20.02.2008, 12:13 +0100 schrieb Markus Fischer: [...] generally asking, how would Reflection act on traits? Can this be detected or will the information be lost after a class has been assembled? E.g. detect if a certain method comes from a trait and which one? Good question. The current patch does not include anything about reflections. But as the information about traits is present in the struct zend_class_entry is is possible to expose trait information via the reflection API. I would propose something like this: class ReflectionTrait: * getMethods(): array[ReflectionMethod] * ... pretty similiar to ReflectionClass extending class ReflectionClass: * getTraits(): array[ReflectionTrait] * usesTraits(): bool extending class ReflectionMethod: * flattened(): bool * getTrait(): ReflectionTrait Maybe ReflectionMethod::flattened() should be ReflectionMethod::belongsToTrait() or something like this, I'm not sure here. cu, Lars signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP / Reflection
Markus Fischer wrote: generally asking, how would Reflection act on traits? Can this be detected or will the information be lost after a class has been assembled? E.g. detect if a certain method comes from a trait and which one? Dammit, sorry, I didn't intended to send it to all individuals. - Markus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 20 Feb 2008, at 07:46, Sebastian Bergmann wrote: Lars Strojny schrieb: I think also for the sake of conceptual integrity separating interfaces clearly from traits is a good idea Interfaces are about (multiple) interface inheritance and traits are about (multiple) implementation inheritance. This separation of interface inheritance and implementation inheritance is ... awesome :) Is there any reason why we cannot support multiple inheritance (which some other languages already do)? The only thing that needs to be clearly defined is sorting order. This avoids trying to create some entirely new functionality to do something where we can simply extend what we already do. -- Geoffrey Sneddon http://gsnedders.com/ -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Stefan, so at th eend of the day users will get renaming and will abuse it. That said I am wondering if at the beginning we might want to do Traits without aliasing and dropping. If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I am suggesting this because it is more what people expect to find. And it is easier to understand imo. marcus Tuesday, February 19, 2008, 10:59:20 PM, you wrote: Hi Evert, Aliasing doesn't make a lot of sense, as you can always : function newMethod() { return $this-oldMethod(); } Don't think so. You do use aliasing to handle conflicts and in the case of a conflict there is no oldMethod. trait A { public function foo() {echo 'foo';} } trait B { public function foo() {echo 'fooBar';} } class MyClass { use A; use B { !foo, fooBar = foo } } The result will be at runtime: class MyClass { public function foo() {echo 'foo';} public function foo() {echo 'fooBar';} } Here you can't do something like this: class MyClass { use A; use B; } since eventually there wont be any method in MyClass. Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Stanislav, if we go the route of allowing that, then we have to do some protocl checks. Meaning if a renamed/aliased method will become an implementation of an abstract method then of course it has to be compatible. The beigger problem I assume you have in mind as well is that replace might be implemented in a way that it uses both delete and add. If now add gets dropped or renamed then there is a problem, called missing function. We could avoid that easily if we have a compiler that allowed us to check which functions are being called. Becasue then we could easily prevent a used function from getting renamed. But all I just said does not really sound like the PHP approach. It is something I would do in my own language. In PHP we always allowed all kinds of nasty. We even hesitate to increase the severity of any E_STRICT. Not even if it would be better for opcode caches. We not even get rid of the insanest stuff... So where do we want to go today with this? marcus Tuesday, February 19, 2008, 11:58:06 PM, you wrote: most important issue to me how to handle interface implementations in cases where methods from the interface implementing trait are renamed in the trait consumer class. Renaming poses problem not only with interfaces. Imagine trait having these methods: function add($key, $value) { ... } function delete($key) { ... } function replace($key, $value) { $this-delete($key); $this-add($key, $value); } What happens if add() is renamed or replaced with function from other trait/interface or dropped? -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Jochem, good arguments. And good ideas. I'd favor 'posesses' then. marcus Tuesday, February 19, 2008, 9:54:09 PM, you wrote: firstly, I'd like to reiterate the general sentiment that Stefans RFC is blinding! (that's a good thing in this context ;-) Marcus Boerger schreef: Hello Lars, we could even go for include here if we wanted to avoid use as much as adding a new keyword. Personally I don't mind using keywords for different stuff as long as it cannot conflict. That is in this case true for both include and use. how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait a person coming accross 'use' or 'include' in the context of trait attribution may either make assumptions or become confused as to possible changes/additions to the use and/or include functionality, a new keyword that aptly describes the intention will more likely force users to actually find out what it means. an another alternative might be 'applies' - which doesn't fit the natural language usage of 'trait' but does succintly describe what is happening. just a thought. marcus Tuesday, February 19, 2008, 9:31:29 PM, you wrote: Hi Stefan, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. cu, Lars Best regards, Marcus Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi! Is there any reason why we cannot support multiple inheritance (which Yes, there is. Ambiguity. -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Geoffrey, Am Mittwoch, den 20.02.2008, 20:14 + schrieb Geoffrey Sneddon: [...] Is there any reason why we cannot support multiple inheritance (which some other languages already do)? The only thing that needs to be clearly defined is sorting order. This avoids trying to create some entirely new functionality to do something where we can simply extend what we already do. Did you read the academic paper about the purpose of traits? In short: traits fix the common misconceptions of multiple inheritance. The most common problem is risky and fragile hierarchies. Also traits do the right thing[tm]: they allow compositions, not uncontrolable hotchpotch architectures. cu, Lars signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I'm not comfortable with this notation, since it strengthens the impression that it is renaming. In my eyes it looks like this: trait_method = false means trait_method is moved to false, it is deleted, but this leads to the wrong impression of this: trait_method = new_name means trait_method is moved to new_name, and I am absolutely against this notion. Renaming implies in my opinion all references to this method might be adjusted (what is not possible at all) and the original method is lost. There are several problems with with lost method already discussed on this list, like not fulfilled requirements (the delete method thing). The aliasing notion has the benefit that a method has to be explicitly excluded to be removed. So the developer explicitly requests for a change that he will handle on its own. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Marcus, Jochem, Although I agree with the general idea, I feel strongly against possesses, mainly because for a non-native english speaker it's a pita to write and will (and I'm sure of this) *very* often be misspelled (leading to general annoyances while debugging). I can't give any better fitting keywords for it though, but possesses is definitly not the best choice imo. - Tul Marcus Boerger wrote: Hello Jochem, good arguments. And good ideas. I'd favor 'posesses' then. marcus Tuesday, February 19, 2008, 9:54:09 PM, you wrote: firstly, I'd like to reiterate the general sentiment that Stefans RFC is blinding! (that's a good thing in this context ;-) Marcus Boerger schreef: Hello Lars, we could even go for include here if we wanted to avoid use as much as adding a new keyword. Personally I don't mind using keywords for different stuff as long as it cannot conflict. That is in this case true for both include and use. how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait a person coming accross 'use' or 'include' in the context of trait attribution may either make assumptions or become confused as to possible changes/additions to the use and/or include functionality, a new keyword that aptly describes the intention will more likely force users to actually find out what it means. an another alternative might be 'applies' - which doesn't fit the natural language usage of 'trait' but does succintly describe what is happening. just a thought. marcus Tuesday, February 19, 2008, 9:31:29 PM, you wrote: Hi Stefan, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. cu, Lars Best regards, Marcus Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Marcus, Am Mittwoch, den 20.02.2008, 20:59 +0100 schrieb Marcus Boerger: [...] so at th eend of the day users will get renaming and will abuse it. I disagree here. I think aliasing is fundamental to traits. If we think of traits as buckets of functionality, the concrete structure of the trait does not really matter. What matters is how the trait is used in the consuming class. Part of the usage is how the trait methods are exposed to the class. So I would really like to see aliasing support as long as there are no technical limitations that forbid proper and simple and understandable aliasing. That said I am wondering if at the beginning we might want to do Traits without aliasing and dropping. If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I have another syntax proposal: class Foo { consume TFoo { methodName as newMethodName; ignore otherMethod; } } foo as bar seems easy to grasp for me. Ignore seems to be technically correct, as the method is not dropped or removed but just ignored for the current class context. I would really prefer not to use exhibit or possess. Most OOP terms are really basic english to make also non-english speakers get the concepts easily. abstract, class, object, interface, etc. pp. is pretty basic, while exhibit or possess is maybe not part of the common basic vocabulary. cu, Las signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
On Tue, Feb 19, 2008 at 3:54 PM, Jochem Maas [EMAIL PROTECTED] wrote: how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait a person coming accross 'use' or 'include' in the context of trait attribution may either make assumptions or become confused as to possible changes/additions to the use and/or include functionality, a new keyword that aptly describes the intention will more likely force users to actually find out what it means. IMO, the keyword should be a verb because the code is instructing the class to add a behavior. possesses and exhibits are adjectives which doesn't make much sense. My vote would be something like acquire. Regards, John Campbell -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi! if we go the route of allowing that, then we have to do some protocl checks. Meaning if a renamed/aliased method will become an implementation of an abstract method then of course it has to be compatible. The beigger I'm kind of confused on a use case for that. Suppose you have trait TFoo that does some API - like implementing serialization, for example. And then you have some abstract method bar() that is supposed to do something unrelated - like convert pounds to kilograms. And then you just rename one of the methods of TFoo into bar() and suddenly it starts being used for converting pounds to kilograms just because it has the same argument count? I don't see any sane application structure working this way. What would be the use case of taking methods from one API and using them as implementation for totally unrelated parts of other API? What if one of the APIs changes? What if change required to implement TFoo but bar() should stay the same? This just looks like very cludgy attempt to avoid typing a few extra lines, which will definitely will come back to bite the developer in the future. I think this is important - to figure out what is the good use case for this. dropped or renamed then there is a problem, called missing function. We could avoid that easily if we have a compiler that allowed us to check which functions are being called. Becasue then we could easily prevent a We can't - as I already mentioned, call resolution is dynamic in PHP, which means compiler can't check which methods are called. On top of that, nobody said methods are always to be called on $this with - operator - there are many other ways to call a method on an object. In PHP we always allowed all kinds of nasty. We even hesitate to increase No, we didn't allow all kinds of nasty. PHP never had dynamic method addition, dynamic object/class redefinition, etc. even though engine-wise it's completely possible. That's the domain of hackish extensions like runkit and IMO it should stay there - in it's own closet which is clearly labeled beware of the leopard. I would have no objection for runkit to have traits-like functions - in fact, I think it can do it right now. Having this in core is another, very different business. -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 20.02.2008, at 21:43, Stefan Marr wrote: If we feel it gets necessary we probbaly might want to support a syntax like: 'trait_method' = false 'trait_method' = 'new_name' 'trait_method' = array('new_name', 'trait_method' I'm not comfortable with this notation, since it strengthens the impression that it is renaming. In my eyes it looks like this: trait_method = false means trait_method is moved to false, it is deleted, but this leads to the wrong impression of this: trait_method = new_name means trait_method is moved to new_name, and I am absolutely against this notion. Renaming implies in my opinion all references to this method might be adjusted (what is not possible at all) and the original method is lost. There are several problems with with lost method already discussed on this list, like not fulfilled requirements (the delete method thing). The aliasing notion has the benefit that a method has to be explicitly excluded to be removed. So the developer explicitly requests for a change that he will handle on its own. I agree that its important to make this concept clear in the syntax and that Marcus's proposal does not make it sufficiently clear. I do like Lars' proposal however: I have another syntax proposal: class Foo { consume TFoo { methodName as newMethodName; ignore otherMethod; } } maybe as should even be expanded to alias though the following does look like the english grammar police will get us: methodName alias newMethodName; regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 20 Feb 2008, at 20:28, Lars Strojny wrote: Am Mittwoch, den 20.02.2008, 20:14 + schrieb Geoffrey Sneddon: [...] Is there any reason why we cannot support multiple inheritance (which some other languages already do)? The only thing that needs to be clearly defined is sorting order. This avoids trying to create some entirely new functionality to do something where we can simply extend what we already do. Did you read the academic paper about the purpose of traits? In short: traits fix the common misconceptions of multiple inheritance. The most common problem is risky and fragile hierarchies. Also traits do the right thing[tm]: they allow compositions, not uncontrolable hotchpotch architectures. Oh, wait. The previous email I was going to send in this thread was still a draft. That explains why that comment makes so little sense :) What I was going to say is that how is something like: ?php trait foo { function output() { echo 'foo'; } } trait bar { function output() { echo 'bar'; } } class foobar { use foo; use bar; } ? Better than: ?php class foo { function output() { echo 'foo'; } } class bar { function output() { echo 'bar'; } } class foobar extends foo, bar { } ? Both are ambiguous if there is no documented conflict resolution: just because there's a proposal for traits doesn't mean you can't clearly define conflict resolution for multiple inheritance. I don't see either being intrinsically better than the other (and yes, I have read the papers about both). -- Geoffrey Sneddon http://gsnedders.com/ -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
John Campbell schreef: On Tue, Feb 19, 2008 at 3:54 PM, Jochem Maas [EMAIL PROTECTED] wrote: how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait a person coming accross 'use' or 'include' in the context of trait attribution may either make assumptions or become confused as to possible changes/additions to the use and/or include functionality, a new keyword that aptly describes the intention will more likely force users to actually find out what it means. IMO, the keyword should be a verb because the code is instructing the class to add a behavior. possesses and exhibits are adjectives which doesn't make much sense. My vote would be something like acquire. that's a good point - someone else mentioned 'consumes' which also seems to fit quite nicely. my main point was to use a different keyword to either 'use' or 'include' to avoid misconception, assumptions and basically get anyone not familiar with the syntax to actually RTFM (I'd probably be guilty of glossing over it, if I saw 'include' myself ... ;-) personally I like 'exhibits' ... it sounds right, to me. I don't agree with the argument that non english speaking users would have problems with such a word any more than most other keywords already in use (e.g. 'implements') ... although the spelling of 'possesses' could indeed be rather annoying :-) Regards, John Campbell -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
Hi Stefan, Thanks for writing such a good proposal. In general I think traits is a very interesting idea. I can think of a few cases in my life as a programmer where it could have helped me out. I think some comments re: the syntax/naming are good ones but I prefer not to get into naming in this email. I believe we can brainstorm re: naming when we figure out exactly what we want to do. I do support though finding a way which is simple for non-English speakers but not too simple like Perl:) Thinking back at the times when something like this would have been useful to me I think there are a couple of main points I'd like to brainstorm about: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. b) I haven't thought this through completely but I think we may want to consider a different model from supporting removing and aliasing of functions. I think this can create a lot of complications especially in larger works and it'll be write-once code and hard for a newcomer to the code to really understand. I think the main reason to support removing/aliasing of functions is in order to avoid conflicts with other Traits/Class methods. Maybe what we can do is to have only aliasing but what it would do is to create a public function with the new name and convert the old function into a private function. Benefits: - Keeps the old code from running predictably without breaking dependencies. - Possibly even allowing some form of is-a relationship to continue to be valid (and therefore the interface discussion may even be resolved; at least to a certain level). In the case I faced an is-a relationship (i.e. working instanceof operator) would have been nice. I need to put a bit more thought into this but it's an initial attempt to provide an additional point of view which may actually give some more structure to the proposal while still delivering the benefits of this idea. I think if this kind of idea could be fully baked it would solve the problems I have had in the past possibly without the more dangerous renaming/removing of functions. I have not looked into feasibility of this idea yet. Anyway, good ideas and thanks for the very professional way you have brought this idea to the community. Let's try and nail down the behavior and then we can have the harder naming discussion :) Just saying harder because I've always considered naming the hardest part in software engineering... Andi -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Wednesday 20 February 2008, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hi Andi. Why no ppp on Traits? It seems useful to be able to pull in a utility function or functions that can be leveraged from other methods, like domain-specific parsers, without exposing them to the outside world. Is it an engine-level implementation issue, or a conceptual complexity issue? I don't really see a complexity issue on the developer level, at least for me. -- Larry Garfield AIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
Because then you get into similar problems as with multiple inheritance when you have property clashes and other issues. The reason why private is beneficial and different because it will allow you to develop self contained functionality which can be attached to random classes. This can be quite useful for Timers, Counters, Containers, etc... Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 9:54 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP On Wednesday 20 February 2008, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hi Andi. Why no ppp on Traits? It seems useful to be able to pull in a utility function or functions that can be leveraged from other methods, like domain-specific parsers, without exposing them to the outside world. Is it an engine-level implementation issue, or a conceptual complexity issue? I don't really see a complexity issue on the developer level, at least for me. -- Larry GarfieldAIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] RFC: Traits for PHP
My email talked about properties not methods. Please re-read it :) Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 10:51 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP I am unclear on how this: trait ParseThingie { protected function parseThingie($thingie) {...} } trait ProcessThingie { protected function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } allows more opportunity for confusion and clashes than this: trait ParseThingie { public function parseThingie($thingie) {...} } trait ProcessThingie { public function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } (Presumably an un-qualified method would be public for traits just like for classes.) OK the above example is a bit of a strawman, but I don't know a non- strawman example here. :-) That's the clarification I'm asking for. On Thursday 21 February 2008, Andi Gutmans wrote: Because then you get into similar problems as with multiple inheritance when you have property clashes and other issues. The reason why private is beneficial and different because it will allow you to develop self contained functionality which can be attached to random classes. This can be quite useful for Timers, Counters, Containers, etc... Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 9:54 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP On Wednesday 20 February 2008, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hi Andi. Why no ppp on Traits? It seems useful to be able to pull in a utility function or functions that can be leveraged from other methods, like domain-specific parsers, without exposing them to the outside world. Is it an engine-level implementation issue, or a conceptual complexity issue? I don't really see a complexity issue on the developer level, at least for me. -- Larry GarfieldAIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. - - Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- Larry GarfieldAIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
I am unclear on how this: trait ParseThingie { protected function parseThingie($thingie) {...} } trait ProcessThingie { protected function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } allows more opportunity for confusion and clashes than this: trait ParseThingie { public function parseThingie($thingie) {...} } trait ProcessThingie { public function parseThingie($thingie) {...} } class Thingies { use ParseThingie; use ProcessThingie; } (Presumably an un-qualified method would be public for traits just like for classes.) OK the above example is a bit of a strawman, but I don't know a non-strawman example here. :-) That's the clarification I'm asking for. On Thursday 21 February 2008, Andi Gutmans wrote: Because then you get into similar problems as with multiple inheritance when you have property clashes and other issues. The reason why private is beneficial and different because it will allow you to develop self contained functionality which can be attached to random classes. This can be quite useful for Timers, Counters, Containers, etc... Andi -Original Message- From: Larry Garfield [mailto:[EMAIL PROTECTED] Sent: Wednesday, February 20, 2008 9:54 PM To: internals@lists.php.net Subject: Re: [PHP-DEV] RFC: Traits for PHP On Wednesday 20 February 2008, Andi Gutmans wrote: a) I think Traits should be able to act as a self-contained behavior which can always be expected to work. For example if I want a Counter behavior I would like that not to depend on the properties in the containing class. While I don't think we should enable public nor protected properties in Traits I think allowing for private properties in Traits would come in very handy. It also is no problem when it comes to mangling as we can use the Trait name. class Trait { private $counter = 0; function getNextSerialNumber() { return $this-counter++; } } I strongly recommend not to support protected/public and not to even get into the discussion of dealing with conflicts of such properties. But I think private is very useful. Hi Andi. Why no ppp on Traits? It seems useful to be able to pull in a utility function or functions that can be leveraged from other methods, like domain-specific parsers, without exposing them to the outside world. Is it an engine-level implementation issue, or a conceptual complexity issue? I don't really see a complexity issue on the developer level, at least for me. -- Larry Garfield AIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- Larry Garfield AIM: LOLG42 [EMAIL PROTECTED] ICQ: 6817012 If nature has made any one thing less susceptible than all others of exclusive property, it is the action of the thinking power called an idea, which an individual may exclusively possess as long as he keeps it to himself; but the moment it is divulged, it forces itself into the possession of every one, and the receiver cannot dispossess himself of it. -- Thomas Jefferson -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
[EMAIL PROTECTED] wrote: Hi, [..] Request for Comments: Traits for PHP [..] If it doesn't affect performance *MUCH* then I'm all for it ! It can bring better structure for complex designs. Also by reusing, I'm assuming less memory will be needed for the code base which is beneficial. - Mark -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 18/02/2008, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: Hi, during last six months I've studied a language construct called Traits. It is a construct to allow fine-grained code reuse and in my opinon this would be a nice feature for PHP, which I did like to propose here. The following RFC deals with the questions what Traits are, how they are used, why they are usefull and how they do look like in PHP. A patch implementing this new language construct is available, too. Thank you for your attention and I'm looking forward to hear your comments :) Kind Regards Stefan Request for Comments: Traits for PHP :HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html ... contents:: This RFC will discuss at first the motivation for Traits describing the rationals and presenting a short real world use case. The main part will describe the concept of Traits in detail using the syntax for Traits implemented in a patch which is part of this proposal. In the end, the URL of the patch and additional resources about Traits are given. Introduction *Traits* is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabeling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins. They are recognized for their potential in supporting better composition and reuse, hence their integration in newer versions of languages such as Perl 6, Squeak, Scala, Slate and Fortress. Traits have also been ported to Java and C#. Why do we need Traits? -- Code reuse is one of the main goals that object-oriented languages try to achieve with inheritance. Unfortunately, single inheritance often forces the developer to take a decision in favor for either code reuse *or* conceptual clean class hierarchies. To achieve code reuse, methods have either to be duplicated or to be moved near the root of the class hierarchy, but this hampers understandability and maintainability of code. To circumvent this problems multiple inheritance and Mixins have been invented. But both of them are complex and hard to understand. PHP5 has been explicitly designed with the clean and successful model of Java in mind: single inheritance, but multiple interfaces. This decision has been taken to avoid the known problems of for example C++. Traits have been invented to avoid those problems, too. They enable designer to build conceptually clean class hierarchies without the need to consider code reuse or complexity problems, but focusing on the real problem domain and maintainability instead. Traits: A Mechanism for Fine-grained Reuse == A Trait is a unit of reuse much like a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior. The following code illustrates the current implementation of an extended version of the PHP reflection API which provides detailed access to doc comment blocks. ReflectionMethod and ReflectionFunction are classes from the reflection API and have to be extended with exactly the same code. In some situations it would be possible to add a common base class, but in this case it is impossible, because the extended classes are not under our control, i.e., they are implemented in third party code or even in C, like it is the case here. :: ?php class ezcReflectionMethod extends ReflectionMethod { /* ... */ function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } /* ... */ } class ezcReflectionFunction extends ReflectionFunction { /* ... */ function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } /* ... */ } ? With Traits it is possible to refactor this redundant code out. :: ?php trait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ } ? This is just a small example of what Traits are useful for. The next sections will discuss on more advanced techniques and describe how the current implementation of Traits for PHP works. The Flattening Property --- As already mentioned, multiple inheritance and Mixins are complex mechanisms. Traits are an
Re: [PHP-DEV] RFC: Traits for PHP
Hi Mark, If it doesn't affect performance *MUCH* then I'm all for it ! It can bring better structure for complex designs. Also by reusing, I'm assuming less memory will be needed for the code base which is beneficial. the current implementation does not save any memory compared to a user-level copy'n'past solution. But there might be the opportunity to optimize the op_array handling. The performance impact is almost the same for a trait usage as for inheritance or interface definitions. The only costly operation is copying the method body from the trait to the class where it is used. But this should be much cheaper than parsing the method for each single class, what would be necessary if one would use a good old copy'n'past approach. Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Larry, It sounds interesting to me, and I can definitely see the value. I think I'd suggest having multiple included traits override each other, however, so that: trait A { function foo() { echo A; } function bar() { echo A; } } trait B { function foo() { echo B; } function bar() { echo B; } } class C { use A; use B; } $c = new C(); $c-foo(); // prints B since that came second. $c-bar(); Lets suppose you will need here the A for some domain specific reason. This is not possible with this mixin semantics, with traits it is. That said, the conventional OOP mechanism to get the same result would, I think, look something like this: interface iface { function foo(); function bar(); } class I implements iface { function foo() { ... } function bar() { ... } } class A implements iface { protected $iface; function __construct() { $this-iface = new I(); } function foo() { return $this-iface-foo(); } function bar() { return $this-iface-bar(); } } The class/interface method takes a little more typing and an extra function call on the stack, but otherwise what is the advantage of Traits over this method? (Really, I'm genuinely curious.) Yes, it is the typical delegation pattern. Often used to achieve code reuse without the need to inherited and clutter up interfaces with unnecessary stuff. The advantage of traits here is the preservation of the encapsulation property of your classes. In many situations you would need to propagate some state to the delegate which is not a nice thing in all situations. Instead it would be more elegant to have a method in the class to preserve encapsulation. The method could be provided by copy and past, or for consistency and conceptual reasons, by a trait :) You also note that this mechanism has no runtime impact. That's unfortunate, because I'd find the ability to add methods to an object at runtime conditionally based on some other value far more useful in my work. :-) Especially since, as above, there seems to be a way to implement this functionality now as-is with a little more typing, yet runtime modification is still impossible without eval() and similar scary stuff. Vis, I'd find the following more useful in the code I write: trait Baby { function crawl() { ... } } trait Teen { function complain() { ... } } class Person { protected $age; function __construct($age) { $this-age = $age; if ($this-age = 3) { $this-addTrait('Baby'); } if ($this-age =13 $this-age =19) { $this-addTrait(Teen'); } } } $p[1] = new Person(19); $p[1]-complain(); $p[2] = new Person(1); $p[2]-crawl(); foreach ($p as $person) { if ($p instanceof Teen) { $person-complain(); $person-parent-ground($person); } } I don't know if that's technically not feasible or technically not a Trait anymore and therefore off topic in this thread (if it is, that's fine, let me know and I'll shut up about it g), but that strikes me as more useful than just runtime composition. This is not Traits anymore, yes :) and as Rasmus suggests there would be definitely some problems. But you might be interested in Context-oriented Programming, it tries to solve such crosscutting concerns you've described in an dynamic way. Unfortunately I've no code example at hand but you could have a lock at http://www.swa.hpi.uni-potsdam.de/cop/ ContextR for Ruby is very promising to solve such problems. I've had a thought on this for PHP, too. But think there would be many people against something like dynamic behavior even if this looks like an oxymoron ;) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Richard, A question (and again, no idea on feasibility, internals, etc.). The above proposal covers adding/overriding internal methods with external ones. Is it possible to also include additional properties? If not, then you would have to override the constructor method (this could be demoted to documentation rather than code then I suppose). the current proposal does not allow state in your traits. At the moment the solution would be like this: trait A { abstract protected function getFoo(); public function doSomeFoo($bar) { return $this-getFoo().' baz ' . $bar; } } Traits can defined abstract methods to define a required method. This abstract methods can be implemented in the class or in an other trait. There are also notions about stateful traits out there. For instance Scala does implement them, but state is an additional level of complexity and I have tried to avoid it in this implementation, since I have had expected much more complains about the aliasing and exclude operations and its pretended complexity. In my opinion stateful traits are the next logical step, but with the cost for some additional complexity, since you need handle conflicting properties. (The stateful traits approach is to make it private to a traits composition, but this might not be obvious to every user.) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Feb 18, 2008 8:27 PM, [EMAIL PROTECTED] wrote: Hi, during last six months I've studied a language construct called Traits. It is a construct to allow fine-grained code reuse and in my opinon this would be a nice feature for PHP, which I did like to propose here. The following RFC deals with the questions what Traits are, how they are used, why they are usefull and how they do look like in PHP. A patch implementing this new language construct is available, too. Thank you for your attention and I'm looking forward to hear your comments :) Kind Regards Stefan I know this is in the bike-shed department, but the following syntax doesn't look very PHP to me: use B { !bigTalk, talk = bigTalk } Could we separate exclusions from aliases somehow? -- troels -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Larry Garfield wrote: On Monday 18 February 2008, Richard Lynch wrote: Why not just allow 'include' here instead? Because include requires the code in question to live in another file, which I don't always want. I'm with Richard Lynch here: Simply allow inclusion. No new language concept, instead an existing one is made more orthogonal which is A Desirable Thing(tm) IMHO. About having it in the same file: You then need to also have the two classes using the Trait to live in the same file (or include_once that file) which is something I'm trying to avoid. I've gotten fond of one class per file for the sake of an autoloader anyway so I don't think separating the common code into a separate file is a big disadvantage. The part about being able to do partial Trait use seems hackish and somewhat complicated to me so I'd rather not have it in the language. It feels a little bit like being able to partially implement an Interface: I think a class should either have a Trait or not. If we're using include to emulate Traits then the same could be accomplished by separating the parts into files (if *really* desired). -1 for Traits as proposed +1 for allowing include in class definitions - Chris -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Stefan, a userland copy'n'paste does not allow to reuse already compiled opcodes. Traits do at least conceptionally. marcus Tuesday, February 19, 2008, 1:09:24 PM, you wrote: Hi Mark, If it doesn't affect performance *MUCH* then I'm all for it ! It can bring better structure for complex designs. Also by reusing, I'm assuming less memory will be needed for the code base which is beneficial. the current implementation does not save any memory compared to a user-level copy'n'past solution. But there might be the opportunity to optimize the op_array handling. The performance impact is almost the same for a trait usage as for inheritance or interface definitions. The only costly operation is copying the method body from the trait to the class where it is used. But this should be much cheaper than parsing the method for each single class, what would be necessary if one would use a good old copy'n'past approach. Kind Regards Stefan Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Rasmus, Tuesday, February 19, 2008, 2:45:15 AM, you wrote: Larry Garfield wrote: You also note that this mechanism has no runtime impact. That's unfortunate, because I'd find the ability to add methods to an object at runtime conditionally based on some other value far more useful in my work. :-) Especially since, as above, there seems to be a way to implement this functionality now as-is with a little more typing, yet runtime modification is still impossible without eval() and similar scary stuff. The idea here is that we want to be able to cache opcodes, classes and functions and optimize them out of the runtime context so the executor can skip creating classes and functions on every single request. A lot of the traffic on this list over the past couple of months seems to ignore this basic premise. Features such as autoload and runtime object manipulation incur a huge performance hit in the sense that they change something that was free before and not only add the cost of the feature itself, but it also means the object in question now can no longer be cached and has to be created on every single request. This doesn't mean we can't consider such features, but people need to also consider the performance implications. For that reason allowing traits in favor of include inside a class body is much better. Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Marcus Boerger wrote: Hello Stefan, any dynamic aspect of a class has brought us to problems in inheritance and required us to design the objct/compile model in a way that inheritance often is done at run time. Imo traits are a way out of this. In fact I'd love to issue a deprecated message as soon as class is found outside of a main block. That would mean deprecating autoload as well since autoloading a class is effectively the same as defining it outside of the main block. -Rasmus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello php, looks good to me. See more detailed thoughts in separate mail resonses. The biggest issue I see is finding a syntax everyone likes. Personally I like everything but one tiny piece, that is you do '!method' to ignore a method from a trait. Since renaming happens in a php array like style I would prefer to have that approach apply for ignoring methods as well. The way to do that imo is 'method=false' or 'method=NULL' which both should be obvious to PHP programmers that heard about Traits. Other than that I'd even appriciate it, if we could get this for 5.3. I mean come on guys it is ready and a very nice solution to the code reuse problem. marcus Monday, February 18, 2008, 8:27:00 PM, you wrote: Hi, during last six months I've studied a language construct called Traits. It is a construct to allow fine-grained code reuse and in my opinon this would be a nice feature for PHP, which I did like to propose here. The following RFC deals with the questions what Traits are, how they are used, why they are usefull and how they do look like in PHP. A patch implementing this new language construct is available, too. Thank you for your attention and I'm looking forward to hear your comments :) Kind Regards Stefan Request for Comments: Traits for PHP :HTML: http://www.stefan-marr.de/artikel/rfc-traits-for-php.html ... contents:: This RFC will discuss at first the motivation for Traits describing the rationals and presenting a short real world use case. The main part will describe the concept of Traits in detail using the syntax for Traits implemented in a patch which is part of this proposal. In the end, the URL of the patch and additional resources about Traits are given. Introduction *Traits* is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabeling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins. They are recognized for their potential in supporting better composition and reuse, hence their integration in newer versions of languages such as Perl 6, Squeak, Scala, Slate and Fortress. Traits have also been ported to Java and C#. Why do we need Traits? -- Code reuse is one of the main goals that object-oriented languages try to achieve with inheritance. Unfortunately, single inheritance often forces the developer to take a decision in favor for either code reuse *or* conceptual clean class hierarchies. To achieve code reuse, methods have either to be duplicated or to be moved near the root of the class hierarchy, but this hampers understandability and maintainability of code. To circumvent this problems multiple inheritance and Mixins have been invented. But both of them are complex and hard to understand. PHP5 has been explicitly designed with the clean and successful model of Java in mind: single inheritance, but multiple interfaces. This decision has been taken to avoid the known problems of for example C++. Traits have been invented to avoid those problems, too. They enable designer to build conceptually clean class hierarchies without the need to consider code reuse or complexity problems, but focusing on the real problem domain and maintainability instead. Traits: A Mechanism for Fine-grained Reuse == A Trait is a unit of reuse much like a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior. The following code illustrates the current implementation of an extended version of the PHP reflection API which provides detailed access to doc comment blocks. ReflectionMethod and ReflectionFunction are classes from the reflection API and have to be extended with exactly the same code. In some situations it would be possible to add a common base class, but in this case it is impossible, because the extended classes are not under our control, i.e., they are implemented in third party code or even in C, like it is the case here. :: ?php class ezcReflectionMethod extends ReflectionMethod { /* ... */ function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } /* ... */ } class ezcReflectionFunction extends ReflectionFunction { /* ... */ function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } /* ... */ } ? With Traits it is possible to refactor this redundant code out. :: ?php trait
Re: [PHP-DEV] RFC: Traits for PHP
Hello Rasmus, not really. We can have a table that keeps track of which class was declared in what file. Then we could actually break down files into class definitions and only import the requested part. In a perfect world each class would be in its own file. A file would only create a single class and nothing more or contain the code to generate output, probably some short, flat procedural code. Then each of these files would get compiled and cached. And loaded from those output generating files... marcus Tuesday, February 19, 2008, 4:59:19 PM, you wrote: Marcus Boerger wrote: Hello Stefan, any dynamic aspect of a class has brought us to problems in inheritance and required us to design the objct/compile model in a way that inheritance often is done at run time. Imo traits are a way out of this. In fact I'd love to issue a deprecated message as soon as class is found outside of a main block. That would mean deprecating autoload as well since autoloading a class is effectively the same as defining it outside of the main block. -Rasmus Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On 19.02.2008, at 15:32, Marcus Boerger wrote: In fact I'd love to issue a deprecated message as soon as class is found outside of a main block. err .. deprecated? as in you want to deprecate the possibility entirely? or you just want to hin to the user that its a bad idea .. (not sure if even E_STRICT would be a good fit there). regards, Lukas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hello Lukas, it doesn't work with opcode cashes. So I want at least an E_STRICT here. And yes I mean what I wrote. That's why I wrote it. marcus Tuesday, February 19, 2008, 6:40:08 PM, you wrote: On 19.02.2008, at 15:32, Marcus Boerger wrote: In fact I'd love to issue a deprecated message as soon as class is found outside of a main block. err .. deprecated? as in you want to deprecate the possibility entirely? or you just want to hin to the user that its a bad idea .. (not sure if even E_STRICT would be a good fit there). regards, Lukas Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Stefan, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. cu, Lars -- Lars Strojny Senior Software Developer MediaVentures GmbH (http://mediaventures.de) signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
Hello Lars, we could even go for include here if we wanted to avoid use as much as adding a new keyword. Personally I don't mind using keywords for different stuff as long as it cannot conflict. That is in this case true for both include and use. marcus Tuesday, February 19, 2008, 9:31:29 PM, you wrote: Hi Stefan, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. cu, Lars Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Marcus, Am Dienstag, den 19.02.2008, 17:58 +0100 schrieb Marcus Boerger: [...] looks good to me. See more detailed thoughts in separate mail resonses. The biggest issue I see is finding a syntax everyone likes. I can't agree more. Personally I like everything but one tiny piece, that is you do '!method' to ignore a method from a trait. Since renaming happens in a php array like style I would prefer to have that approach apply for ignoring methods as well. The way to do that imo is 'method=false' or 'method=NULL' which both should be obvious to PHP programmers that heard about Traits. The irritating thing is that currently it would be null = 'oldmethod'. This is what I would critisize in general. I would prefer 'oldMethodName' = 'newMethodName' instead. 'oldMethodName' = null would be really cool. Other than that I'd even appriciate it, if we could get this for 5.3. I mean come on guys it is ready and a very nice solution to the code reuse problem. [...] This would be a killer feature for 5.3! How realistic is it to get this in? [...] cu, Lars signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
On Tue, 19 Feb 2008 13:23:57 +0100, Stefan Marr [EMAIL PROTECTED] wrote: Traits can defined abstract methods to define a required method. This abstract methods can be implemented in the class or in an other trait. There are also notions about stateful traits out there. For instance Scala does implement them, but state is an additional level of complexity and I have tried to avoid it in this implementation, since I have had expected much more complains about the aliasing and exclude operations and its pretended complexity. In my opinion stateful traits are the next logical step, but with the cost for some additional complexity, since you need handle conflicting properties. (The stateful traits approach is to make it private to a traits composition, but this might not be obvious to every user.) Kind Regards Stefan (Sorry for the double email; I meant to send this to the list.) So if the Trait is not stateful, what is the advantage over delegation? That was cited in an earlier email as a shortcoming of delegation, but if the Traits implementation doesn't address it either except through a getter/setter, then it's still functionally equivalent to delegation. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Marcus, Am Dienstag, den 19.02.2008, 21:42 +0100 schrieb Marcus Boerger: [...] we could even go for include here if we wanted to avoid use as much as adding a new keyword. Personally I don't mind using keywords for different stuff as long as it cannot conflict. That is in this case true for both include and use. I'm not sure about this. I can imagine it would not be really intuitive why someone use a namespace and use a trait while he also includes a file and includes a trait. So my only concern is that this great language feature would be harder to understand as it must be. cu, Lars -- Lars Strojny Senior Software Developer MediaVentures GmbH (http://mediaventures.de) signature.asc Description: Dies ist ein digital signierter Nachrichtenteil
Re: [PHP-DEV] RFC: Traits for PHP
Hi Marcus, Hi Troels, The biggest issue I see is finding a syntax everyone likes. Well, lets try some variations. Since renaming happens in a php array like style I would prefer to have that approach apply for ignoring methods as well. The way to do that imo is 'method=false' or 'method=NULL' which both should be obvious to PHP programmers that heard about Traits. At first I'll have to make this clear. Aliasing != renaming. It is not renaming operation. Aliasing will give you an additional name for a method body. By example: trait Foo { public function foo() {echo 'foo';} } class FooFoo { use Foo { bar = foo } } This will eventually result in the following class at runtime: class FooFoo { /* RUNTIME */ public function foo() { echo 'foo';} public function bar() { echo 'foo';} } My idea behind this notation was the key = value thing use Trait { additionalMethodName = method } but may be we should use a keyword here which will be more clear. Troels ask for a separation of aliases and exclusions. Here are some notation proposals: [1] Explicit Except/Without List use Trait except foo1, foo2 { bar = foo1 } the keyword except could may be replaced by exceptfor or without if it fits better. [2a] ! is not readable -- except use Trait { except foo1, foo2; bar = foo1 } [2b] ! is not readable -- without use Trait { without foo1; without foo2; bar = foo1; } [Aa] Aliasing is not obvious use Trait { bar is foo1; //aliasMethod is method } [Ab] Aliasing is not obvious use Trait { bar from foo1; //aliasMethod from method } I'm not sure about Aa and Ab because they do not read well in my opinion. What do you think? -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
firstly, I'd like to reiterate the general sentiment that Stefans RFC is blinding! (that's a good thing in this context ;-) Marcus Boerger schreef: Hello Lars, we could even go for include here if we wanted to avoid use as much as adding a new keyword. Personally I don't mind using keywords for different stuff as long as it cannot conflict. That is in this case true for both include and use. how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait a person coming accross 'use' or 'include' in the context of trait attribution may either make assumptions or become confused as to possible changes/additions to the use and/or include functionality, a new keyword that aptly describes the intention will more likely force users to actually find out what it means. an another alternative might be 'applies' - which doesn't fit the natural language usage of 'trait' but does succintly describe what is happening. just a thought. marcus Tuesday, February 19, 2008, 9:31:29 PM, you wrote: Hi Stefan, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. cu, Lars Best regards, Marcus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
In case anyone is really excited about traits and traits don't make it in soon, I'll point out that something similar has been available in php for years. We've been implementing traits based on the fact that $this has a different meaning in php than in other languages. In php, $this is the most recent object context. So... it's easy to create a trait class and make calls to it from your non-trait class using :: syntax. - calls within the trait class automatically go back to the non-trait class. This makes the purists shudder and they added a STRICT message for it. (If you're a purist please don't bother replying with how evil I am. I already know this makes your stomach turn.) It obviously isn't as clean as a well defined trait feature (or doing a re-architecture of your app to elimate the need), but if you need traits today, this may work for you. - Todd -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Stanislav, traits the included trait is using). Ok this is the scope. Now we would need to adjust all those method bodies, find all method calls on $this-oldMethodName() and change them to $this-newMethodName(). You can't - PHP has dynamic method resolution (think $this-$foo()). Also, it has callbacks - what happens if method is registered as callback is renamed? thanks, this is very good reason not to allow renaming, but aliasing. :) Kind Regards Stefan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
traits the included trait is using). Ok this is the scope. Now we would need to adjust all those method bodies, find all method calls on $this-oldMethodName() and change them to $this-newMethodName(). You can't - PHP has dynamic method resolution (think $this-$foo()). Also, it has callbacks - what happens if method is registered as callback is renamed? -- Stanislav Malyshev, Zend Software Architect [EMAIL PROTECTED] http://www.zend.com/ (408)253-8829 MSN: [EMAIL PROTECTED] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Personally I like everything but one tiny piece, that is you do '!method' to ignore a method from a trait. Since renaming happens in a php array like style I would prefer to have that approach apply for ignoring methods as well. The way to do that imo is 'method=false' or 'method=NULL' which both should be obvious to PHP programmers that heard about Traits. The irritating thing is that currently it would be null = 'oldmethod'. This is what I would critisize in general. I would prefer 'oldMethodName' = 'newMethodName' instead. 'oldMethodName' = null would be really cool. It is not renaming is aliasing :) Feels like I should give some thoughts on why renaming is not a good idea. The question is, how should renaming work and in which scope is it applied? Renaming would imply to adjust all references to a method name in all methods of one composition. A composition are all methods flattened into a class from one specific trait usage (including all methods from traits the included trait is using). Ok this is the scope. Now we would need to adjust all those method bodies, find all method calls on $this-oldMethodName() and change them to $this-newMethodName(). Think this would be possible, yes. But think the original traits idea goes a step further. By excluding a method from a trait it is possible to mesh traits together and build compositions where the result is a interleaving construct, like gears. The problem with renaming is, you will have no chance to achieve such a meshed situation without additional glue code. Excluding a trait method can be thought of as punching a hole into your class which is either filled by another trait or by a method defined in the class itself. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Stefan Marr wrote: Hi Stanislav, traits the included trait is using). Ok this is the scope. Now we would need to adjust all those method bodies, find all method calls on $this-oldMethodName() and change them to $this-newMethodName(). You can't - PHP has dynamic method resolution (think $this-$foo()). Also, it has callbacks - what happens if method is registered as callback is renamed? thanks, this is very good reason not to allow renaming, but aliasing. :) Aliasing doesn't make a lot of sense, as you can always : function newMethod() { return $this-oldMethod(); } just seems like unneeded complexity, without a clear benefit.. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Feb 19, 2008 9:54 PM, Jochem Maas [EMAIL PROTECTED] wrote: how about 'possesses' or 'exhibits' - both these words are closer to the natural language usage of 'trait' with regard to a subject. John exhibits a trait Jack possesses a trait I prefer ``without`` over ``except``, because ``except`` is close to ``exception`` and because it has a different meaning in other languages (Eg. ``catch``). I'm not sure if the use-keyword is a good idea as namespaces are already used. If we use use for traits, maybe going back to import for namespaces would be the way to go. I agree that ``use`` is a bad choice, because of the nameclash with the namespaces syntax (pun intended). ``possesses`` is hideous, but ``exhibit`` isn't too bad. On Feb 19, 2008 10:02 PM, Stefan Marr [EMAIL PROTECTED] wrote: Here are some notation proposals: (snip) I'm not sure about Aa and Ab because they do not read well in my opinion. What do you think? [Ac] How about this: class FooFoo { exhibit Traitor { alias foo as bar; } } -- troels -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Evert, Aliasing doesn't make a lot of sense, as you can always : function newMethod() { return $this-oldMethod(); } Don't think so. You do use aliasing to handle conflicts and in the case of a conflict there is no oldMethod. trait A { public function foo() {echo 'foo';} } trait B { public function foo() {echo 'fooBar';} } class MyClass { use A; use B { !foo, fooBar = foo } } The result will be at runtime: class MyClass { public function foo() {echo 'foo';} public function foo() {echo 'fooBar';} } Here you can't do something like this: class MyClass { use A; use B; } since eventually there wont be any method in MyClass. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi Larry, So if the Trait is not stateful, what is the advantage over delegation? That was cited in an earlier email as a shortcoming of delegation, but if the Traits implementation doesn't address it either except through a getter/setter, then it's still functionally equivalent to delegation. Think the difference is not the functional part here but the conceptional goal which is achieved. Delegation has still a strong right to exist even with traits. The idea of delegation is to reuse a complete entity. May be not the best example but still a good one is the OO Stack build from a linked list. You did like to reuse the list as a container for the stack data. It is full-fledged object here, which will do something for you. But in situations where you have a strong coherence of the state and the behavior you need and the state may consist of several properties, the natural thing would be to implement the behavior in a method in this class, because delegation would require you to make this properties accessible by getters/setters or have methods with many parameters. Here the real question is, does the delegate has a right to exist without this client? Are there any other clients using this class, or is it more appropriated to merge it directly into this class? This questions could only be answered seriously for a specific case. Traits are meant to simplify the code reuse for single methods or groups of methods while delegation allows reuse of complete autonomous entities. Well, think the above is only true in a world of perfect design ;) -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
On Feb 19, 2008 10:51 PM, Evert | Rooftop [EMAIL PROTECTED] wrote: Aliasing doesn't make a lot of sense, as you can always : function newMethod() { return $this-oldMethod(); } just seems like unneeded complexity, without a clear benefit.. I believe the idea was to resolve nameclashes. -- troels -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] RFC: Traits for PHP
Hi, Am Montag, den 18.02.2008, 20:27 +0100 schrieb [EMAIL PROTECTED]: [...] To underpin this relationship, it is possible to declare that a Trait implements an interface like this:: ?php interface IHello { public function sayHello(); } trait SayHello implements IHello { public function sayHello() { echo 'Hello World!'; } } class MyHelloWorld { use SayHello; } $o = new MyHelloWorld(); var_dump($o instanceof IHello); // bool(true) We have discussed that in IRC a bit and a lot of questions remain. The most important issue to me how to handle interface implementations in cases where methods from the interface implementing trait are renamed in the trait consumer class. I would propose to not overcomplicate things here and I see no real advantage in allowing traits to implement interfaces. I think also for the sake of conceptual integrity separating interfaces clearly from traits is a good idea: interfaces define structure while traits are function buckets. A class may use traits, may implement interfaces and may extend another class. This paradigm is pretty easy to explain to the user. cu, Lars -- Lars Strojny Senior Software Developer MediaVentures GmbH (http://mediaventures.de) signature.asc Description: Dies ist ein digital signierter Nachrichtenteil