Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:42464 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 10062 invoked from network); 3 Jan 2009 14:50:44 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Jan 2009 14:50:44 -0000 Authentication-Results: pb1.pair.com header.from=helly@php.net; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=helly@php.net; spf=unknown; sender-id=unknown Received-SPF: unknown (pb1.pair.com: domain php.net does not designate 85.214.94.56 as permitted sender) X-PHP-List-Original-Sender: helly@php.net X-Host-Fingerprint: 85.214.94.56 aixcept.net Linux 2.6 Received: from [85.214.94.56] ([85.214.94.56:56370] helo=h1149922.serverkompetenz.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 82/41-01547-F3B7F594 for ; Sat, 03 Jan 2009 09:50:43 -0500 Received: from MBOERGER-ZRH.corp.google.com (238-135.62-81.cust.bluewin.ch [81.62.135.238]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by h1149922.serverkompetenz.net (Postfix) with ESMTP id E68C111F09F; Sat, 3 Jan 2009 15:50:34 +0100 (CET) Date: Sat, 3 Jan 2009 15:47:44 +0100 Reply-To: Marcus Boerger X-Priority: 3 (Normal) Message-ID: <145582992.20090103154744@marcus-boerger.de> To: =?iso-8859-15?Q?Johannes_Schl=FCter?= CC: Marcus Boerger , =?iso-8859-15?Q?David_Z=FClke?= , PHP Internals In-Reply-To: <1230920192.6125.141.camel@goldfinger> References: <08AA10DA-2704-415C-8A8C-893C89990DC1@bitextender.com> <868073456.20081231173818@marcus-boerger.de> <1230920192.6125.141.camel@goldfinger> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness From: helly@php.net (Marcus Boerger) Hello Johannes, Friday, January 2, 2009, 7:16:32 PM, you wrote: > Hi, > On Wed, 2008-12-31 at 17:38 +0100, Marcus Boerger wrote: >> So far it is. Yet I as much as you do not like the inconsistency. So I >> spend a little bit on providing the following patch that should do >> what >> you were looking for. > I thought bout this issue for one day or so, there are three things to > consider here: > - the language design question > - implementation-related things > - getting 5.3 out > For the first question I have to say that this is a major change to > language. Bringing this feature in makes it a mixture of a class-based > OO model and JavaScript-like class-less OO model. As I tend to read way > more code than I write I, personally, prefer the clearer class based > approach. > Nonetheless there seems to be large support for this, so let's lake a > deeper look: >> The disadvantage: Calling properties is case sensitive while calling >> methods isn't. But since this has nothign to do with this patch and >> the patch only increases consistency I am all for applying it. > That's one of the symptoms of the underlying problem we're having: In > our object implementation methods and properties are kept completely > separated. Using properties now like methods will have side effects, one > is described above. I found another one today: > class A { > public $p; > public function __construct() { > $this->p = function() { echo 1; }; > } > } > class B extends A { > private function p() { > echo 2; > } > } > $a = new A(); > $b = new B(); > $a->p(); > $b->p(); ?>> > What do you expect? Well, the first call, to $a->p(); works, the second > one, to $b->p();, doesn't since where accessing the private method > B::p(). > $ sapi/cli/php test.php > 1 > Fatal error: Call to undefined method B::p() in test.php on line 16 > Depending on your view on this that result can be correct or wrong, it > might even be wrong in different ways, maybe overwriting $a->p with > $b->p should be forbidden, maybe it should treat private elements like > non-existent ones. > The obvious thing is that it feels like the "is-a" relationship isn't > enforced anymore. First, for properties we already have that anyway. Remember you can add properties to object instances at any time. So being able to add methods at any time just reduces one more inconsistency between things. Also since properties follow a mixture of class based and prototype based object model we have to respect prototype semantics for the parts where proptotype model is used. This means when you dynamically add a closure then this is done in the manner of prototype semantics and needs to follow it. Thus with a slightly different code the result is perfectly correct: p = function() { echo 1; }; $a->p(); $b->p(); ?> So this raises the question what the status quo without the patch is: class Test { public $func; function __construct() { $this->func = function() { echo __METHOD__ . "()\n"; }; } private function func() { echo __METHOD__ . "()\n"; } } $o = new Test; $f = $o->func; $f(); // Test::{closure}() $o->func(); // Error call to private method... So apparently we already have the exact issue at hand and we take precedence in the actual function which in my opinion is a good choice. And this also is exactly the behavior your example with the patch applies shows. To summarize this from my point of view we only get a bit more of consistency. But for people with a JavaScript background we get a lot more. As we now support what they are used to and that actually is a pretty big advantage. However if that is the intention, then something we might want to look into in order to make it easier for those people is to fix something that propbably looks wrong to them. That is binding a closure to a property outside of the scope of the object does not bind the object to the this_ptr as it would in case the assignment is done inside the object scope (a class method). But once again this is somethign to be fixed whether or not we apply the patch. > Additionally there are other areas with such conflicts: Reflection > (ReflectionMethod doesn't work, ReflectionProperty has no hint it's > executable, ...) and other meta-functionality are obvious, others might > (and will) be quite hidden. Reflection now has closure support. > I guess the only solid way to implement that feature would be by merging > the property and method tables into an "element" table so we reduce such > conflicts -- while that's a major engine and language change. Every > other approach will have side-effects. That would mean a major change in language and we should not go that route. > This leads us to the third consideration: 5.3 is around 1.5 years in > development now with lots of new features. It was announced that we > wanted to go to a beta status to get it out soon ("release early, > release often" ...) > I'd say it would be good to concentrate on making 5.3 stable and then > see how new features are accepted. If users really demand such a > functionality, when using closures for "real life" development, we can > still add it, but that should be done with the time needed to identify > side-effects and other consequences, not in a rush during holiday season > after a feature freeze has been announced. Stable also means stable features and semantics. And that includes trying to get rid of inconsistencies. marcus Best regards, Marcus