> 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