Re: [RFC][Vote] Typed Properties

From: Date: Wed, 25 May 2016 13:59:06 +0000
Subject: Re: [RFC][Vote] Typed Properties
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-93504@lists.php.net to get a copy of this message
Hi, Nikita Popov wrote:
On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthreads@pthreads.org> 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/

« previous php.internals (#93504) next »