Hi,

Nikita Popov wrote:
On Wed, May 25, 2016 at 10:30 AM, Joe Watkins <pthre...@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/

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to