[RFC] [PRE-VOTE] Union types

php.internals

Bob Weinand

10 years ago
Hey all, I know, it has been quite some time … but it's still well in time for 7.1. Time to move on and put Union types to vote soon. [In the next 1-2 days] We have done some changes to the RFC to emphasize the appeal of union types as well as clarified what exactly we will vote on. If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types Thanks, Bob

Andrew Faulds

10 years ago
Hi Bob, Bob Weinand wrote:
> Hey all, > > I know, it has been quite some time … but it's still well in time for 7.1. > > Time to move on and put Union types to vote soon. [In the next 1-2 days] > > We have done some changes to the RFC to emphasize the appeal of union types as well as clarified what exactly we will vote on. > > If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types
I do wonder if 1-2 days is really sufficient time, given that before now, the only announced RFC had been substantially less complete. That aside, the behaviour the RFC now specifies for how weak typing interacts with union types is frighteningly complicated. I don't see how it could be anything other than that, but the new complexity this introduces to PHP is enough for me to vote against this RFC, even ignoring my other concerns. Thanks.
-- Andrea Faulds https://ajf.me/

Rowan Collins

10 years ago
On 02/06/2016 18:11, Andrea Faulds wrote:
> That aside, the behaviour the RFC now specifies for how weak typing > interacts with union types is frighteningly complicated. I don't see how > it could be anything other than that, but the new complexity this > introduces to PHP is enough for me to vote against this RFC, even > ignoring my other concerns.
That is rather a long-winded set of rules, I agree. I wonder if it's possible for the order the union type is defined to be taken into account? That way you could specify the rule thus: * The type is tested against each type in the union in turn. * If weak typing is active, scalar types will be coerced where this would normally be allowed, and passed over where a TypeError would be thrown. * If strict typing is active, scalar types will be treated the same as non-scalar types, and must match precisely. So: function f(int | float $number) { echo gettype($number); } f('10'); // int function g(float | int $number) { echo gettype($number); } g('10'); // float function h(int | Foo | string) { echo gettype($number); } h('10'); // int h(new Foo); // object h('hello'); // string function i(string | int) { echo gettype($number); } i('10'); // string i(10); // string This last example is the only one that might be a bit surprising - the "| int" in the type def is actually doing nothing - but there's always scope for user error. In strict mode, things would be a bit different, because no coercion is allowed: declare(strict_types=1); function f(int | float $number) { echo gettype($number); } f('10'); // [!] TypeError function g(float | int $number) { echo gettype($number); } g('10'); // [!] TypeError function h(int | Foo | string) { echo gettype($number); } h('10'); // string h(new Foo); // object h('hello'); // string function i(string | int) { echo gettype($number); } i('10'); // string i(10); // int It may be that the implementation makes this prohibitively difficult, but it would certainly be easier to document than the rules currently proposed. Regards,
-- Rowan Collins [IMSoP]

Bob Weinand

10 years ago
> Am 02.06.2016 um 19:33 schrieb Rowan Collins <rowan.collins@gmail.com>: > > On 02/06/2016 18:11, Andrea Faulds wrote: >> That aside, the behaviour the RFC now specifies for how weak typing >> interacts with union types is frighteningly complicated. I don't see how >> it could be anything other than that, but the new complexity this >> introduces to PHP is enough for me to vote against this RFC, even >> ignoring my other concerns. > > That is rather a long-winded set of rules, I agree. I wonder if it's possible for the order the union type is defined to be taken into account? That way you could specify the rule thus: > > * The type is tested against each type in the union in turn. > * If weak typing is active, scalar types will be coerced where this would normally be allowed, and passed over where a TypeError would be thrown. > * If strict typing is active, scalar types will be treated the same as non-scalar types, and must match precisely. > > > So: > > function f(int | float $number) { echo gettype($number); } > f('10'); // int > > function g(float | int $number) { echo gettype($number); } > g('10'); // float > > function h(int | Foo | string) { echo gettype($number); } > h('10'); // int > h(new Foo); // object > h('hello'); // string > > function i(string | int) { echo gettype($number); } > i('10'); // string > i(10); // string > > This last example is the only one that might be a bit surprising - the "| int" in the type def is actually doing nothing - but there's always scope for user error. > > > In strict mode, things would be a bit different, because no coercion is allowed: > > declare(strict_types=1); > > function f(int | float $number) { echo gettype($number); } > f('10'); // [!] TypeError > > function g(float | int $number) { echo gettype($number); } > g('10'); // [!] TypeError > > function h(int | Foo | string) { echo gettype($number); } > h('10'); // string > h(new Foo); // object > h('hello'); // string > > function i(string | int) { echo gettype($number); } > i('10'); // string > i(10); // int > > > It may be that the implementation makes this prohibitively difficult, but it would certainly be easier to document than the rules currently proposed. > > Regards, > -- > Rowan Collins > [IMSoP]
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. 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. The current way is the only viable one, as far as we discovered. Bob

