Re: Re: [RFC] [PRE-VOTE] Union types

From: Date: Thu, 02 Jun 2016 20:56:28 +0000
Subject: Re: Re: [RFC] [PRE-VOTE] Union types
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to internals+get-93733@lists.php.net to get a copy of this message
> Am 02.06.2016 um 22:25 schrieb Rowan Collins <rowan.collins@gmail.com>: > > On 02/06/2016 18:43, Bob Weinand wrote: >> We had that exact idea relatively early, but it exposes other problems… order suddenly >> matters. You cannot just add "a" type and get the expected results. >> >> E.g. >> function f(true | string $foo) { ... } >> >> everything except 0, ±0, "0" and "" would now return true. That's >> totally WTF. Sure, it's more friendly for people who want to read*rules*. But it is very bad >> for intuitivity. > > I'm not so sure about that - the RFC already mentions the mnemonic that "|" > means "or", and anyone reading PHP code should be familiar with short-cutting boolean > operators, so this feels kind of natural to me: "$foo must be true OR a string". Thus > "I would prefer it to be true, but if not, will accept a string". This is a bitwise or (as in constant flags), where all modes are allowed. It's not a boolean or, whose mnemonic is "||" (not "|"). >> Also: >> >>> >function i(string | int) { echo gettype($number); } >>> >i('10'); // string >>> >i(10); // string >> This. This is especially bad as it has different behaviors in strict and weak mode then. >> That's a no-go. > > Again, the logic is "I would prefer a string if you can, but an int if not"; if weak > mode tries its best to match that specification, it will always land on a string coercion. And again, in strict mode, this would result in an integer - but not in weak mode. (because strict types mandates no cast). This is a no-go, no matter what. > It's more of a problem the other way around, though, because I'd forgotten that weak > mode is allowed to perform lossy casts: > > function f ( int | string $number ) { echo $number; } > f('1a'); > > In weak mode, this would echo "1", because the int cast succeeds, lossily. > That's a little odd, I admit. > > > The rules are much clearer in table form, by the way, thumbs up for that. :) Although it would > be nice to point to some documentation of where these rules were lifted from, given the claim that > "they are not the invention of this proposal". E.g. object->string is possible right now and is preserved (but object->int etc. aren't). Or a non-numeric string cannot be passed to neither int nor float; thus not possible to pass them to int|float. > Looking at them, I see there is one extra rule which doesn't seem to be consistent with > normal weak typing, but is trying very hard to be lossless, and that's "float -> int > (if lossless)" as a separate priority from "float -> int". I'm not strictly opposed here. If more people agree here I may change that. > Current loose typing performs no such check: > > function f(int $x) { echo gettype($x), ':', $x; } > f(4.5); // integer:4 > > But the proposal is that this will prefer a string a cast: > > function f(int | string $x) { echo gettype($x), ':', $x; } > f(4.5); // string:4.5 > > If you get rid of this extra rule, the order of checks actually becomes a simple priority > order, regardless of source type: [exact match], int, float, string, boolean. > > > If the aim is to be lossless, then perhaps the order could be tweaked to make lossy casts > always lower priority: string, float, int, boolean? That's technically lossy when passing > int(9007199254740993) to "float | int" because it's above the safe threshold of 2^53, > but the current implementation is already lossy when passing it to "float | string": > > function f(float | string $x) { var_export($x); } > f(9007199254740993); // 9007199254740992.0 Yes, but this same behavior we have with strict types and we shall adhere to that. Bob > > Regards, > > -- > Rowan Collins > [IMSoP]

« previous php.internals (#93733) next »