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".
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.
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".
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".
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
Regards,
--
Rowan Collins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php