Rowan Collins

10 years ago
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]

Bob Weinand

10 years ago
> 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

Unnamed Person

10 years ago
why not try all types weakly from left to right in weak mode? Rule: if type check would give a fatal error for a type, try next type. E.g. function i(int | string $var) { echo gettype($var) . ' ' . $var; } i('10'); // int 10 i('10a'); // int 10 i('foo'); // string foo i(10.0); // int 10 i(10); // int 10 Regards Thomas Bob Weinand wrote on 02.06.2016 22:56:

Rowan Collins

10 years ago
On 03/06/2016 11:16, Thomas Bley wrote:
> why not try all types weakly from left to right in weak mode? > Rule: if type check would give a fatal error for a type, try next type.
This is what I suggested, but Bob is insistent that weak mode should always select the same type as strict mode where there is a valid strict match, which I guess makes sense. A strict left-to-right check violates that: function i(string | int $x) { echo gettype($x); } i(10); // string in weak mode, int in strict mode function j(int | string $x) { echo gettype($x); } j('10'); // int in weak mode, string in strict mode The main complication that I haven't quite got my head round yet is the fact that an int->float coercion is allowed in strict mode. So to be consistent, weak mode needs to privilege that cast: function k(string | float $x) { echo gettype($x); } k(10); // float But in other cases it doesn't seem sensible to privilege float over string: function l(string | float $x) { echo gettype($x); } l("1.5a"); // I would expect string, but float would succeed if attempted Regards,
-- Rowan Collins [IMSoP]

Bob Weinand

10 years ago
> Am 3.6.2016 um 12:28 schrieb Rowan Collins <rowan.collins@gmail.com>: > > On 03/06/2016 11:16, Thomas Bley wrote: >> why not try all types weakly from left to right in weak mode? >> Rule: if type check would give a fatal error for a type, try next type. > > This is what I suggested, but Bob is insistent that weak mode should always select the same type as strict mode where there is a valid strict match, which I guess makes sense. > > A strict left-to-right check violates that: > > function i(string | int $x) { echo gettype($x); } > i(10); // string in weak mode, int in strict mode > > function j(int | string $x) { echo gettype($x); } > j('10'); // int in weak mode, string in strict mode > > > The main complication that I haven't quite got my head round yet is the fact that an int->float coercion is allowed in strict mode. So to be consistent, weak mode needs to privilege that cast: > > function k(string | float $x) { echo gettype($x); } > k(10); // float > > But in other cases it doesn't seem sensible to privilege float over string: > > function l(string | float $x) { echo gettype($x); } > l("1.5a"); // I would expect string, but float would succeed if attempted
Exact matches *ALWAYS* match without coercion. Emphasis from the RFC: Primarily, this issue is *avoided if a parameter type exactly matches the input type* or if PHP is in strict type mode.
> Regards, > -- > Rowan Collins > [IMSoP]
Bob

Rowan Collins

10 years ago
On 03/06/2016 12:59, Bob Weinand wrote:
>> function l(string | float $x) { echo gettype($x); } >> l("1.5a"); // I would expect string, but float would succeed if attempted > > Exact matches *ALWAYS* match without coercion.
Gah, I keep making that mistake in my examples. I did say I was struggling to get my head around things! ;) I'm still missing an explanation of exactly where you derived the current proposed rules from, though. The RFC just states "these rules are not an invention of this proposal", but goes on to say "applies PHP casting rules in a sane way", which implies some decisions were involved in drawing up these rules. I think you may be right that the rules are as simple as they can be, and I don't want to waste too much of your time, but a basic summary of the reasoning used would be much appreciated. Regards,
-- Rowan Collins [IMSoP]

Bob Weinand

