[RFC] [VOTE] Union types

php.internals

Bob Weinand

10 years ago
Hey, It has been long enough under discussion... I've put union types into vote. Please find the RFC located at: https://wiki.php.net/rfc/union_types <https://wiki.php.net/rfc/union_types> The vote is open until the 23th. Thanks for voting, Bob

Derick Rethans

10 years ago
On Tue, 14 Jun 2016, Bob Weinand wrote:
> It has been long enough under discussion... I've put union types into > vote. > > Please find the RFC located at: > https://wiki.php.net/rfc/union_types <https://wiki.php.net/rfc/union_types>
Not clear on some of the wording. When you say: "This RFC proposes a vote on whether ?Foo shall be replaced by Foo | null in general." Do you mean that ?Foo will no longer be allowed at all if this RFCs passes? cheers, Derick

Fleshgrinder

10 years ago
On 6/14/2016 5:22 PM, Derick Rethans wrote:
> Not clear on some of the wording. When you say: > > "This RFC proposes a vote on whether ?Foo shall be replaced by Foo | > null in general." > > Do you mean that ?Foo will no longer be allowed at all if this RFCs > passes? > > cheers, > Derick >
Same question here, since https://wiki.php.net/rfc/nullable_types already passed and directly voiding it makes no sense. I mentioned this before but maybe it is better to change the RFC to disallow the question mark if an union type is in use: # OK ?string null|string string|null ?SomeClass SomeClass|SomeOtherClass|null null|SomeClass|SomeOtherClass SomeClass|null|SomeOtherClass # BAD ?SomeClass|SomeOtherClass ?SomeOtherClass|SomeClass ?string|int ?int|string This would be a perfectly valid and reasonable restriction that makes sense in every way because it helps to avoid ambiguity. However, disallowing ?T is not.
-- Richard "Fleshgrinder" Fussenegger

Bob Weinand

