Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:64571 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 26273 invoked from network); 5 Jan 2013 23:37:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 5 Jan 2013 23:37:15 -0000 Authentication-Results: pb1.pair.com header.from=cpriest@zerocue.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=cpriest@zerocue.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zerocue.com designates 67.200.53.250 as permitted sender) X-PHP-List-Original-Sender: cpriest@zerocue.com X-Host-Fingerprint: 67.200.53.250 mail.zerocue.com Received: from [67.200.53.250] ([67.200.53.250:58171] helo=mail.zerocue.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 42/EB-62408-A29B8E05 for ; Sat, 05 Jan 2013 18:37:15 -0500 Received: from [172.17.0.122] (unknown [66.25.151.173]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.zerocue.com (Postfix) with ESMTPSA id 7CE81121072; Sat, 5 Jan 2013 23:37:11 +0000 (UTC) Message-ID: <50E8B922.4070104@zerocue.com> Date: Sat, 05 Jan 2013 17:37:06 -0600 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Thunderbird/17.0 MIME-Version: 1.0 To: Steve Clay CC: internals@lists.php.net References: <50E41BB6.4030901@zerocue.com> <50E4A43E.6030302@zerocue.com> <50E4B232.5000505@mrclay.org> <50E4BDDE.8050509@zerocue.com> <50E4D0BB.7060701@mrclay.org> <50E4FA09.7030001@zerocue.com> <50E529B6.1050903@sugarcrm.com> <50E593DF.9090004@mrclay.org> <50E60994.4000400@sugarcrm.com> <50E86BBB.2080104@mrclay.org> <50E8797C.7030203@zerocue.com> <50E8950C.1080102@mrclay.org> In-Reply-To: <50E8950C.1080102@mrclay.org> Content-Type: multipart/alternative; boundary="------------060701060407020109040507" Subject: Re: [PHP-DEV] [PHP-RFC] Property Accessors 1.2 for Final Review before Vote From: cpriest@zerocue.com (Clint Priest) --------------060701060407020109040507 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit The problem I see with your proposal is that get/isset/unset could all bypass the setter which I think is a bad idea. If the problem is simply this "hidden state" that keeps being referred to, I thought the solution I mentioned before would be better. To re-iterate that prior idea is to make it behave identically to __get(). The first call to a getter would initiate the (calling) guard, any other access outside of the getter from that point forward would return NULL, but the access by the getter would return the property. It would stop the infinite loop, stop invalid access, the author could see where they've gone wrong (a warning could be emitted even) and we maintain the current solution without introducing more complexity (which would probably lead to further problems). For your pro's listed * I don't think a local variable named $prop (for example) is very clear that it's going to modify a property of $this, I would expect $this->prop and that $prop would be modifying a local value. * That's a misconception that I accidentally let perpetuate because I wasn't careful when I confirmed your alternate verbiage. And then it adds the evil's listed. -Clint On 1/5/2013 3:03 PM, Steve Clay wrote: > On 1/5/13 2:05 PM, Clint Priest wrote: >> I like the alternate idea here, but I'm not sure what advantage it >> has over the current >> situation? > > See the "Pros" I listed. The primary being a clear differentiation > between calling accessors and handling of the storage value associated > with the property. > >> if an accessor is >> already "in the call chain" then it will not be called again and >> "standard property rules" >> take effect. > > I see that as not simpler, and in fact leading to small bugs whenever > getters/setters start becoming complex enough to call outside methods. > Consider this: > > class Foo { > public $bar = 2 { > get { return $this->calcBar(); } > } > public function calcBar() { > return $this->bar * 3; > } > } > > echo $foo->bar; // 6 > > Within calcBar, "$this->bar" is the raw property (2), because hidden > state has "unwrapped" (if you will) the property. > > echo $foo->calcBar(); // 18 > > But here, within the first call of calcBar "$this->bar" triggers the > getter. Now, of course, this is a foolish implementation, but within > any method that could be called from the getter/setter, the symbol > $this->bar could mean two completely different things; I think this is > bad. > > If, as I proposed, the storage var were only accessible as $prop in > the accessor scopes, that would force authors to pass $prop to any > supporting methods, clarifying intent. $this->bar would *always* be > accessor calls. > > In this model, I think infinite-loop-causing recursions would be > easier to spot. If absolutely necessary we could always throw a fatal > error whenever a getter was called twice in the same call chain. > > Steve > >>> AFAICT C# strictly separates fields ("properties" in PHP) and >>> properties (a set of >>> accessors that emulate a field). >>> >>> So the RFC provides 3 features (using C# terms): >>> 1. A property API >>> 2. A built-in storage variable so you don't need a separate field >>> 3. Access to the storage variable as if it were a field of the same >>> name >>> >>> I think #2 is useful, avoiding the need to make a separate field >>> just to make properties >>> read-only or type-hinted. However I think the complexity and >>> confusion we're running >>> into is mostly caused by #3. >>> >>> I think we might be better served by having another way to access >>> this storage variable. >>> >>> What if instead, we have the storage var available as $prop inside >>> all the accessors? >>> These would be the default implementations: >>> >>> get { return $prop; } >>> set($value) { $prop = $value; } >>> isset { return $prop !== NULL; } >>> unset { $prop = NULL; } >>> >>> Pros: >>> * Makes clear that $prop is regular var access, and that >>> $this->PropertyName *always* >>> goes through accessors >>> * Gives isset/unset full access to the storage var, which allows >>> doing things that can't >>> be done via setter/getter. E.g. you could actually implement a >>> property being "unset", >>> which would be different from having it set to NULL. >>> >>> Cons: >>> * Allows "evil", like having reads affect the storage var. >>> * Allows authors to hang themselves with recursive accessor calls, >>> BUT those mistakes >>> would be apparent from looking at the code. >>> >>> What functionality possible in the RFC would be lost by this? >>> >>> Steve Clay >> > > > Steve Clay -- -Clint --------------060701060407020109040507--