10 years ago
> Am 02.06.2016 um 19:11 schrieb Andrea Faulds <ajf@ajf.me>: > > Hi Bob, > > Bob Weinand wrote: >> Hey all, >> >> I know, it has been quite some time … but it's still well in time for 7.1. >> >> Time to move on and put Union types to vote soon. [In the next 1-2 days] >> >> We have done some changes to the RFC to emphasize the appeal of union types as well as clarified what exactly we will vote on. >> >> If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types > > I do wonder if 1-2 days is really sufficient time, given that before now, the only announced RFC had been substantially less complete. > > That aside, the behaviour the RFC now specifies for how weak typing interacts with union types is frighteningly complicated. I don't see how it could be anything other than that, but the new complexity this introduces to PHP is enough for me to vote against this RFC, even ignoring my other concerns. > > Thanks. > -- > Andrea Faulds > https://ajf.me/
Hey, I think this is more of a presentation problem. As you say, there's not much a better way to do that. It's basically our weak casting rules, just applied to the most lossless type available. It's out weak casting rules which are so complex; the RFCs combination is not particularly complex. It needs to cover everything, but it's particularly important for the trivial cases to be handled here. Would be quite WTF if you could not pass a float to something accepting int (as one of its types). I'd welcome every suggestion to make the rules look less scary, because they actually aren't. Bob

Fleshgrinder

10 years ago
On 6/2/2016 7:37 PM, Bob Weinand wrote:
> Hey, > > I think this is more of a presentation problem. > As you say, there's not much a better way to do that. > > It's basically our weak casting rules, just applied to the most lossless type available. > It's out weak casting rules which are so complex; the RFCs combination is not particularly complex. > It needs to cover everything, but it's particularly important for the trivial cases to be handled here. Would be quite WTF if you could not pass a float to something accepting int (as one of its types). > > I'd welcome every suggestion to make the rules look less scary, because they actually aren't. > > Bob >
Don't you think this matrix would be a better presentation and simpler? |--------|--------|--------|--------| | type | #1 | #2 | #3 | |--------|--------|--------|--------| | bool | string | int | | | int | string | float | bool | | float | string | int | bool | | object | string | | | | string | float | int | bool | |--------|--------|--------|--------| Everything else is a TypeError. Note that I try string first all the time. Simply because it makes no difference for PHP afterwards, e.g.: function f(string|int $a) { if ($a == 1) echo 'foo'; } f(true); // true ~> '1' ~> 1 = foo Even if the change I applied is not intelligent and is not a good idea (haven't thought about it deeply), the presentation as a table should help a lot.
-- Richard "Fleshgrinder" Fussenegger

Bob Weinand

10 years ago
> Am 02.06.2016 um 19:52 schrieb Fleshgrinder <php@fleshgrinder.com>: > > On 6/2/2016 7:37 PM, Bob Weinand wrote: >> Hey, >> >> I think this is more of a presentation problem. >> As you say, there's not much a better way to do that. >> >> It's basically our weak casting rules, just applied to the most lossless type available. >> It's out weak casting rules which are so complex; the RFCs combination is not particularly complex. >> It needs to cover everything, but it's particularly important for the trivial cases to be handled here. Would be quite WTF if you could not pass a float to something accepting int (as one of its types). >> >> I'd welcome every suggestion to make the rules look less scary, because they actually aren't. >> >> Bob >> > > Don't you think this matrix would be a better presentation and simpler? > > |--------|--------|--------|--------| > | type | #1 | #2 | #3 | > |--------|--------|--------|--------| > | bool | string | int | | > | int | string | float | bool | > | float | string | int | bool | > | object | string | | | > | string | float | int | bool | > |--------|--------|--------|--------| > > Everything else is a TypeError.
Done that, does it look better now? :-)
> Note that I try string first all the time. Simply because it makes no > difference for PHP afterwards, e.g.: > > function f(string|int $a) { > if ($a == 1) echo 'foo'; > } > > f(true); // true ~> '1' ~> 1 = foo > > Even if the change I applied is not intelligent and is not a good idea > (haven't thought about it deeply), the presentation as a table should > help a lot.
There is one reason, it must not be inconsistent with strict types. Switching from strict_types=1 to strict_types=0 shall always work without semantics changes (as long as you don't catch TypeErrors).
> -- > Richard "Fleshgrinder" Fussenegger
Thanks, Bob

Fleshgrinder

10 years ago
On 6/2/2016 8:45 PM, Bob Weinand wrote:
> Done that, does it look better now? :-) >
Absolutely in my opinion, looks much simpler now. :)
> only if actually numeric, the result of $str + 0
Shouldn't we use is_numeric_string() here?
-- Richard "Fleshgrinder" Fussenegger

