[RFC] Unary null coalescing operator

php.internals

Andrew Faulds

9 years ago
Hi all, Here's a small RFC for a small feature, which I've wondered about for a while: https://wiki.php.net/rfc/unary_null_coalescing_operator What do you think of it? Thanks!
-- Andrea Faulds https://ajf.me/

Fleshgrinder

9 years ago
On 6/21/2017 7:05 PM, Andrea Faulds wrote:
> Hi all, > > Here's a small RFC for a small feature, which I've wondered about for a > while: https://wiki.php.net/rfc/unary_null_coalescing_operator > > What do you think of it? > > Thanks!
I would prefer [1] to be extended to any and everything that can be null, like Kotlin, Ceylon, and others have it. Otherwise one needs to change back and forth between one and two question marks depending on context. The null coalesce operator is more of a special form of the ternary operator, but this proposal is a different beast and closer to nullable types than to the ternary operator. Hence, using a single question mark comes more natural. [1] https://wiki.php.net/rfc/nullsafe_calls
-- Richard "Fleshgrinder" Fussenegger

Sara Golemon

9 years ago
On Wed, Jun 21, 2017 at 1:05 PM, Andrea Faulds <ajf@ajf.me> wrote:
> Here's a small RFC for a small feature, which I've wondered about for a > while: https://wiki.php.net/rfc/unary_null_coalescing_operator > > What do you think of it? >
I think that `if ($_GET['x']?? === 1)` looks and feels a lot like `if (@$_GET['x'] === 1)`... Yes, the latter has runtime performance issues and will still send notices to error handlers and logs. But perhaps if we're going to extend syntax, the syntax could be something along the lines of: if (@@$_GET['x'] === 1) The double @@ could indicate "No, really, don't send any kind of warning (or lower) anywhere. Just deal with it. And as a bonus, the @@ syntax is valid in older PHPs (acting like a single @). -Sara

Andrew Faulds

9 years ago
Hi Sara, Sara Golemon wrote:
> On Wed, Jun 21, 2017 at 1:05 PM, Andrea Faulds <ajf@ajf.me> wrote: >> Here's a small RFC for a small feature, which I've wondered about for a >> while: https://wiki.php.net/rfc/unary_null_coalescing_operator >> >> What do you think of it? >> > I think that `if ($_GET['x']?? === 1)` looks and feels a lot like `if > (@$_GET['x'] === 1)`... > > Yes, the latter has runtime performance issues and will still send > notices to error handlers and logs. But perhaps if we're going to > extend syntax, the syntax could be something along the lines of: > > if (@@$_GET['x'] === 1) > > The double @@ could indicate "No, really, don't send any kind of > warning (or lower) anywhere. Just deal with it. And as a bonus, the > @@ syntax is valid in older PHPs (acting like a single @).
I'm not entirely sure if you're trolling. But in case you aren't, the main problem with @ as I see it is it's a blunt-force instrument. It doesn't just ignore a specific error, it ignores all errors. If you do, say, `myFunction()[0]??`, only errors related to the existence of the 0 index are silenced. But in the case of `@myFunction()[0]`, any error the function produces is silenced, no matter how relevant it is. It's the expression equivalent of Pokémon exception handling (Gotta catch 'em all: try {/*…*/} catch (Error $e) {}). For that reason, I don't like the idea of extending @.
-- Andrea Faulds https://ajf.me/

Sara Golemon

9 years ago
On Wed, Jun 21, 2017 at 4:15 PM, Andrea Faulds <ajf@ajf.me> wrote:
>> The double @@ could indicate "No, really, don't send any kind of >> warning (or lower) anywhere. Just deal with it. And as a bonus, the >> @@ syntax is valid in older PHPs (acting like a single @). > > I'm not entirely sure if you're trolling. >
Sorry, my first draft of this email had it limited to variables. :p Of course, as you point out, even in the case of variables, we might want the subscript to be the result of something more dynamic, so that solution doesn't work so well... Nevermind then. -Sara

Stas Malyshev

9 years ago
Hi!
> I think that `if ($_GET['x']?? === 1)` looks and feels a lot like `if > (@$_GET['x'] === 1)`... > > Yes, the latter has runtime performance issues and will still send > notices to error handlers and logs. But perhaps if we're going to > extend syntax, the syntax could be something along the lines of:
I'd rather fix @ (or make another operator like @@ that Sara proposed) to make nullsafe access - and maybe even extend it to full expression like isset/empty does - so I could do something like @$foo['bar']->blah->foo['bah'] and have it mean "try to fetch the whole chain and if something is missing on the way return null". I kinda get the argument for PHP not doing it by default, though I personally could live with that too ;) - but I still need this thing quite frequently when dealing with all kinds of dirty data. With trailing ?? it is not clear how it would chain, and even if it chains having something at the end that changes how the expression is interpreted is both confusing and may be very hard for the parser.
-- Stas Malyshev smalyshev@gmail.com

Andrew Faulds

9 years ago
Hi Stas, Stanislav Malyshev wrote:
> Hi! > >> I think that `if ($_GET['x']?? === 1)` looks and feels a lot like `if >> (@$_GET['x'] === 1)`... >> >> Yes, the latter has runtime performance issues and will still send >> notices to error handlers and logs. But perhaps if we're going to >> extend syntax, the syntax could be something along the lines of: > > I'd rather fix @ (or make another operator like @@ that Sara proposed) > to make nullsafe access - and maybe even extend it to full expression > like isset/empty does - so I could do something like > @$foo['bar']->blah->foo['bah'] and have it mean "try to fetch the whole > chain and if something is missing on the way return null". I kinda get > the argument for PHP not doing it by default, though I personally could > live with that too ;) - but I still need this thing quite frequently > when dealing with all kinds of dirty data.
You already can use @. I'm not sure how it could be "fixed": the fundamental problem with @ is that it is a blunt-force instrument that mutes all errors, but this is also its purpose, and any change to that will break some use cases. The best fix would be to get rid of it entirely, but we can't do that since it actually has to be used in some cases right now, in particular standard library functions that produce E_WARNINGs on I/O errors.
> With trailing ?? it is not clear how it would chain,
It's a unary operator, I don't know what “chain” would mean for one. You can use it within other expressions (1 + $a?? is valid, for example), and you can nest it within itself ($a???? is also valid, though I've no idea why you'd do that).
> and even if it > chains having something at the end that changes how the expression is > interpreted is both confusing and may be very hard for the parser.
Unary ?? is a two-line addition to the syntax and completely unambiguous from a parsing perspective. Thanks.
-- Andrea Faulds https://ajf.me/

