Hello internals!
I'm wondering if there are any plans for union type casts support.
That's basically what I mean:
function checkItOut(int|float|string $bar)
{
$foo = (int|float)$bar;
var_dump($foo);
}
I assume the behavior should be the same as if we called the function
having respective parameter type-hint (with a remark that strict types are
disabled):
function checkItOut(int|float|string $bar)
{
$foo = cast($bar);
var_dump($foo);
}
function cast(int|float $bar): int|float
{
return $bar;
}
Best regards,
Yevhen
$foo = (int|float)$bar;
As written, I wouldn't know what to expect this to do with a string value -- would it cast it to int or float?
Based on the behavior of your second example, the answer appears to be "float", so this syntax seems to be equivalent to:
$foo = \is_int($bar) ? $bar : (float) $bar;
Or, even more concisely:
$foo = 0+$bar;
I'd be even less sure what to expect when casting to other union types. What would the expected result of casting a string to (bool|array|object) be, for example? I'm not sure there are many meaningful operations which could be constructed here.
As I mentioned before, it would work the same alike way as if we called
function with such type-hint.
FMPOV, one of the most meaningful use-cases would be nullable casts (like
casting ?string
into ?float
for example).
Regards, Yevhen
$foo = (int|float)$bar;
As written, I wouldn't know what to expect this to do with a string value
-- would it cast it to int or float?Based on the behavior of your second example, the answer appears to be
"float", so this syntax seems to be equivalent to:$foo = \is_int($bar) ? $bar : (float) $bar;
Or, even more concisely:
$foo = 0+$bar;
I'd be even less sure what to expect when casting to other union types.
What would the expected result of casting a string to (bool|array|object)
be, for example? I'm not sure there are many meaningful operations which
could be constructed here.
$foo = (int|float)$bar;
As written, I wouldn't know what to expect this to do with a string value -- would it cast it to int or float?
Based on the behavior of your second example, the answer appears to be "float", so this syntax seems to be equivalent to:
$foo = \is_int($bar) ? $bar : (float) $bar;
Or, even more concisely:
$foo = 0+$bar;
I'd be even less sure what to expect when casting to other union types. What would the expected result of casting a string to (bool|array|object) be, for example? I'm not sure there are many meaningful operations which could be constructed here.
To unsubscribe, visit: https://www.php.net/unsub.php
Hi,
I think the intention is that it would follow precisely the same casting rules as function parameters do.
So e.g:
function foo(int|float $var) {
return $var;
}
$f1 = foo(‘1’);
$c1 = (int|float) ‘1’;
$f2 = foo(‘1.1’);
$c2 = (int|float) ‘1.1’;
In both scenarios the $f1/$c1 and $f2/$c2 would result in the same type.
Your first example isn’t quite the same though; Passing ‘1’ to a parameter typed as int|float
will cast it to an integer, your example casts such a value to a float.
The 0+$value
thing is interesting, but also definitely seems less intuitive to my eye.
Given your last comment I think its worth reiterating Eugene’s point is simply about exposing the existing cast behaviour that happens with typed parameters, to be usable on variables.
I can see some benefit in the proposal, but I think I’d be more interested in the ability to define local variables as being a given type (or union), and then have the engine cast (or error) when assigning to them - essentially how typed object properties work, but for regular variables.
Le 5 oct. 2022 à 06:46, Eugene Sidelnyk zsidelnik@gmail.com a écrit :
I assume the behavior should be the same as if we called the function
having respective parameter type-hint (with a remark that strict types are
disabled):
Hi,
Function parameters are more restrictive than explicit cast in what it accepts. In particular, the following inputs are rejected with a TypeError when fed to a function that accepts an int
: "3 mices"
, null
, [ ]
. Most notably, no type conversion is performed when the input type is null
or array
, or when the target type is array
or object
.
For reference, the original conversion rules are here: https://wiki.php.net/rfc/union_types_v2#coercive_typing_mode https://wiki.php.net/rfc/union_types_v2#coercive_typing_mode (I don’t know if there has been adjustments since then.)
—Claude
There is a difference is declaring a function parameter of different
types ... because before hand, when the code calls the function, we
might not be sure about what kind if data the function will receive,
so the function could expect different types, and work the parameter
correctly internally..... nice
but ... when casting, on purpose, what use case can apply to it?
Are you facing a situation where manual union type cast is needed? can
you share it with us?
thanks
I used to have an awkward feeling when it was necessary to convert the
nullable integer into a nullable string. It would be kind of ternary
operator anyway. Either $b = (null !== $a) ? (string)$a : null;
or $b = (string)$a ?: null;
.
A lot easier to read would it be if written this way: $b = (?string)$a;
.
The intentions are clear when doing explicit type-cast.
Currently, I don't see any other situations when this feature may be useful
Thank you
On Wed, Oct 5, 2022, 4:43 PM juan carlos morales dev.juan.morales@gmail.com
wrote:
There is a difference is declaring a function parameter of different
types ... because before hand, when the code calls the function, we
might not be sure about what kind if data the function will receive,
so the function could expect different types, and work the parameter
correctly internally..... nicebut ... when casting, on purpose, what use case can apply to it?
Are you facing a situation where manual union type cast is needed? can
you share it with us?thanks
I used to have an awkward feeling when it was necessary to convert the
nullable integer into a nullable string. It would be kind of ternary
operator anyway. Either$b = (null !== $a) ? (string)$a : null;
or$b = (string)$a ?: null;
.A lot easier to read would it be if written this way:
$b = (?string)$a;
.
The intentions are clear when doing explicit type-cast.Currently, I don't see any other situations when this feature may be useful
I don't think that this tiny edge case warrants a new language feature.
I can endorse using azjezz/psl
for this though:
use Psl\Type;
$myValue = Type\union(Type\int(), Type\null())
->coerce($input);
This will also throw an exception (GOOD) if the cast is not safe to
perform.
Marco Pivetta
Le 5 oct. 2022 à 19:53, Eugene Sidelnyk zsidelnik@gmail.com a écrit :
I used to have an awkward feeling when it was necessary to convert the nullable integer into a nullable string. It would be kind of ternary operator anyway. Either
$b = (null !== $a) ? (string)$a : null;
or$b = (string)$a ?: null;
.A lot easier to read would it be if written this way:
$b = (?string)$a;
. The intentions are clear when doing explicit type-cast.Currently, I don't see any other situations when this feature may be useful
Thank you
There has been some discussion and interest around nullable casting (which, contrarily to union type casting, has only one possible and obvious semantics), see https://wiki.php.net/rfc/nullable-casting https://wiki.php.net/rfc/nullable-casting and the two discussion threads linked in the bottom of the page. However, the RFC seems to be inactive for now,
—Claude
Are you facing a situation where manual union type cast is needed?
I can't think of any examples for full union types off the top of my head, but nullable casts would frequently be useful, e.g. when you have a value that is either a numeric string or null, and you want an integer, but for null to stay null, not become zero.
There's also a slightly different case, where you want values which aren't numeric to also become null. As I commented on another thread, this is a space I've been thinking about recently, and it gets complicated quickly.
Regards,
--
Rowan Tommins
[IMSoP]