Bob Weinand

10 years ago
> Am 02.06.2016 um 20:53 schrieb Fleshgrinder <php@fleshgrinder.com>: > > On 6/2/2016 8:45 PM, Bob Weinand wrote: >> Done that, does it look better now? :-) >> > > Absolutely in my opinion, looks much simpler now. :) > >> only if actually numeric, the result of $str + 0 > > Shouldn't we use is_numeric_string() here?
That's the internal function responsible for the conversion. Bob

Andrew Faulds

10 years ago
Hi, Bob Weinand wrote:
> I think this is more of a presentation problem. > As you say, there's not much a better way to do that.
Well, that's why I question if we should do it at all, if there's no way to do it without this complexity.
> It's basically our weak casting rules, just applied to the most lossless type available.
Right, I think I can see the logic to that. But I don't think it works out so well in practice. Consider the hypothetical example `int|string`. Under your rules, if I pass a float to that parameter, it becomes a string. That makes sense if the function just wants a number, in integer or string format, for that parameter. But what if the function wants either a number (in integer format) or a string, and does different things depending on which of these it gets? Now the proposed weak typing rules are broken. A real-world example of this is array indices. Given array keys can be either integers or strings, then if we wanted to take an array key as a parameter, surely we'd use the type declaration `int|string`, right? Well, it turns out that in PHP, $a[1.5] is not equivalent to $a["1.5"], it's equivalent to $a[1]. Yet, if I pass 1.5 to an `int|string` typed parameter, I'd get "1.5". So, we'd end up with an inconsistency: <?php function fetchValueForKeyInArray(array $array, int|string $key) { return $array[$key]; } $arr = ["1.5" => "wrong", 1 => "right"]; var_dump($arr[1.5]); // string(5) "right" var_dump(fetchValueForKeyInArray($arr, $key)); // string(5) "wrong" ?> Trying to do the most "lossless" conversion works for some use-cases, but it doesn't work for others, and it doesn't necessarily match existing behaviour in other parts of PHP. This is a wider concern for me, in that union types have two different use cases: where you want to accept any type of some ad-hoc super-type (int|float as an ad-hoc "number", array|\Traversable as an ad-hoc "thing that can be foreach()'d), but there is also the use case of where you want to accept two completely unrelated types (int|string for two kinds of array key, int|array, etc.) and perhaps do different things depending on the types given. This latter use case strikes me as making a function overly complicated (make a separate function instead), and it interacts poorly with weak typing (if PHP decides to give you a different type, you get a completely different code path!), yet the addition of union types encourages writing such functions! (At least, for people who want to use type declarations throughout their code.) Moreover, I think whatever weak typing precedence rules we choose, they can only work reasonably for one or the other of these use-cases, not both. I think that `int|string` is a succint example of that: whichever ruleset we choose, it will do the wrong thing for some usecase, we're just deciding which one to privilege.
> It's out weak casting rules which are so complex; the RFCs combination is not particularly complex.
The RFC uses simple rules, but the resulting behaviour is complex. PHP's weak typing rules are complicated enough as they are, and cause enough problem, without the addition of yet more rules, this time for how weak typing should work within union types. I don't think 2 days is enough time to discuss this before voting on it. Thanks.
-- Andrea Faulds https://ajf.me/

Fleshgrinder

10 years ago
On 6/3/2016 5:13 PM, Andrea Faulds wrote:
> The RFC uses simple rules, but the resulting behaviour is complex. > > PHP's weak typing rules are complicated enough as they are, and cause > enough problem, without the addition of yet more rules, this time for > how weak typing should work within union types. > > I don't think 2 days is enough time to discuss this before voting on it. >
I actually agree with Andrea on this. There are too many side effects that are endlessly hard to cover; even if we put all our brain power together. I would actually propose to make them always strict. It should not be a problem for people to simply cast them to the right type. Maybe it even helps to prevent that people overuse union types (which I am a bit afraid of too but the feature is too useful). In the end, anyone who does not like it can always resort to using no type hint at all as they could in the past. I know that Bob already said that it is a no go but I do not quite agree here. That being said, there is another possible approach. Do nothing in weak mode. This might sound weird but the fact that the engine will coerce the variables anyways as needed would help. Any union type would be mixed again, like it always was up until now. A problem every PHP developer knows about and knows how to handle. In the end it is about relying on super type behavior. If I accept float|int|string than I should only perform actions on them that all of them support and I have to check the actual type anyways if I want to change my behavior based on the specific type. Hence, I can also error out if I do not receive the type I was expecting. As we are already doing. :)
-- Richard "Fleshgrinder" Fussenegger