Nikita Popov

9 years ago
On Thu, Jun 22, 2017 at 10:52 PM, Andrea Faulds <ajf@ajf.me> wrote:
> Hi Stas, > > Stanislav Malyshev wrote: > >> Hi! >> >> I think that `if ($_GET['x']?? === 1)` looks and feels a lot like `if >>> (@$_GET['x'] === 1)`... >>> >>> Yes, the latter has runtime performance issues and will still send >>> notices to error handlers and logs. But perhaps if we're going to >>> extend syntax, the syntax could be something along the lines of: >>> >> >> I'd rather fix @ (or make another operator like @@ that Sara proposed) >> to make nullsafe access - and maybe even extend it to full expression >> like isset/empty does - so I could do something like >> @$foo['bar']->blah->foo['bah'] and have it mean "try to fetch the whole >> chain and if something is missing on the way return null". I kinda get >> the argument for PHP not doing it by default, though I personally could >> live with that too ;) - but I still need this thing quite frequently >> when dealing with all kinds of dirty data. >> > > You already can use @. I'm not sure how it could be "fixed": the > fundamental problem with @ is that it is a blunt-force instrument that > mutes all errors, but this is also its purpose, and any change to that will > break some use cases. The best fix would be to get rid of it entirely, but > we can't do that since it actually has to be used in some cases right now, > in particular standard library functions that produce E_WARNINGs on I/O > errors. > > With trailing ?? it is not clear how it would chain, >> > > It's a unary operator, I don't know what “chain” would mean for one. You > can use it within other expressions (1 + $a?? is valid, for example), and > you can nest it within itself ($a???? is also valid, though I've no idea > why you'd do that). > > and even if it >> chains having something at the end that changes how the expression is >> interpreted is both confusing and may be very hard for the parser. >> > > Unary ?? is a two-line addition to the syntax and completely unambiguous > from a parsing perspective. >
As has been pointed out on reddit, unary ?? is ambiguous for cases like $a?? - 1, which could be either ($a??) - 1 or $a ?? (-1). Of course, precedence resolution is possible, but I wouldn't call the syntax unambiguous. Nikita