10 years ago
> Am 14.06.2016 um 18:09 schrieb Fleshgrinder <php@fleshgrinder.com>: > > On 6/14/2016 5:22 PM, Derick Rethans wrote: >> Not clear on some of the wording. When you say: >> >> "This RFC proposes a vote on whether ?Foo shall be replaced by Foo | >> null in general." >> >> Do you mean that ?Foo will no longer be allowed at all if this RFCs >> passes? >> >> cheers, >> Derick >> > > Same question here, since https://wiki.php.net/rfc/nullable_types > already passed and directly voiding it makes no sense. > > I mentioned this before but maybe it is better to change the RFC to > disallow the question mark if an union type is in use: > > # OK > > ?string > null|string > string|null > > ?SomeClass > > SomeClass|SomeOtherClass|null > null|SomeClass|SomeOtherClass > SomeClass|null|SomeOtherClass > > # BAD > > ?SomeClass|SomeOtherClass > ?SomeOtherClass|SomeClass > > ?string|int > ?int|string > > This would be a perfectly valid and reasonable restriction that makes > sense in every way because it helps to avoid ambiguity. However, > disallowing ?T is not. > > -- > Richard "Fleshgrinder" Fussenegger >
These last ones (which you describe as "BAD" are anyway disallowed. The separate vote is to remove ?string by string | null as only option. (It basically just preserves the concept of nullability, but reverses the decision to use a trailing ?. This vote is in order to give those who prefer only foo | null instead of ?foo a chance to voice their opinion.) Bob

Stas Malyshev

10 years ago
Hi!
> The separate vote is to remove ?string by string | null as only option.
So we just held a vote on introducing ?type a month ago, to now vote on removing it. Am I the only one to whom it doesn't make a lot of sense?
-- Stas Malyshev smalyshev@gmail.com

Fleshgrinder

10 years ago
On 6/14/2016 8:00 PM, Stanislav Malyshev wrote:
> So we just held a vote on introducing ?type a month ago, to now vote on > removing it. Am I the only one to whom it doesn't make a lot of sense? >
Exactly what I question too especially because the other vote was so overwhelmingly positive.
-- Richard "Fleshgrinder" Fussenegger

Bob Weinand

10 years ago
> Am 14.06.2016 um 20:35 schrieb Fleshgrinder <php@fleshgrinder.com>: > > On 6/14/2016 8:00 PM, Stanislav Malyshev wrote: >> So we just held a vote on introducing ?type a month ago, to now vote on >> removing it. Am I the only one to whom it doesn't make a lot of sense? >> > > Exactly what I question too especially because the other vote was so > overwhelmingly positive.
If we'd voted first on unions (and had a separate vote whether to allow null as type), I'm sure the vote would have been just as positive and the nullables RFC not appeared at all. I'm personally guessing that people mainly wanted to see nullability _at all_ rather than the specific "?" syntax. Thus there's a separate vote... Bob

Zeev Suraski

10 years ago
> On 14 ביוני 2016, at 21:00, Stanislav Malyshev <smalyshev@gmail.com> wrote: > > Hi! > >> The separate vote is to remove ?string by string | null as only option. > > So we just held a vote on introducing ?type a month ago, to now vote on > removing it. Am I the only one to whom it doesn't make a lot of sense? >
I actually think this was discussed ahead of time. The thinking was that we'll approve (or reject) nullable types independently without having to wait for union types. If Union types passed - we'd reconsider the syntax for it. I think we need to clarify the vote here. I'm personally against Union types because it makes no sense for classes, and for scalars we're better off with dedicated solution a (e.g. "numeric"); but if it does pass, I'd rather have just one way of doing nullable types and not two. Zeev

Levi Morrison

10 years ago
> I'm personally against Union types because it makes no sense for classes
I've been over this before but I'll repeat it here for completeness: this is not true. Unions provide a way to discriminate between potential sets of types. Even among classes there is power in unions. Consider the idea of encoding a Something or Nothing with methods such as `map`, `flatmap`, `filter`, etc. A Something will return a Something for map, and a Nothing will return a Nothing. By using inheritance there are two problems: 1. We can create additional subclasses that do not obey the semantics of the type. Imagine how frustrating a stack that does not behave like a stack would be; same principle here. 2. We don't have covariant return types so we cannot express that Nothing::map will return Nothing and Something::map will return Something. Using two final classes for Something and Nothing and then doing a union on them has neither of these downsides. Even if we add return type covariance we cannot solve problem 1. Given that there are numerous other uses with built-in types such as Array | Traversable (iterable), int | string (array key), int | float (numeric) and so forth it does not make sense to me to special case these things. Generality is better for language features than special casing.

Bob Weinand

10 years ago
> Am 14.6.2016 um 21:53 schrieb Levi Morrison <levim@php.net>: > >> I'm personally against Union types because it makes no sense for classes > > I've been over this before but I'll repeat it here for completeness: > this is not true. Unions provide a way to discriminate between > potential sets of types. Even among classes there is power in unions. > Consider the idea of encoding a Something or Nothing with methods such > as `map`, `flatmap`, `filter`, etc. > > A Something will return a Something for map, and a Nothing will return > a Nothing. By using inheritance there are two problems: > > 1. We can create additional subclasses that do not obey the > semantics of the type. Imagine how frustrating a stack that does not > behave like a stack would be; same principle here. > 2. We don't have covariant return types so we cannot express that > Nothing::map will return Nothing and Something::map will return > Something. > > Using two final classes for Something and Nothing and then doing a > union on them has neither of these downsides. Even if we add return > type covariance we cannot solve problem 1. > > Given that there are numerous other uses with built-in types such as > Array | Traversable (iterable), int | string (array key), int | float > (numeric) and so forth it does not make sense to me to special case > these things. Generality is better for language features than special > casing.
What Levi tries to explain: unions are like a temporary virtual super-interface to any accepted class without actually being implemented by them. Typically you are writing adapters for these things, but an adapter is not always the solution (i.e. in cases where a part of the handling is identical, but depending on the actual class (instanceof) they ultimately get dispatched to somewhere else). For exactly these cases (which, I admit, aren’t numerous [The cases where it’s legitimate and there is no other superior solution]) union classes are helpful. Bob

Zeev Suraski

10 years ago
On 14 ביוני 2016, at 22:53, Levi Morrison <levim@php.net<mailto:levim@php.net>> wrote: I'm personally against Union types because it makes no sense for classes I've been over this before but I'll repeat it here for completeness: this is not true. There are more than enough constructs in PHP to handle all these use cases, and handle them nicely. We don't need specialized constructs for every use case. Either way, no point at redoing the discussion. Apologies if I triggered it, context was only the vote. Zeev

Levi Morrison

10 years ago
On Tue, Jun 14, 2016 at 2:43 PM, Zeev Suraski <zeev@zend.com> wrote:
> > On 14 ביוני 2016, at 22:53, Levi Morrison <levim@php.net> wrote: > > I'm personally against Union types because it makes no sense for classes > > > I've been over this before but I'll repeat it here for completeness: > this is not true. > > > There are more than enough constructs in PHP to handle all these use cases, > and handle them nicely. We don't need specialized constructs for every use > case.
To clarify here, you are saying we don't need unions because they are a special case, yes? But you previously stated you are in favor of special casing the language types such as numeric? These are at odds.

Christoph Becker

10 years ago
On 15.06.2016 at 00:51, Levi Morrison wrote:
> On Tue, Jun 14, 2016 at 2:43 PM, Zeev Suraski <zeev@zend.com> wrote: >> >> On 14 ביוני 2016, at 22:53, Levi Morrison <levim@php.net> wrote: >> >> I'm personally against Union types because it makes no sense for classes >> >> I've been over this before but I'll repeat it here for completeness: >> this is not true. >> >> There are more than enough constructs in PHP to handle all these use cases, >> and handle them nicely. We don't need specialized constructs for every use >> case. > > To clarify here, you are saying we don't need unions because they are > a special case, yes? But you previously stated you are in favor of > special casing the language types such as numeric? > > These are at odds.
In my opinion, there have to be always compromises when designing a language for practical purposes. Theoretically, it would not even be necessary for PHP to have scalar types; everything could be done with (immutable) objects as well. However, we do have scalar types, and these are likely to stay, so it seems reasonable to me to add a few special cases to our type system covering this issue (say, Stringable, Iterable, numeric, Invokable). Adding union types as a general mechanism, on the other hand, adds a new level of complexity for the user which is orthogonal to the classical OO type system, at least when type definitions will be added, what I estimate will not take long, due to the verbose inline union typing. And that is easily going to get out of hand, because independent libraries might introduce their own LIB\numeric, for instance, potentially with slightly different definitions (e.g. with or without GMP). Finally, I don't consider |false a very reasonable thing, because the respective functions could return a nullable type as well, what would in my opinion be better anyway for the famous strpos(), which requests the position of $needle in $haystack, what should be either a numeric index or NULL (== not present). And at least built-in functions may also return NULL for wrong argument types, which would require to type their return values as X|false|null to be exact.
-- Christoph M. Becker

Zeev Suraski

10 years ago
> -----Original Message----- > From: morrison.levi@gmail.com [mailto:morrison.levi@gmail.com] On Behalf > Of Levi Morrison > Sent: Wednesday, June 15, 2016 1:51 AM > To: Zeev Suraski <zeev@zend.com> > Cc: PHP internals <internals@lists.php.net> > Subject: Re: [PHP-DEV] [RFC] [VOTE] Union types > > On Tue, Jun 14, 2016 at 2:43 PM, Zeev Suraski <zeev@zend.com> wrote: > > There are more than enough constructs in PHP to handle all these use > > cases, and handle them nicely. We don't need specialized constructs > > for every use case. > > To clarify here, you are saying we don't need unions because they are a > special case, yes? But you previously stated you are in favor of special casing > the language types such as numeric? > > These are at odds.
They're not. Let me supplement what I said: We don't need specialized constructs for every use case; They make sense for ultra-common ones only, and only if the added benefit (compared to doing it using the methods currently available) outweighs the increased cognitive burden. Hence, 'numeric' makes perfect sense, while a generic Union Types feature does not. Zeev

Sebastian Bergmann

10 years ago
On 06/14/2016 08:52 PM, Zeev Suraski wrote:
> I'm personally against Union types because it makes no sense for classes, and for scalars we're better off with dedicated solution a (e.g. "numeric");
Same reason I voted no.

Bob Weinand

10 years ago
> Am 14.06.2016 um 17:22 schrieb Derick Rethans <derick@php.net>: > > On Tue, 14 Jun 2016, Bob Weinand wrote: > >> It has been long enough under discussion... I've put union types into >> vote. >> >> Please find the RFC located at: >> https://wiki.php.net/rfc/union_types <https://wiki.php.net/rfc/union_types> > > Not clear on some of the wording. When you say: > > "This RFC proposes a vote on whether ?Foo shall be replaced by Foo | > null in general." > > Do you mean that ?Foo will no longer be allowed at all if this RFCs > passes? > > cheers, > Derick >
Correct. I think there should be only one way to do that; others may disagree, hence it is a separate vote. Bob