Andrew Faulds

10 years ago
Hi again, In an attempt to be constructive, I have implemented an alternative approach to weak scalar type selection here: https://github.com/krakjoe/php-src/compare/multi-types...TazeTSchnitzel:multi-types-roulette Where there is no exact scalar type match, this patch uses an algorithm originally suggested by Nikita, wherein we use rand() to pick which type to cast to. This is much simpler than having a type precedence matrix, and thus is easier to remember and reason about. The choice of selection function means that no particular use-case is privileged. Given PHP's scalar types are roughly equivalent (after all, PHP juggles them freely), this apparently unorthodox selection process should nonetheless produce sensible results in most cases. Please tell me your thoughts!
-- Andrea Faulds https://ajf.me/

Bob Weinand

10 years ago
> Am 05.06.2016 um 00:55 schrieb Andrea Faulds <ajf@ajf.me>: > > Hi again, > > In an attempt to be constructive, I have implemented an alternative approach to weak scalar type selection here: > > https://github.com/krakjoe/php-src/compare/multi-types...TazeTSchnitzel:multi-types-roulette > > Where there is no exact scalar type match, this patch uses an algorithm originally suggested by Nikita, wherein we use rand() to pick which type to cast to. > > This is much simpler than having a type precedence matrix, and thus is easier to remember and reason about. The choice of selection function means that no particular use-case is privileged. Given PHP's scalar types are roughly equivalent (after all, PHP juggles them freely), this apparently unorthodox selection process should nonetheless produce sensible results in most cases. > > Please tell me your thoughts! > > -- > Andrea Faulds > https://ajf.me/ <https://ajf.me/>
This is the holy grail I was hunting for so long! All my computational problems can be solved by a simple rand()! In case nobody objects I'm going to merge that straight ahead into php-src 7.0 (no need for master-only, after all it's no real BC break!). Thanks a very much!!! Bob

Robert Stoll

10 years ago
Hi Andrea, Bob
> -----Ursprüngliche Nachricht----- > Von: Bob Weinand [mailto:bobwei9@hotmail.com] > Gesendet: Sonntag, 5. Juni 2016 01:00 > An: Andrea Faulds > Cc: internals@lists.php.net > Betreff: Re: [PHP-DEV] Re: [RFC] [PRE-VOTE] Union types > > > > Am 05.06.2016 um 00:55 schrieb Andrea Faulds <ajf@ajf.me>: > > > > Hi again, > > > > In an attempt to be constructive, I have implemented an alternative approach to weak scalar type selection here: > > > > https://github.com/krakjoe/php-src/compare/multi-types...TazeTSchnitzel:multi-types-roulette > > > > Where there is no exact scalar type match, this patch uses an algorithm originally suggested by Nikita, wherein we
use
> rand() to pick which type to cast to. > > > > This is much simpler than having a type precedence matrix, and thus is easier to remember and reason about. The
choice
> of selection function means that no particular use-case is privileged. Given PHP's scalar types are roughly equivalent
(after
> all, PHP juggles them freely), this apparently unorthodox selection process should nonetheless produce sensible
results in
> most cases. > > > > Please tell me your thoughts! > > > > -- > > Andrea Faulds > > https://ajf.me/ <https://ajf.me/> > This is the holy grail I was hunting for so long! > > All my computational problems can be solved by a simple rand()! > > In case nobody objects I'm going to merge that straight ahead into php-src 7.0 (no need for master-only, after all
it's no real
> BC break!). > > Thanks a very much!!! > > Bob
Not sure if this is a clever idea. I haven't read all emails so bear with me if this is more than clear. What happens with the following? function foo(int | string $a) { if ($a == "") { //a } else { //b } } foo(false); What branch is taken? Is it taken randomly?

Ryan Pallas

