Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:93504 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 78064 invoked from network); 25 May 2016 13:59:13 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 25 May 2016 13:59:13 -0000 X-Host-Fingerprint: 137.50.159.218 oa-edu-159-218.wireless.abdn.ac.uk Received: from [137.50.159.218] ([137.50.159.218:28534] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 80/72-63510-DAFA5475 for ; Wed, 25 May 2016 09:59:10 -0400 Message-ID: <80.72.63510.DAFA5475@pb1.pair.com> To: internals@lists.php.net References: Date: Wed, 25 May 2016 14:59:06 +0100 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: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 137.50.159.218 Subject: Re: [PHP-DEV] [RFC][Vote] Typed Properties From: ajf@ajf.me (Andrea Faulds) Hi, Nikita Popov wrote: > On Wed, May 25, 2016 at 10:30 AM, Joe Watkins wrote: > >> > *Nullable typed properties will not raise an exception when accessed >> before initialization.* >> > > I don't agree with this choice, for three reasons: > > a) This unnecessarily restricts what can be expressed in the type system. > With these semantics it will no longer be possible to express that a > property should be nullable, but have no default value. This situation is > not uncommon in practice, in particular anytime you have a nullable > constructor argument, you will want the corresponding property to be > nullable without a default, to ensure that it is explicitly initialized. I agree with you here. In some cases, there are *three* potential meaningful states for a property: * uninitialised - the constructor (or indeed, other code) is yet to set it * null - the property is left intentionally empty * some other value - the property is intentionally given a value A simple example might be a Lisp-style linked list cell: class LinkedList { public int $head; public ?LinkedList $tail; } In a properly initialised LinkedList, the $head is some value, and the $tail is either another linked list (the remainder of the list), or null (we're at the end of the list). Before the LinkedList is initialised, ideally both properties would be undefined. That way, if we make a mistake and fail to explicitly set either in our code, PHP will give us an error message. However, the currently proposed behaviour would mean that this will only happen for $head, and PHP will fill in null for $tail for us. Notice that in this class, we aren't using null to mean a property that hasn't yet been set. Instead, we're using it to mean a property that's been deliberately left unfilled. So PHP has assumed for us that if we forget to set $tail, the remainder of the list is empty. Yet PHP assumed that if we forget to set $head, that's a mistake and must produce an error. This inconsistency of assumptions is unhelpful, and I don't see how this follows from the types I declared. I don't understand why nullable properties have to behave differently here, anyway. Doesn't it add complexity to the implementation to handle them differently from non-nullable typed properties? Doesn't it introduce inconsistency to assume a default value for nullable typed properties, but not for non-nullable ones? > b) This directly contradicts the meaning of ?Type for parameters. For > parameters ?Type means that it's a nullable parameter **without a default > value**. That's the very thing that distinguishes it from the Type $prop = > null syntax. And now ?Type for properties should mean the exact opposite? Given typed properties look much like typed parameters, it would be reasonable for users to expect that they behave the same, so this is a good point. > c) If you view this in a larger scope of union types, this *special case* > becomes even more weird. Why does the particular union Type|null get > special treatment, while all other unions don't? Or is it actually not > specific to "null", but to single value types? E.g. if we also allowed > Type|false, would that also receive an implicit false default value? What > about the type null|false? Does that get an implicit default, and if so, > which? I realize this is not quite in scope for type properties, but the > further evolution of the type system should be kept in mind. This bothers me also. Thanks! -- Andrea Faulds https://ajf.me/