Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:61921 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 80275 invoked from network); 1 Aug 2012 13:42:35 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Aug 2012 13:42:35 -0000 Authentication-Results: pb1.pair.com header.from=php@stefan-marr.de; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=php@stefan-marr.de; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain stefan-marr.de from 81.20.134.149 cause and error) X-PHP-List-Original-Sender: php@stefan-marr.de X-Host-Fingerprint: 81.20.134.149 vps-1012701-4512.united-hoster.de Received: from [81.20.134.149] ([81.20.134.149:58870] helo=vps-1012701-4512.united-hoster.de) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D1/48-32875-84239105 for ; Wed, 01 Aug 2012 09:42:34 -0400 Received: from [134.184.43.20] by vps-1012701-4512.united-hoster.de with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.72) (envelope-from ) id 1SwZC0-0005lm-DG; Wed, 01 Aug 2012 15:42:29 +0200 Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii X-Priority: 3 In-Reply-To: Date: Wed, 1 Aug 2012 15:42:27 +0200 Cc: Content-Transfer-Encoding: quoted-printable Message-ID: <7D18CEE8-F045-43BF-BC4D-8A718FB5CED0@stefan-marr.de> References: <232501B15F7F4B3197123F219370E36D@pc> <2125641B4C7D4D6E8616F86C9C5563D2@pc> <5D98E000-D40D-43EC-9C94-D5B00331C82E@stefan-marr.de> To: Stan Vass X-Mailer: Apple Mail (2.1084) Subject: Re: [PHP-DEV] Traits behavior still up in the air in 5.4 From: php@stefan-marr.de (Stefan Marr) Hi Stan: On 01 Aug 2012, at 14:56, Stan Vass wrote: >> =46rom that follows that traits override the super class's methods. >> And, conflict resolution is only done between traits, not between a = class and its traits. >> The class body is a definite thing. Why would you purposefully add = something to a class body that conflicts with a trait? >> The class needs to know exactly what the traits are doing. There is = no black-box reuse. >=20 > But that's precisely my point. No class would *purposefully* add = something to conflict with a trait. Then by your own description the = only case is *accidentally* adding something to conflict with it. In = such a case why on Earth is it allowed without a fatal error? Because it is not a matter of horizontal reuse. Why don't you get a warning when you override an inherited method? Because that is precisely the way things are supposed to work. The body of a class is not a trait. These methods are not 'equals'. I still think that design decision is a sensible one with respect to the = rest of PHP. >=20 >> The use case for overriding is typically that you got a conflict that = you need to resolve by making a call to both conflicting methods. >> Consider two traits that happen to provide a log() function, and in = the resulting class you need to call both in all places log() has been = called before. >> Since the user of these traits is the only place where such semantic = is sensibly defined, the method in the class body is overriding the = traits methods, and can access aliases you >> introduced for the traits' methods. >=20 > The way it works right now, on conflict, a class may access the trait = method via the alias, or its own overriden copy by the conflicting name. > What is a trait to do? It can't access its own method at all as it = doesn't "know" the alias. >=20 > The way this is implemented makes no sense, I'm afraid. Traits are not classes, traits are supposed to enable composition. There is no static binding between trait methods. And, yes, this is by = design. It makes sense when you use traits for things you couldn't use classes = for. If you need strong consistency guarantees then you want to use classes. >=20 >> Let's use your example and make something more complex out of it: >>=20 >> trait T { >> function bar(){ $this->print(); >> $str =3D 'print'; >> $this->$str(); } >> function print() { echo 'trait'; } >> } >>=20 >> > class C { >> use T { print as foo; } >> } >>=20 >> What is supposed to happen in this example if we assume renaming? >> Would you expect the first function call to print() in bar() to work = after the renaming? >> Would you expect the second call, using metaprogramming, to work as = well? >=20 > It's very simple: >=20 > 1) *only* the original name should work for methods defined in a trait = (including metacalls). > 2) *only* the new name should work from methods defined in the using = class (including metacalls). >=20 > Yes, I know: this is a lot more complicated to implement. *But* if = we'll take shortcuts in user-facing behavior just because it's simpler = to implement, then aliasing should've have never been added at all for = 5.4, until it can be implemented reasonably. So, what is your proposal? >=20 >> If we use aliasing instead of renaming, we have predictable behavior = for all options. >=20 > It's not predictable at all. If the class defines "function print" in = your example above, the trait suddenly can't call it's own method = anymore! Metacall or not. It is calling another method instead, indeed. That's composition, and = that's what traits are designed for. >> There is no proper way to handle state, state requires splitting, = merging, and what not. None of the research prototypes provides a simple = solution. >=20 > State does not require splitting, merging. What does state "splitting" = even mean? Here's a very simple design principle here: if you can't = guarantee correctness for a behavior, provide a limited behavior, which = guarantees correctness. This is how language design works. If there's a = conflict, die with a fatal error, make people rename their properties so = there's no conflict. http://scg.unibe.ch/archive/papers/Berg07aStatefulTraits.pdf > Assuming *silently* that the user is intentionally colliding state = variables between traits because he/she wants to merge/split state is = insanity IMO. Instead of calling my insane, I would prefer if you make constructive = proposals. I guess, since you are an expert in language design (and an active user = of PHP), you are aware of this behavior: class T1 { public function foo() { $this->prop =3D 1; } } class T2 extends T1 { public function bar() { $this->prop =3D 2; } } $o =3D new T2; $o->foo(); $o->bar(); var_dump($o); What is your point again? Traits offer already a much stronger safety-net than most other = constructs in the language. And, thereby are way to strict for some = people. >> The solution we have is a 'best effort' solution. >> If you can do better, please make a proposal. >=20 > I did in my original email. No property collisions. Fatal errors. It's = very simple. There is nothing simple in PHP... People don't like fatal errors, especially not for things they intend to = just work. =46rom my example above, the kind of guarantees you expect are just not = something that is part of what PHP is. >> I assume we are talking about: = http://php.net/manual/en/language.oop5.traits.php >>=20 >> Static variables and members/properties are not related at all. The = writer of the documentation didn't get the wording correct. Please feel = free to submit a patch. >=20 > I've submitted a doc bug. No one want to fix it since they think it's = PHP that's wrong, not the manual. I can't do anything more about it. > Here's the link: https://bugs.php.net/bug.php?id=3D62156 I don't know who 'they' are, but I am the insane (thanks for that = attribute) person who wrote the RFCs and the implementation. So, either = you accept my answer that static properties just work, and you fix the = manual by providing a greatly appreciate patch, or, you open a new thread and propose a change, start an RFC, and all = that jazz. Best regards Stefan --=20 Stefan Marr Software Languages Lab Vrije Universiteit Brussel Pleinlaan 2 / B-1050 Brussels / Belgium http://soft.vub.ac.be/~smarr Phone: +32 2 629 2974 Fax: +32 2 629 3525