10 years ago
On Sun, Jun 5, 2016 at 6:09 AM, Robert Stoll <php@tutteli.ch> wrote:
> Hi Andrea, Bob > > > -----Ursprüngliche Nachricht----- > > Von: Bob Weinand [mailto:bobwei9@hotmail.com] > > Gesendet: Sonntag, 5. Juni 2016 01:00 > > An: Andrea Faulds > > Cc: internals@lists.php.net > > Betreff: Re: [PHP-DEV] Re: [RFC] [PRE-VOTE] Union types > > > > > > > Am 05.06.2016 um 00:55 schrieb Andrea Faulds <ajf@ajf.me>: > > > > > > Hi again, > > > > > > In an attempt to be constructive, I have implemented an alternative > approach to weak scalar type selection here: > > > > > > > https://github.com/krakjoe/php-src/compare/multi-types...TazeTSchnitzel:multi-types-roulette > > > > > > Where there is no exact scalar type match, this patch uses an > algorithm originally suggested by Nikita, wherein we > use > > rand() to pick which type to cast to. > > > > > > This is much simpler than having a type precedence matrix, and thus is > easier to remember and reason about. The > choice > > of selection function means that no particular use-case is privileged. > Given PHP's scalar types are roughly equivalent > (after > > all, PHP juggles them freely), this apparently unorthodox selection > process should nonetheless produce sensible > results in > > most cases. > > > > > > Please tell me your thoughts! > > > > > > -- > > > Andrea Faulds > > > https://ajf.me/ <https://ajf.me/> > > This is the holy grail I was hunting for so long! > > > > All my computational problems can be solved by a simple rand()! > > > > In case nobody objects I'm going to merge that straight ahead into > php-src 7.0 (no need for master-only, after all > it's no real > > BC break!). > > > > Thanks a very much!!! > > > > Bob > > Not sure if this is a clever idea. I haven't read all emails so bear with > me if this is more than clear. What happens > with the following? > > function foo(int | string $a) { > if ($a == "") { > //a > } else { > //b > } > } > > foo(false); > > What branch is taken? Is it taken randomly? >
In this case, A will always be taken, because of the loose comparison (==). Basically: var_dump("" == ""); // bool(true) var_dump(0 == ""); // bool(true) var_dump(false == ""); // bool(true)

Robert Stoll

10 years ago
> -----Ursprüngliche Nachricht----- > Von: Ryan Pallas [mailto:derokorian@gmail.com] > Gesendet: Sonntag, 5. Juni 2016 14:22 > An: Robert Stoll > Cc: Bob Weinand; Andrea Faulds; internals@lists.php.net > Betreff: Re: [PHP-DEV] Re: [RFC] [PRE-VOTE] Union types > > > > On Sun, Jun 5, 2016 at 6:09 AM, Robert Stoll <php@tutteli.ch> wrote: > > > Hi Andrea, Bob > > > -----Ursprüngliche Nachricht----- > > Von: Bob Weinand [mailto:bobwei9@hotmail.com] > > Gesendet: Sonntag, 5. Juni 2016 01:00 > > An: Andrea Faulds > > Cc: internals@lists.php.net > > Betreff: Re: [PHP-DEV] Re: [RFC] [PRE-VOTE] Union types > > > > > > > > Am 05.06.2016 um 00:55 schrieb Andrea Faulds <ajf@ajf.me>: > > > > > > Hi again, > > > > > > In an attempt to be constructive, I have implemented an alternative approach to weak scalar type selection > here: > > > > > > https://github.com/krakjoe/php-src/compare/multi-types...TazeTSchnitzel:multi-types-roulette > > > > > > Where there is no exact scalar type match, this patch uses an algorithm originally suggested by Nikita, wherein > we > use > > rand() to pick which type to cast to. > > > > > > This is much simpler than having a type precedence matrix, and thus is easier to remember and reason about. > The > choice > > of selection function means that no particular use-case is privileged. Given PHP's scalar types are roughly > equivalent > (after > > all, PHP juggles them freely), this apparently unorthodox selection process should nonetheless produce sensible > results in > > most cases. > > > > > > Please tell me your thoughts! > > > > > > -- > > > Andrea Faulds > > > https://ajf.me/ <https://ajf.me/> > > This is the holy grail I was hunting for so long! > > > > All my computational problems can be solved by a simple rand()! > > > > In case nobody objects I'm going to merge that straight ahead into php-src 7.0 (no need for master-only, after all > it's no real > > BC break!). > > > > Thanks a very much!!! > > > > Bob > > > Not sure if this is a clever idea. I haven't read all emails so bear with me if this is more than clear. What happens > with the following? > > function foo(int | string $a) { > if ($a == "") { > //a > } else { > //b > } > } > > foo(false); > > What branch is taken? Is it taken randomly? > > > > In this case, A will always be taken, because of the loose comparison (==). Basically: > > var_dump("" == ""); // bool(true) > var_dump(0 == ""); // bool(true) > var_dump(false == ""); // bool(true) >
My fault, so what about if ($a === "") { }

