Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:91780 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 45908 invoked from network); 19 Mar 2016 20:32:25 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 19 Mar 2016 20:32:25 -0000 X-Host-Fingerprint: 94.10.73.146 unknown Received: from [94.10.73.146] ([94.10.73.146:2768] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 3B/AA-03097-757BDE65 for ; Sat, 19 Mar 2016 15:32:23 -0500 Message-ID: <3B.AA.03097.757BDE65@pb1.pair.com> To: internals@lists.php.net References: <56E9C241.1090905@fleshgrinder.com> Date: Sat, 19 Mar 2016 20:32:19 +0000 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0 SeaMonkey/2.40 MIME-Version: 1.0 In-Reply-To: <56E9C241.1090905@fleshgrinder.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 94.10.73.146 Subject: Re: [PHP-DEV] [RFC Discussion] Typed Properties From: ajf@ajf.me (Andrea Faulds) Hi, Fleshgrinder wrote: > On 3/16/2016 5:36 PM, Phil Sturgeon wrote: >> 2. This whole temporary nullability situation, where unset properties >> will error on attempted usage if not set. Should they instead error >> after the constructor has been called if they are still not holding a >> value? >> > > I see a big problem with the erroring no matter when as others already > pointed out, e.g. together with named constructors (or factory methods > if you prefer that name) but also with lazy loading. I think that the > null value of properties during and after construction should simply be > ignored and left to the implementer. I know that it would be nice to > have 100% assurance that the property is always set but it would simply > result in rules that are too strict for various use cases. I mean, > aren't we trying to solve a problem that never was a problem here? This is actually a problem for optimising PHP. If the compiler cannot be sure a property's value actually matches its declared type, it can't optimise operations on that property to remove a type check. I also think it would be unintuitive if typed properties had some exception where they don't obey the given type. If I ask for an integer, then surely I should get an integer? > > Another more complicated user case would be *mysqli_fetch_object* that > populates the properties with values from a storage but values that > should become something specific and strict at some point but are > initially populated as strings. Type coercion would be a nice thing here > but with strict checks afterwards. Note that this cannot be handled by > the extension due to user types: > > final class Bar { > > private string $data; > > public function __construct(string $data) { > $this->data = $data; > } > > } > > final class Foo { > > private Bar $bar; > > private function __construct() { > if (isset($this->bar)) { > $this->bar = new Bar($bar); > } > } > > } > > $mysqli_result->fetch_object(Foo::class); > > It is correctly populated with a string and the constructor changes it > to the desired instance. All fine, but the strict type check would kill > everything here. > > I think that the strict type checks should start with the first > *userland* assignment and at no other point in time. The correct > initialization of an object is up to the implementer as it always was. This adds a loophole to property type checks which, as previously mentioned, prevents us from performing optimisations. I also don't see why internal functions should be treated specially here, given that surely one could write userland code with the same needs as MySQLi? It doesn't seem intuitive. > On 3/16/2016 6:27 PM, Chris Riley wrote: >> [...] how about some syntax which allows for a property to be null, >> or for it to be a specific type. I'd suggest a null assignment to >> fall in line with parameter type hints eg: >> >> class Foo { >> protected int $bar = null; //can be null >> private stdClass $baz; //can't be null >> } >> > > This aligns nicely with the syntax that is present in PHP for arguments > since ages and it directly could solve the Nullable problem mentioned in > future scope. We could certainly do this, but I'm not sure we should. Like for arguments, this would mean that your default value must be null, and you don't have to assign to it. But what if you want a different default value? What if you want to require it be assigned to? Adding a syntax form for nullable types (e.g. `?int` or `int|null`) would avoid these issues, and also solve the nullable return type issue. > > On 3/16/2016 5:36 PM, Phil Sturgeon wrote: >> 3. Weak vs Strict. Right now this is entirely strict, with no >> declare() to change mode. Reasons for this vary, from various sources, >> but include "Not sure how to implement it" and "Well people should not >> be using properties as part of their public API". >> > > An ini setting to control type checks and hints would be a nice thing to > have. An INI setting to control type checks is impractical, because it would affect all PHP code running in a given PHP interpreter. This means you control not only the type checking mode of your own code, but also of all the libraries you're using. Unless you never use other people's code, using this INI setting would just break things. > Like the checked mode of Google's Dart language. Such a setting > could and should also allow to disable type checks altogether, like we > have it with assertions: > > strict_types = -1 ; NOOP > strict_types = 0 ; PHP 5 Style > strict_types = 1 ; PHP 7 Coercion Style > strict_types = 2 ; PHP 7 Strict Style Why would you want to disable type checks altogether? There might be a small performance improvement, but you've removed important error checking. What if something goes wrong at runtime? > Where 1 would be the default since the default should be for development > and people who hate strict types just throw that zero in their ini and > are fine to reuse any code out there while ignoring all property/scalar > type checks/hints. This solves a problem which I don't believe exists. The system PHP 7 has means that if you don't want to use strict types, they never affect you. > > This would make the `declare` thingy pretty useless and I think it is > easier to understand. I thought that this approach was kind of weird > since its inception. Yes, the declare() approach is unusual compared to other settings. That's because it was designed so the choices your code makes doesn't affect other code which uses it. In the Composer era, this matters, because a lot of code your interpreter is running will not be written or maintained by you. Thanks. -- Andrea Faulds https://ajf.me/