On Wed, Nov 5, 2025, at 4:48 PM, Rowan Tommins [IMSoP] wrote:
> On 05/11/2025 08:38, Alexandre Daubois wrote:
>> What we propose is to align these new operators to already existing
>> rules applied to function arguments. This is, indeed, stricter than
>> current cast operators. But I wouldn't say it has*nothing to do* with
>> the title of the RFC.
>> Maybe it's not perfectly accurate. If the naming is a problem and
>> should be changed, I'd be happy to hear suggestions and update
>> accordingly with a better name.
>
> Let's imagine how someone would describe these two expressions if this 
> RFC passed:
>
> (int)$foo
> (!int)$foo
>
> Here are the differences I see:
>
> 1) The first casts any non-numeric input to zero; the second throws 
> TypeError.
> 2) Certain values, such as "123foo" are considered numeric by one, but 
> not by the other.
>
> That's it. There's no need to mention null specifically, it's just one 
> of many non-numeric values.
>
> In fact, people might forget to mention point 2, because the difference 
> between "always returns an integer" and "may cause your entire program 
> to exit if fed unvalidated input" is far more important.
>
> So, if you want a name, I suggest something to do with "throw" or "error".
>
>
> But the problem I see with the RFC is deeper than that: there's no 
> actual discussion of *why* throwing a TypeError is better, or *when* 
> this completely new form of cast would be used.
>
> As I've tried to argue in previous messages, exception-handling is *not* 
> convenient for tasks like handling user input. It is maybe useful for 
> deeper code, where you expect the value to already be validated. So I 
> think we should be looking at more than one type of new cast; or at 
> least a choice of syntax that anticipates that.
>
>
> As for the other part of the RFC, looking at these two expressions:
>
> (int)$foo
> (?int)$foo
>
> I would expect the *only* differences to be to do with null input, and 
> maybe null output.
>
> But in the proposal, using the new operator will *crash my application* 
> for values where the other returned zero, and even for values where the 
> other returned non-zero integers.
>
> If that part of the proposal goes to a vote as currently written, I will 
> vote No.
>
>
> -- 
> Rowan Tommins
> [IMSoP]


I very much appreciate the goal here, but at the same time I share Rowan and 
other's concerns that it's too one-off and non-obvious.

The general case here is "I have a variable of type X, and I want to losslessly 
convert it t type Y if that's possible, and do this other thing if not."  Where 
"the other thing" could be "return null", "Warning", "Exception", "default 
value", etc.  

This is in contrast to the current casting logic, which allows a lossy 
conversion with no communication that a loss has happened.

Lossy and lossless conversion are sufficiently different that the syntax should 
not be so similar.  

My first thought is some kind of language construct pseudo-function, like:

cast($var, int); // Weak mode rules conversion to int, or error
cast($var, ?int); // Weak mode rules conversion to int, allowing null, or error
cast($var, int|string|null); // Weak mode rules conversion to int if possible, 
string if not, allow null, or error

(This may or may not be ideal.)

But at this point, it feels an awful lot like filter_var() 
(https://www.php.net/filter_var).

And of course there's the question of how to signal an incompatibility.  
Returning null defeats the purpose of allowing null, an exception is too heavy 
and inappropriate, and... we have nothing else.

I feel compelled to mention my error handling proposal from earlier this year: 
https://externals.io/message/127188

I'm in favor of better type conversion tools that follow the same weak-rules as 
functions.  But I agree that just sticking a ? in the existing syntax and 
calling it a day is not the right approach, even if it feels easy at first 
blush.

--Larry Garfield

Reply via email to