Stas Malyshev

10 years ago
Hi!
> Where there is no exact scalar type match, this patch uses an algorithm > originally suggested by Nikita, wherein we use rand() to pick which type > to cast to.
Random type conversion. For people that are bored with plaid old deterministic code bugs.
-- Stas Malyshev smalyshev@gmail.com

Sara Golemon

10 years ago
On Thu, Jun 2, 2016 at 4:00 AM, Bob Weinand <bobwei9@hotmail.com> wrote:
> I know, it has been quite some time … but it's still well in time for 7.1. > > Time to move on and put Union types to vote soon. [In the next 1-2 days] > > We have done some changes to the RFC to emphasize the appeal of union types as well as clarified what exactly we will vote on. > > If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types >
Would it be COMPLETELY antisocial at this point to ask for a secondary vote on this RFC for adding the "num" type which is an alias for (int | float) ? -Sara

Bob Weinand

10 years ago
> Am 03.06.2016 um 03:41 schrieb Sara Golemon <pollita@php.net>: > >> On Thu, Jun 2, 2016 at 4:00 AM, Bob Weinand <bobwei9@hotmail.com> wrote: >> I know, it has been quite some time … but it's still well in time for 7.1. >> >> Time to move on and put Union types to vote soon. [In the next 1-2 days] >> >> We have done some changes to the RFC to emphasize the appeal of union types as well as clarified what exactly we will vote on. >> >> If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types > Would it be COMPLETELY antisocial at this point to ask for a secondary > vote on this RFC for adding the "num" type which is an alias for (int > | float) ? > > -Sara
Not anti-social, but I won't add it... The main concern is that it is an extra BC break (num is not too rare for class/namespace names I'd argue). Additionally it warrants extra discussion. Num, Numeric? Which one? Also proper elaboration why we should add it or not would have to be done... I think this should be an own RFC thus. Bob

Stas Malyshev

10 years ago
Hi!
> Would it be COMPLETELY antisocial at this point to ask for a secondary > vote on this RFC for adding the "num" type which is an alias for (int > | float) ?
I think piling up votes that are not necessary for the specific RFC's topic is not right. We can always have another RFC :)
-- Stas Malyshev smalyshev@gmail.com

Theodore Brown

10 years ago
On Thu, 2 June 2016 Bob Weinand wrote: > Hey all, >  > I know, it has been quite some time … but it's still well in time for 7.1. >  > Time to move on and put Union types to vote soon. [In the next 1-2 days] >  > We have done some changes to the RFC to emphasize the appeal of > union types as well as clarified what exactly we will vote on. >  > If you have more feedback, it's welcome: https://wiki.php.net/rfc/union_types >  > Thanks, > Bob Thank you (and Levi) for this RFC! I can't vote, but I'd like to weigh in with my userland perspective. Just last week I was working with several functions that accept array|Traversable and array|string parameters. Union types would make it easier to document these functions, as well as eliminate the boilerplate code currently required to validate their parameters. I am also in favor of the proposal to replace ?QuestionMarkNullables with union|null. Having a single way to declare nullable types will keep the reflection API simpler, make things easier for static analysis tools, and prevent developers from having to wonder which syntax they should use for a given function. This would be a big win for language consistency, and this is probably our only chance to make the change without breaking BC. Theodore Brown

Fleshgrinder

10 years ago
On 6/3/2016 3:40 PM, Theodore Brown wrote:
> I am also in favor of the proposal to replace ?QuestionMarkNullables > with union|null. Having a single way to declare nullable types will > keep the reflection API simpler, make things easier for static > analysis tools, and prevent developers from having to wonder which > syntax they should use for a given function. This would be a big win > for language consistency, and this is probably our only chance to > make the change without breaking BC. >
I am actually only in favor of disallowing ?T1|T2 in favor of T1|T2|null but not ?T because it's shorter and I do not see a problem with that.
-- Richard "Fleshgrinder" Fussenegger