[RFC] anti-coalescing-operator

  107661
October 24, 2019 17:21 dohpaz@gmail.com (Ken Stanley)
Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing
more succinct code for how to handle null values has been a blessing. But,
what about the inverse when you want to do something when a value is not
null? You're left with the traditional (and sometimes verbose) methods of
using if conditions or the full-blown ternary operator `$foo !== null ?
 : null;`.

I am here to gauge the interest of the community in having an
anti-coalescing operator that would execute code only if the condition is
not null, otherwise returning null in its stead. If this is not a wholly
terrible idea, I will -- as suggested -- then continue to create an
official RFC.

My initial thought process would be to use a similar syntax to the Null
Coalescing Operator (??), but to add negation: `$bar = $foo !??
$foo->getBar()`. I didn't want to use `!?` because then if anybody wanted
to add an anti-ternary operator (e.g., `!?:`) for falsey comparison, then
they'd have to get creative or use the three-character approach I am
already proposing. The purpose is simply to negate the existing behavior,
so at first glance I do not see any BC breakages or additional complexities
that haven't already been addressed - naturally, I could be wrong.

The driving use case, as hinted at in my above example, is if I have a
nullable object I only want to call a method on it if the object is not
null. Otherwise, default to the null value.

I am working through the RFC Howto [https://wiki.php.net/rfc/howto], and it
suggests that I ask for wiki karma for my account (897syudjhf) so that I
may create the RFC when appropriate.

Additionally, I have not [yet] found any existing precedence for
anti-coalescing; i.e., there does not seem to be an elegant counterpart to
COALESCE() in SQL. And, as they say, naming is hard. If
`anti-coalescing-operator` does not sit well with you all, I am open to
naming suggestions.

Thank you for your time,
Ken Stanley
  107662
October 24, 2019 17:33 Danack@basereality.com (Dan Ackroyd)
On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote:
> > Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing > more succinct code for how to handle null values has been a blessing. But, > what about the inverse when you want to do something when a value is not > null?
Hi Ken, It may help to give a real world example, rather than a metasyntactic one, as I can't immediately see how this would be useful. People have been expressing a concern over 'symbol soup' for similar ideas. The null colalesce scenario happens frequently enough, that it seemed to overcome the hurdle needed for acceptance. Again, giving a real world example of what you currently need to do frequently might help other people understand the need. cheers Dan
  107663
October 24, 2019 17:46 php-lists@koalephant.com (Stephen Reay)
> On 25 Oct 2019, at 00:33, Dan Ackroyd <Danack@basereality.com> wrote: > >> On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: >> >> Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing >> more succinct code for how to handle null values has been a blessing. But, >> what about the inverse when you want to do something when a value is not >> null? > > Hi Ken, > > It may help to give a real world example, rather than a metasyntactic > one, as I can't immediately see how this would be useful. > > People have been expressing a concern over 'symbol soup' for similar > ideas. The null colalesce scenario happens frequently enough, that it > seemed to overcome the hurdle needed for acceptance. Again, giving a > real world example of what you currently need to do frequently might > help other people understand the need. > > cheers > Dan > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
Hi Ken, This sounds like an alternative approach (for solving the same basic problem) to the nullsafe operator discussed a while back, no? https://wiki.php.net/rfc/nullsafe_calls Cheers Stephen
  107664
October 24, 2019 17:56 dohpaz@gmail.com (Ken Stanley)
On Thu, Oct 24, 2019 at 1:46 PM Stephen Reay <php-lists@koalephant.com>
wrote:

> Hi Ken, > > This sounds like an alternative approach (for solving the same basic > problem) to the nullsafe operator discussed a while back, no? > https://wiki.php.net/rfc/nullsafe_calls > > > Cheers > Stephen >
Hi Stephen! Yes, it would be similar if the object you're testing against is the same object you want to call (e.g., $foo !?? $foo->getBar()). But, if the variable is not an object, or it's just a test for another object, then the nullsafe operator does not seem to address this situation (e.g., $userId !?? $bar->getUser($userId())). In fact, I could see this RFC complimenting the nullsafe operator: $userId !?? $bar->getUser($userId)?->getName(). Thank you, Ken Stanley PS. Dan, I am going to respond to your request for a code example; I am taking my time so that I can give you and everyone else a good example. :)
  107681
October 24, 2019 23:28 pollita@php.net (Sara Golemon)
On Thu, Oct 24, 2019 at 12:46 PM Stephen Reay <php-lists@koalephant.com>
wrote:

> This sounds like an alternative approach (for solving the same basic > problem) to the nullsafe operator discussed a while back, no?
https://wiki.php.net/rfc/nullsafe_calls
> > At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks ago (Javascript is making this one popular), and I threw together a rough
PoC at https://github.com/php/php-src/compare/master...sgolemon:null-coalesce which I suspect he intends to RFC properly soon. As long as the topic is at hand, what's the general appetite for it? Should I bother polishing the turd? -Sara
  107683
October 25, 2019 00:03 andreas@dqxtech.net (Andreas Hennings)
On Fri, 25 Oct 2019 at 01:28, Sara Golemon <pollita@php.net> wrote:
> > On Thu, Oct 24, 2019 at 12:46 PM Stephen Reay <php-lists@koalephant.com> > wrote: > > > This sounds like an alternative approach (for solving the same basic > > problem) to the nullsafe operator discussed a while back, no? > > https://wiki.php.net/rfc/nullsafe_calls > > > > At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks > ago (Javascript is making this one popular), and I threw together a rough > PoC at > https://github.com/php/php-src/compare/master...sgolemon:null-coalesce which > I suspect he intends to RFC properly soon. As long as the topic is at > hand, what's the general appetite for it? Should I bother polishing the > turd? > > -Sara
?-> is a great idea. The problem is this only works for method chaining, not for function argument nesting. So we might want something else in addition to that. foo(bar(baz() ???) ???); -- Andreas
  107685
October 25, 2019 00:43 mike@newclarity.net (Mike Schinkel)
> On Oct 24, 2019, at 8:03 PM, Andreas Hennings <andreas@dqxtech.net> wrote: > > On Fri, 25 Oct 2019 at 01:28, Sara Golemon <pollita@php.net> wrote: >> >> https://wiki.php.net/rfc/nullsafe_calls > > ?-> is a great idea.
Totally agree, that would be nice.
> The problem is this only works for method chaining, not for function > argument nesting. > So we might want something else in addition to that. > > foo(bar(baz() ???) ???);
I am confused about this. Why would this be needed? In case the functions baz(), bar() or foo() do not exist? Please help me see what I am missing. -Mike
  107731
October 30, 2019 11:34 phpmailinglists@gmail.com (Peter Bowyer)
On Fri, 25 Oct 2019 at 00:28, Sara Golemon <pollita@php.net> wrote:

> At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks > ago (Javascript is making this one popular), and I threw together a rough > PoC at > https://github.com/php/php-src/compare/master...sgolemon:null-coalesce > which > I suspect he intends to RFC properly soon. As long as the topic is at > hand, what's the general appetite for it? Should I bother polishing the > turd? >
It would be the best Christmas present ever. Well. Almost. Peter
  107733
October 30, 2019 13:50 dohpaz@gmail.com (Ken Stanley)
On Wed, Oct 30, 2019 at 7:35 AM Peter Bowyer <phpmailinglists@gmail.com>
wrote:

> On Fri, 25 Oct 2019 at 00:28, Sara Golemon <pollita@php.net> wrote: > >> At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks >> ago (Javascript is making this one popular), and I threw together a rough >> PoC at >> https://github.com/php/php-src/compare/master...sgolemon:null-coalesce >> which >> I suspect he intends to RFC properly soon. As long as the topic is at >> hand, what's the general appetite for it? Should I bother polishing the >> turd? >> > > It would be the best Christmas present ever. > > Well. Almost. > > Peter >
Folks, I haven't forgotten about this; in fact, I've been thinking about it all weekend, and I cannot come up with a good use-case that hasn't already been shown to have either a viable current work-around, or an RFC (with code already written) that would give me what I was looking to do with my !?? operator syntax. So, with that said, I see no reason to further the discussion on a not-null coalescing operator. I do want to thank everybody for their kind and thoughtful feedback. You really made me think about this, and I enjoyed it. I will continue to look for something I can cut my teeth on as a first-time contribution to php core. - Ken Stanley
  107665
October 24, 2019 18:59 dohpaz@gmail.com (Ken Stanley)
On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <Danack@basereality.com> wrote:

> On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: > > > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing > > more succinct code for how to handle null values has been a blessing. > But, > > what about the inverse when you want to do something when a value is not > > null? > > Hi Ken, > > It may help to give a real world example, rather than a metasyntactic > one, as I can't immediately see how this would be useful. > > People have been expressing a concern over 'symbol soup' for similar > ideas. The null colalesce scenario happens frequently enough, that it > seemed to overcome the hurdle needed for acceptance. Again, giving a > real world example of what you currently need to do frequently might > help other people understand the need. > > cheers > Dan >
Hi Dan, After some thought, and searching through my existing code bases, I believe I've come up with a decent code example to help demonstrate the usefulness of the proposed anti-coalescing-operator: Without !??: getUser($userId); if (isset($_SERVER['fname']) { $user->setName($_SERVER['fname']); } if (isset($_SERVER['lname']) { $user->setName($_SERVER['lname']); } if (isset($_SERVER['mname']) { $user->setName($_SERVER['mname']); } if (isset($_SERVER['phone']) { $user->setName($_SERVER['phone']); } if (isset($_SERVER['email']) { $user->setName($_SERVER['email']); } $this-saveUser($user); } } With !??: getUser($userId); $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); $_SERVER['email'] !?? $user->setName($_SERVER['email']); $this-saveUser($user); } } Thank you, Ken Stanley
  107668
October 24, 2019 20:24 rowan.collins@gmail.com (Rowan Tommins)
Hi Ken,

This is definitely an interesting idea, and when described as "the 
opposite of ??" the !?? syntax makes sense.

Looking at the example, though, the "negating" part becomes a bit confusing.

The verbose form reads naturally as a positive assertion - "if this is 
set, do this":
> if (isset($_SERVER['fname']) { > $user->setName($_SERVER['fname']); > }
If we used the ?? operator, it would be a negative, "if this is not set, do this":
> $_SERVER['fname'] ?? $user->unsetName();
So the short-hand form becomes a kind of double negative - "if this is not set, don't do this", or "if this is not not set, do this":
> $_SERVER['fname'] !?? $user->setName($_SERVER['fname']);
That makes me think that the choice of syntax isn't quite right, but I'm not sure what to suggest instead. Regards, -- Rowan Tommins (né Collins) [IMSoP]
  107669
October 24, 2019 20:29 andreas@dqxtech.net (Andreas Hennings)
On Thu, 24 Oct 2019 at 20:59, Ken Stanley <dohpaz@gmail.com> wrote:
> > On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <Danack@basereality.com> wrote: > > > On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: > > > > > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing > > > more succinct code for how to handle null values has been a blessing. > > But, > > > what about the inverse when you want to do something when a value is not > > > null? > > > > Hi Ken, > > > > It may help to give a real world example, rather than a metasyntactic > > one, as I can't immediately see how this would be useful. > > > > People have been expressing a concern over 'symbol soup' for similar > > ideas. The null colalesce scenario happens frequently enough, that it > > seemed to overcome the hurdle needed for acceptance. Again, giving a > > real world example of what you currently need to do frequently might > > help other people understand the need. > > > > cheers > > Dan > > > > Hi Dan, > > After some thought, and searching through my existing code bases, I believe > I've come up with a decent code example to help demonstrate the usefulness > of the proposed anti-coalescing-operator: > > Without !??: > > class ExampleController > { > /** > * PATCH a User object. > */ > public function saveAction(int $userId) > { > $user = $this->getUser($userId); > > if (isset($_SERVER['fname']) { > $user->setName($_SERVER['fname']); > } > > if (isset($_SERVER['lname']) { > $user->setName($_SERVER['lname']); > } > > if (isset($_SERVER['mname']) { > $user->setName($_SERVER['mname']); > } > > if (isset($_SERVER['phone']) { > $user->setName($_SERVER['phone']); > } > > if (isset($_SERVER['email']) { > $user->setName($_SERVER['email']); > } > > $this-saveUser($user); > } > } > > With !??: > > class ExampleController > { > /** > * PATCH a User object. > */ > public function saveAction(int $userId) > { > $user = $this->getUser($userId); > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); > $_SERVER['email'] !?? $user->setName($_SERVER['email']); > > $this-saveUser($user); > } > } > Thank you, > Ken Stanley
Not convinced. 1. Most of the perceived brevity is from omitting line breaks and curly brackets, which is a bit misleading imo. 2. It is not the intended use of these kinds of operators (ternary or null coalesce). Normally you would use them to produce a value, here you use them for control flow only. 3. One purpose of the operator should be that you don't have to repeat the variable. Here you do, e.g. $_SERVER['fname'] 1. If you would simply omit the line breaks in the first version, you would get this: if (isset($_SERVER['fname'])) $user->setName($_SERVER['fname']); if (isset($_SERVER['lname'])) $user->setName($_SERVER['lname']); if (isset($_SERVER['mname'])) $user->setName($_SERVER['mname']); if (isset($_SERVER['phone'])) $user->setName($_SERVER['phone']); if (isset($_SERVER['email'])) $user->setName($_SERVER['email']); 2. Instead of "abusing" your new operator, you could simply "abuse" the old ternary ?: instead: !isset($_SERVER['fname']) ?: $user->setName($_SERVER['fname']); !isset($_SERVER['lname']) ?: $user->setName($_SERVER['lname']); !isset($_SERVER['mname']) ?: $user->setName($_SERVER['mname']); !isset($_SERVER['phone']) ?: $user->setName($_SERVER['phone']); !isset($_SERVER['email']) ?: $user->setName($_SERVER['email']); 3. One way to not repeat the variable would be to introduce a temporary local variable, like so: if (NULL !== $fname = $_SERVER['fname'] ?? NULL) $user->setName($fname); This gets more useful if the variable expression is something longer. A new language feature for this purpose could have an anatomy like this: https://3v4l.org/TjuuO or https://3v4l.org/U6arm and the short syntax would be like so: $product = ($x ??! NULL) * ($y ??! NULL); or the NULL can be omitted: $product = ($x ??!) * ($y ??!); So, the operator would break out of the current expression context, and produce a value one level up, a bit like a try/throw/catch would, or like a break in switch. This is just a basic idea, it still leaves a lot of questions open. If the expression context is multiple levels deep, how many of these levels are we breaking? I am not suggesting this is a good idea, but I think it is an improvement to the original proposal. -- Andreas
  107670
October 24, 2019 21:19 webdevxp.com@gmail.com (Kosit Supanyo)
Hi Ken

I totally agree with Andreas especially:

One purpose of the operator should be that you don't have to repeat
> the variable. Here you do, e.g. $_SERVER['fname']
But if this operator provide some way not to repeat the variable it will make sense. For example: $_SERVER['fname'] !?? $user->setName($$) But I think this functionality should be of something like pipeline operator: // send tmp variable to the next expression unconditionally $ret = $_SERVER['fname'] |> $user->setName($$); // send tmp variable to the next expression only when $_SERVER['fname'] is set. $ret = $_SERVER['fname'] ?|> $user->setName($$); Also the syntax like above will be consistent with the proposed safe-navigation operators. Cheers On Fri, Oct 25, 2019 at 3:29 AM Andreas Hennings <andreas@dqxtech.net> wrote:
> On Thu, 24 Oct 2019 at 20:59, Ken Stanley <dohpaz@gmail.com> wrote: > > > > On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <Danack@basereality.com> > wrote: > > > > > On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: > > > > > > > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), > writing > > > > more succinct code for how to handle null values has been a blessing. > > > But, > > > > what about the inverse when you want to do something when a value is > not > > > > null? > > > > > > Hi Ken, > > > > > > It may help to give a real world example, rather than a metasyntactic > > > one, as I can't immediately see how this would be useful. > > > > > > People have been expressing a concern over 'symbol soup' for similar > > > ideas. The null colalesce scenario happens frequently enough, that it > > > seemed to overcome the hurdle needed for acceptance. Again, giving a > > > real world example of what you currently need to do frequently might > > > help other people understand the need. > > > > > > cheers > > > Dan > > > > > > > Hi Dan, > > > > After some thought, and searching through my existing code bases, I > believe > > I've come up with a decent code example to help demonstrate the > usefulness > > of the proposed anti-coalescing-operator: > > > > Without !??: > > > > > class ExampleController > > { > > /** > > * PATCH a User object. > > */ > > public function saveAction(int $userId) > > { > > $user = $this->getUser($userId); > > > > if (isset($_SERVER['fname']) { > > $user->setName($_SERVER['fname']); > > } > > > > if (isset($_SERVER['lname']) { > > $user->setName($_SERVER['lname']); > > } > > > > if (isset($_SERVER['mname']) { > > $user->setName($_SERVER['mname']); > > } > > > > if (isset($_SERVER['phone']) { > > $user->setName($_SERVER['phone']); > > } > > > > if (isset($_SERVER['email']) { > > $user->setName($_SERVER['email']); > > } > > > > $this-saveUser($user); > > } > > } > > > > With !??: > > > > > class ExampleController > > { > > /** > > * PATCH a User object. > > */ > > public function saveAction(int $userId) > > { > > $user = $this->getUser($userId); > > > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); > > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); > > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); > > $_SERVER['email'] !?? $user->setName($_SERVER['email']); > > > > $this-saveUser($user); > > } > > } > > Thank you, > > Ken Stanley > > Not convinced. > 1. Most of the perceived brevity is from omitting line breaks and > curly brackets, which is a bit misleading imo. > 2. It is not the intended use of these kinds of operators (ternary or > null coalesce). Normally you would use them to produce a value, here > you use them for control flow only. > 3. One purpose of the operator should be that you don't have to repeat > the variable. Here you do, e.g. $_SERVER['fname'] > > 1. > If you would simply omit the line breaks in the first version, you > would get this: > > if (isset($_SERVER['fname'])) $user->setName($_SERVER['fname']); > if (isset($_SERVER['lname'])) $user->setName($_SERVER['lname']); > if (isset($_SERVER['mname'])) $user->setName($_SERVER['mname']); > if (isset($_SERVER['phone'])) $user->setName($_SERVER['phone']); > if (isset($_SERVER['email'])) $user->setName($_SERVER['email']); > > 2. > Instead of "abusing" your new operator, you could simply "abuse" the > old ternary ?: instead: > > !isset($_SERVER['fname']) ?: $user->setName($_SERVER['fname']); > !isset($_SERVER['lname']) ?: $user->setName($_SERVER['lname']); > !isset($_SERVER['mname']) ?: $user->setName($_SERVER['mname']); > !isset($_SERVER['phone']) ?: $user->setName($_SERVER['phone']); > !isset($_SERVER['email']) ?: $user->setName($_SERVER['email']); > > 3. > One way to not repeat the variable would be to introduce a temporary > local variable, like so: > > if (NULL !== $fname = $_SERVER['fname'] ?? NULL) > $user->setName($fname); > > This gets more useful if the variable expression is something longer. > > A new language feature for this purpose could have an anatomy like this: > https://3v4l.org/TjuuO or > https://3v4l.org/U6arm > > and the short syntax would be like so: > > $product = ($x ??! NULL) * ($y ??! NULL); > > or the NULL can be omitted: > > $product = ($x ??!) * ($y ??!); > > So, the operator would break out of the current expression context, > and produce a value one level up, a bit like a try/throw/catch would, > or like a break in switch. > > This is just a basic idea, it still leaves a lot of questions open. > If the expression context is multiple levels deep, how many of these > levels are we breaking? > > I am not suggesting this is a good idea, but I think it is an > improvement to the original proposal. > > -- Andreas > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  107674
October 24, 2019 21:52 dohpaz@gmail.com (Ken Stanley)
On Thu, Oct 24, 2019 at 5:19 PM Kosit Supanyo com@gmail.com>
wrote:

> Hi Ken > > I totally agree with Andreas especially: > > One purpose of the operator should be that you don't have to repeat >> the variable. Here you do, e.g. $_SERVER['fname'] > > > But if this operator provide some way not to repeat the variable it will > make sense. For example: > > $_SERVER['fname'] !?? $user->setName($$) >
I asked Andreas for their opinion on why this is bad in this context? Especially since if I were to use a traditional ternary or if condition, then I'd still be repeating the variable.
> > But I think this functionality should be of something like pipeline > operator: > > // send tmp variable to the next expression unconditionally > $ret = $_SERVER['fname'] |> $user->setName($$); > // send tmp variable to the next expression only when $_SERVER['fname'] is > set. > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > Also the syntax like above will be consistent with the proposed > safe-navigation operators. >
I'm more interested in having a negation operator for the null-coalescing operator, especially since cognatively it should be easy to discern what it does. I've personally not seen |>, and I'd be confused as to what it does (e.g., is it a bitwise OR on a greater than comparison?). Thank you! The idea of $$ is neat, but not quite what I'm trying to achieve here. If anything, wouldn't that facilitate a different RFC? - Ken Stanley
  107676
October 24, 2019 22:00 marandall@php.net (Mark Randall)
On 24/10/2019 22:52, Ken Stanley wrote:
> I'm more interested in having a negation operator for the null-coalescing > operator, especially since cognatively it should be easy to discern what it > does.
At the point your syntax ends up looking like you're screaming at your source code, I think easy cognition has likely gone out the window. There are plenty of much more expressive ways of doing this without introducing new syntax IMHO. Mark Randall
  107677
October 24, 2019 22:02 webdevxp.com@gmail.com (Kosit Supanyo)
Hi Ken

`|>` is not something new it appeared in many languages long time ago (in
some forms). JavaScript also has a proposal of it. And PHP someone has
already proposed one.
https://github.com/tc39/proposal-pipeline-operator
https://wiki.php.net/rfc/pipe-operator

Cheers

On Fri, Oct 25, 2019 at 4:53 AM Ken Stanley <dohpaz@gmail.com> wrote:

> > On Thu, Oct 24, 2019 at 5:19 PM Kosit Supanyo com@gmail.com> > wrote: > >> Hi Ken >> >> I totally agree with Andreas especially: >> >> One purpose of the operator should be that you don't have to repeat >>> the variable. Here you do, e.g. $_SERVER['fname'] >> >> >> But if this operator provide some way not to repeat the variable it will >> make sense. For example: >> >> $_SERVER['fname'] !?? $user->setName($$) >> > > I asked Andreas for their opinion on why this is bad in this context? > Especially since if I were to use a traditional ternary or if condition, > then I'd still be repeating the variable. > > >> >> But I think this functionality should be of something like pipeline >> operator: >> >> // send tmp variable to the next expression unconditionally >> $ret = $_SERVER['fname'] |> $user->setName($$); >> // send tmp variable to the next expression only when $_SERVER['fname'] >> is set. >> $ret = $_SERVER['fname'] ?|> $user->setName($$); >> >> Also the syntax like above will be consistent with the proposed >> safe-navigation operators. >> > > I'm more interested in having a negation operator for the null-coalescing > operator, especially since cognatively it should be easy to discern what it > does. I've personally not seen |>, and I'd be confused as to what it does > (e.g., is it a bitwise OR on a greater than comparison?). > > Thank you! The idea of $$ is neat, but not quite what I'm trying to > achieve here. If anything, wouldn't that facilitate a different RFC? > > - Ken Stanley > >
  107692
October 25, 2019 10:20 rowan.collins@gmail.com (Rowan Tommins)
On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo com@gmail.com> wrote:

> But I think this functionality should be of something like pipeline > operator: > > // send tmp variable to the next expression unconditionally > $ret = $_SERVER['fname'] |> $user->setName($$); > // send tmp variable to the next expression only when $_SERVER['fname'] is > set. > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > Also the syntax like above will be consistent with the proposed > safe-navigation operators. >
I really like this idea, and it actually makes the pipeline operator itself feel more useful, too. Imagine this chain, where not only might the variable not be set, but it might not match a user, or the user might have no name: $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() ?|> strtoupper($$); As well as not needing to repeat the expression each time, as you would with an "anti-coalesce", "null-safe chain" feels a clearer reading of the intent here than "if not unset". Regards, -- Rowan Tommins [IMSoP]
  107695
October 25, 2019 10:27 andreas@dqxtech.net (Andreas Hennings)
On Fri, 25 Oct 2019 at 12:21, Rowan Tommins collins@gmail.com> wrote:
> > On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo com@gmail.com> wrote: > > > But I think this functionality should be of something like pipeline > > operator: > > > > // send tmp variable to the next expression unconditionally > > $ret = $_SERVER['fname'] |> $user->setName($$); > > // send tmp variable to the next expression only when $_SERVER['fname'] is > > set. > > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > > > Also the syntax like above will be consistent with the proposed > > safe-navigation operators. > > > > > I really like this idea, and it actually makes the pipeline operator itself > feel more useful, too. > > Imagine this chain, where not only might the variable not be set, but it > might not match a user, or the user might have no name: > > $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() > ?|> strtoupper($$); > > As well as not needing to repeat the expression each time, as you would > with an "anti-coalesce", "null-safe chain" feels a clearer reading of the > intent here than "if not unset".
I like this. It is a bit like a temporary local variable. One limitation is that you only have one such pipe value at a time. E.g. it would not cover this: return isset($a, $b) ? foo($a, $b) : null; or any nested parameters like foo(bar(baz())) where any intermediate value could be null.
  107696
October 25, 2019 10:28 andreas@dqxtech.net (Andreas Hennings)
On Fri, 25 Oct 2019 at 12:27, Andreas Hennings <andreas@dqxtech.net> wrote:
> > On Fri, 25 Oct 2019 at 12:21, Rowan Tommins collins@gmail.com> wrote: > > > > On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo com@gmail.com> wrote: > > > > > But I think this functionality should be of something like pipeline > > > operator: > > > > > > // send tmp variable to the next expression unconditionally > > > $ret = $_SERVER['fname'] |> $user->setName($$); > > > // send tmp variable to the next expression only when $_SERVER['fname'] is > > > set. > > > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > > > > > Also the syntax like above will be consistent with the proposed > > > safe-navigation operators. > > > > > > > > > I really like this idea, and it actually makes the pipeline operator itself > > feel more useful, too. > > > > Imagine this chain, where not only might the variable not be set, but it > > might not match a user, or the user might have no name: > > > > $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() > > ?|> strtoupper($$); > > > > As well as not needing to repeat the expression each time, as you would > > with an "anti-coalesce", "null-safe chain" feels a clearer reading of the > > intent here than "if not unset". > > I like this. > It is a bit like a temporary local variable. > > One limitation is that you only have one such pipe value at a time. > E.g. it would not cover this: > > return isset($a, $b) ? foo($a, $b) : null; > > or any nested parameters like foo(bar(baz())) where any intermediate > value could be null.
Sorry, this last part is wrong of course. The pipe works great for nested calls. Just with multiple parameters which all can be null it does not.
  107673
October 24, 2019 21:48 dohpaz@gmail.com (Ken Stanley)
On Thu, Oct 24, 2019 at 4:29 PM Andreas Hennings <andreas@dqxtech.net>
wrote:

> On Thu, 24 Oct 2019 at 20:59, Ken Stanley <dohpaz@gmail.com> wrote: > > > > On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <Danack@basereality.com> > wrote: > > > > > On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: > > > > > > > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), > writing > > > > more succinct code for how to handle null values has been a blessing. > > > But, > > > > what about the inverse when you want to do something when a value is > not > > > > null? > > > > > > Hi Ken, > > > > > > It may help to give a real world example, rather than a metasyntactic > > > one, as I can't immediately see how this would be useful. > > > > > > People have been expressing a concern over 'symbol soup' for similar > > > ideas. The null colalesce scenario happens frequently enough, that it > > > seemed to overcome the hurdle needed for acceptance. Again, giving a > > > real world example of what you currently need to do frequently might > > > help other people understand the need. > > > > > > cheers > > > Dan > > > > > > > Hi Dan, > > > > After some thought, and searching through my existing code bases, I > believe > > I've come up with a decent code example to help demonstrate the > usefulness > > of the proposed anti-coalescing-operator: > > > > Without !??: > > > > > class ExampleController > > { > > /** > > * PATCH a User object. > > */ > > public function saveAction(int $userId) > > { > > $user = $this->getUser($userId); > > > > if (isset($_SERVER['fname']) { > > $user->setName($_SERVER['fname']); > > } > > > > if (isset($_SERVER['lname']) { > > $user->setName($_SERVER['lname']); > > } > > > > if (isset($_SERVER['mname']) { > > $user->setName($_SERVER['mname']); > > } > > > > if (isset($_SERVER['phone']) { > > $user->setName($_SERVER['phone']); > > } > > > > if (isset($_SERVER['email']) { > > $user->setName($_SERVER['email']); > > } > > > > $this-saveUser($user); > > } > > } > > > > With !??: > > > > > class ExampleController > > { > > /** > > * PATCH a User object. > > */ > > public function saveAction(int $userId) > > { > > $user = $this->getUser($userId); > > > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); > > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); > > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); > > $_SERVER['email'] !?? $user->setName($_SERVER['email']); > > > > $this-saveUser($user); > > } > > } > > Thank you, > > Ken Stanley > > Not convinced. > 1. Most of the perceived brevity is from omitting line breaks and > curly brackets, which is a bit misleading imo.
This argument can be made about ?? And ?:, which have already passed muster and creates a precedent. Additionally, this is meant to compliment the existing ?? by adding a negation counterpart (similar to how == has !== and
> has <).
I’m curious to what you find misleading about it? Its meant to literally be the not-null coalescing operator.
> 2. It is not the intended use of these kinds of operators (ternary or > null coalesce). Normally you would use them to produce a value, here > you use them for control flow only.
Here is another example, not using them for flow control: user !?? $this->user->getName(); } } compared to: user instanceof User return $this->user !== null ? $this->user->getName() : null; } }
> 3. One purpose of the operator should be that you don't have to repeat > the variable. Here you do, e.g. $_SERVER['fname'] > > I'm not sure how that's necessarily a bad thing. Would you elaborate? Is it
simply a matter of writing the same characters twice? How is that different than: if (isset($_SERVER['fname'])) { $user->setName($_SERVER['fname']); }
> 1. > If you would simply omit the line breaks in the first version, you > would get this: > > if (isset($_SERVER['fname'])) $user->setName($_SERVER['fname']); > if (isset($_SERVER['lname'])) $user->setName($_SERVER['lname']); > if (isset($_SERVER['mname'])) $user->setName($_SERVER['mname']); > if (isset($_SERVER['phone'])) $user->setName($_SERVER['phone']); > if (isset($_SERVER['email'])) $user->setName($_SERVER['email']);
Ugh! I just noticed that I mistakenly did not update the method names for each line, so I can see how this might look like flow control. Those methods should be setFirstName, setLastName, setMiddleName, setPhone, and setEmail respectively. My apologies.
> > 2. > Instead of "abusing" your new operator, you could simply "abuse" the > old ternary ?: instead: > > !isset($_SERVER['fname']) ?: $user->setName($_SERVER['fname']); > !isset($_SERVER['lname']) ?: $user->setName($_SERVER['lname']); > !isset($_SERVER['mname']) ?: $user->setName($_SERVER['mname']); > !isset($_SERVER['phone']) ?: $user->setName($_SERVER['phone']); > !isset($_SERVER['email']) ?: $user->setName($_SERVER['email']); > > Re; #1 and #2 here: the same argument can be made for both ?? and ?:, which
again, has already passed muster and set precedent.
> 3. > One way to not repeat the variable would be to introduce a temporary > local variable, like so: > > if (NULL !== $fname = $_SERVER['fname'] ?? NULL) > $user->setName($fname); > The entire point of !?? would be to keep things terse and simple in nature.
Does it fit every possible use case? No. But neither do ?? and ?:. And, like ?? and ?:, no one is required to use it if they feel being more verbose makes sense for their needs.
> > This gets more useful if the variable expression is something longer. > > A new language feature for this purpose could have an anatomy like this: > https://3v4l.org/TjuuO or > https://3v4l.org/U6arm > > and the short syntax would be like so: > > $product = ($x ??! NULL) * ($y ??! NULL); > > or the NULL can be omitted: > > $product = ($x ??!) * ($y ??!); >
Not sure if the ??! was on purpose as an alternative to !??, but given how other operators put the negation operator first, I feel we should maintain the common standard.
> > So, the operator would break out of the current expression context, > and produce a value one level up, a bit like a try/throw/catch would, > or like a break in switch. > > Isn't this the same as the aforementioned null-safe operator [
https://wiki.php.net/rfc/nullsafe_calls]?
> This is just a basic idea, it still leaves a lot of questions open. > If the expression context is multiple levels deep, how many of these > levels are we breaking? > > I am not suggesting this is a good idea, but I think it is an > improvement to the original proposal. > > -- Andreas >
Thank you for the great feedback!
  107684
October 25, 2019 00:27 andreas@dqxtech.net (Andreas Hennings)
On Thu, 24 Oct 2019 at 23:49, Ken Stanley <dohpaz@gmail.com> wrote:
> > On Thu, Oct 24, 2019 at 4:29 PM Andreas Hennings <andreas@dqxtech.net> wrote: >> >> On Thu, 24 Oct 2019 at 20:59, Ken Stanley <dohpaz@gmail.com> wrote: >> > >> > On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <Danack@basereality.com> wrote: >> > >> > > On Thu, 24 Oct 2019 at 18:21, Ken Stanley <dohpaz@gmail.com> wrote: >> > > > >> > > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing >> > > > more succinct code for how to handle null values has been a blessing. >> > > But, >> > > > what about the inverse when you want to do something when a value is not >> > > > null? >> > > >> > > Hi Ken, >> > > >> > > It may help to give a real world example, rather than a metasyntactic >> > > one, as I can't immediately see how this would be useful. >> > > >> > > People have been expressing a concern over 'symbol soup' for similar >> > > ideas. The null colalesce scenario happens frequently enough, that it >> > > seemed to overcome the hurdle needed for acceptance. Again, giving a >> > > real world example of what you currently need to do frequently might >> > > help other people understand the need. >> > > >> > > cheers >> > > Dan >> > > >> > >> > Hi Dan, >> > >> > After some thought, and searching through my existing code bases, I believe >> > I've come up with a decent code example to help demonstrate the usefulness >> > of the proposed anti-coalescing-operator: >> > >> > Without !??: >> > > > >> > class ExampleController >> > { >> > /** >> > * PATCH a User object. >> > */ >> > public function saveAction(int $userId) >> > { >> > $user = $this->getUser($userId); >> > >> > if (isset($_SERVER['fname']) { >> > $user->setName($_SERVER['fname']); >> > } >> > >> > if (isset($_SERVER['lname']) { >> > $user->setName($_SERVER['lname']); >> > } >> > >> > if (isset($_SERVER['mname']) { >> > $user->setName($_SERVER['mname']); >> > } >> > >> > if (isset($_SERVER['phone']) { >> > $user->setName($_SERVER['phone']); >> > } >> > >> > if (isset($_SERVER['email']) { >> > $user->setName($_SERVER['email']); >> > } >> > >> > $this-saveUser($user); >> > } >> > } >> > >> > With !??: >> > > > >> > class ExampleController >> > { >> > /** >> > * PATCH a User object. >> > */ >> > public function saveAction(int $userId) >> > { >> > $user = $this->getUser($userId); >> > >> > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); >> > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); >> > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); >> > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); >> > $_SERVER['email'] !?? $user->setName($_SERVER['email']); >> > >> > $this-saveUser($user); >> > } >> > } >> > Thank you, >> > Ken Stanley >> >> Not convinced. >> 1. Most of the perceived brevity is from omitting line breaks and >> curly brackets, which is a bit misleading imo. > > > This argument can be made about ?? And ?:, which have already passed muster and creates a precedent.
But these were designed to produce a value, not for just control flow - see my other point. Yes, the same argument could have been made for those, if a similar example had been given to advertise their introduction.
> Additionally, this is meant to compliment the existing ?? by adding a negation counterpart (similar to how == has !== and > has <). > > I’m curious to what you find misleading about it? Its meant to literally be the not-null coalescing operator.
Misleading as in "look how much shorter this is".
> >> >> 2. It is not the intended use of these kinds of operators (ternary or >> null coalesce). Normally you would use them to produce a value, here >> you use them for control flow only. > > > Here is another example, not using them for flow control: > > > class Foo > { > /** > * @return User|null > */ > private $user; > > /** > * @return string|null > */ > public function getName(): ?string > { > return $this->user !?? $this->user->getName(); > } > } > > compared to: > > class Foo > { > /** > * @return User|null > */ > private $user; > > /** > * @return string|null > */ > public function getName(): ?string > { > // or $this->user instanceof User > return $this->user !== null ? $this->user->getName() : null; > } > }
This example is better indeed. But here I would prefer to have the ?-> operator proposed earlier (nullsafe calls). return $this->user?->getName();
>> >> 3. One purpose of the operator should be that you don't have to repeat >> the variable. Here you do, e.g. $_SERVER['fname'] >> > > I'm not sure how that's necessarily a bad thing. Would you elaborate? Is it simply a matter of writing the same characters twice? How is that different than: > > if (isset($_SERVER['fname'])) { > $user->setName($_SERVER['fname']); > }
I thought you like brevity? "terse and simple"? Ofc it is not just about typing more characters, but about having two places that need to be updated if we change the value expression. All the arguments for DRY apply. And yes, with existing if/else code we would also have this kind of repetition for this use case. But if we introduce a new operator, we would expect this to go away, wouldn't we? The repetition becomes more relevant if the expression we would repeat is really long: isset($something['something']['something']['something']) !?? $something['something']['something']['something']->foo();
> >> >> 1. >> If you would simply omit the line breaks in the first version, you >> would get this: >> >> if (isset($_SERVER['fname'])) $user->setName($_SERVER['fname']); >> if (isset($_SERVER['lname'])) $user->setName($_SERVER['lname']); >> if (isset($_SERVER['mname'])) $user->setName($_SERVER['mname']); >> if (isset($_SERVER['phone'])) $user->setName($_SERVER['phone']); >> if (isset($_SERVER['email'])) $user->setName($_SERVER['email']); > > > Ugh! I just noticed that I mistakenly did not update the method names for each line, so I can see how this might look like flow control. Those methods should be setFirstName, setLastName, setMiddleName, setPhone, and setEmail respectively. My apologies.
I meant "only control flow" in the sense that we are not returning a value, or rather, we do not read the value. Ofc it makes a more lively example to have different methods, but I was looking past that already :)
> >> >> >> 2. >> Instead of "abusing" your new operator, you could simply "abuse" the >> old ternary ?: instead: >> >> !isset($_SERVER['fname']) ?: $user->setName($_SERVER['fname']); >> !isset($_SERVER['lname']) ?: $user->setName($_SERVER['lname']); >> !isset($_SERVER['mname']) ?: $user->setName($_SERVER['mname']); >> !isset($_SERVER['phone']) ?: $user->setName($_SERVER['phone']); >> !isset($_SERVER['email']) ?: $user->setName($_SERVER['email']); >> > > Re; #1 and #2 here: the same argument can be made for both ?? and ?:, which again, has already passed muster and set precedent. >
As before, they were not really designed for this case. But if we do use them, they already go a long way.
>> >> 3. >> One way to not repeat the variable would be to introduce a temporary >> local variable, like so: >> >> if (NULL !== $fname = $_SERVER['fname'] ?? NULL) $user->setName($fname); > > The entire point of !?? would be to keep things terse and simple in nature. Does it fit every possible use case? No. But neither do ?? and ?:. And, like ?? and ?:, no one is required to use it if they feel being more verbose makes sense for their needs. > >> >> >> This gets more useful if the variable expression is something longer. >> >> A new language feature for this purpose could have an anatomy like this: >> https://3v4l.org/TjuuO or >> https://3v4l.org/U6arm >> >> and the short syntax would be like so: >> >> $product = ($x ??! NULL) * ($y ??! NULL); >> >> or the NULL can be omitted: >> >> $product = ($x ??!) * ($y ??!); > > > Not sure if the ??! was on purpose as an alternative to !??, but given how other operators put the negation operator first, I feel we should maintain the common standard.
I don't really think of it as a "negated ??". The motivation to have a negation seems quite theoretical to me. I am more interested in actual use cases.
> >> >> >> So, the operator would break out of the current expression context, >> and produce a value one level up, a bit like a try/throw/catch would, >> or like a break in switch. >> > > Isn't this the same as the aforementioned null-safe operator [https://wiki.php.net/rfc/nullsafe_calls]?
Except that ?-> only works for method chaining, not for function args. (as pointed out in a previous message) -- Andreas
> >> >> This is just a basic idea, it still leaves a lot of questions open. >> If the expression context is multiple levels deep, how many of these >> levels are we breaking? >> >> I am not suggesting this is a good idea, but I think it is an >> improvement to the original proposal. >> >> -- Andreas > > > > Thank you for the great feedback!
  107671
October 24, 2019 21:23 weirdan@gmail.com (Bruce Weirdan)
Hi Ken

> $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); > $_SERVER['email'] !?? $user->setName($_SERVER['email']);
What you described is already achievable with short-circuit && : isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); Besides, it's a widely used idiom known from shell scripting. -- Best regards, Bruce Weirdan mailto:weirdan@gmail.com
  107672
October 24, 2019 21:30 webdevxp.com@gmail.com (Kosit Supanyo)
Hi Bruce

If I understand correctly.

$_SERVER['fname'] !?? $user->setName($_SERVER['fname']);


Will return the result of  $user->setName($_SERVER['fname']) if
$_SERVER['fname']  is set or null if not set. While:

isset($_SERVER['fname']) && $user->setName($_SERVER['fname']);


Will return boolean.

Cheers

On Fri, Oct 25, 2019 at 4:24 AM Bruce Weirdan <weirdan@gmail.com> wrote:

> Hi Ken > > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > > $_SERVER['lname'] !?? $user->setName($_SERVER['lname']); > > $_SERVER['mname'] !?? $user->setName($_SERVER['mname']); > > $_SERVER['phone'] !?? $user->setName($_SERVER['phone']); > > $_SERVER['email'] !?? $user->setName($_SERVER['email']); > > What you described is already achievable with short-circuit && : > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > Besides, it's a widely used idiom known from shell scripting. > > -- > Best regards, > Bruce Weirdan mailto: > weirdan@gmail.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  107675
October 24, 2019 21:55 dohpaz@gmail.com (Ken Stanley)
On Thu, Oct 24, 2019 at 5:31 PM Kosit Supanyo com@gmail.com>
wrote:

> Hi Bruce > > If I understand correctly. > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > > > Will return the result of $user->setName($_SERVER['fname']) if > $_SERVER['fname'] is set or null if not set. While: > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > Will return boolean. >
Yes. Semantically the same, but one is terse and the other is explicit.
> > Cheers > >
  107680
October 24, 2019 23:23 pollita@php.net (Sara Golemon)
On Thu, Oct 24, 2019 at 4:55 PM Ken Stanley <dohpaz@gmail.com> wrote:

> > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > > Will return boolean. > > > > Just testing the waters: Is there any appetite to have AND and OR behave more like Pythons operator?
Instead of now: (a or b) => bool(true) if either of a or b are true (a and b) => bool(true) is either of a or b are true Behave as: (a or b) => Value of a if true, b if a is not true but b is, bool(false) otherwise. (a and b) => Value of b if both are true, bool(false) otherwise. Coincidentally, this change to T_LOGICAL_AND would server OP's purpose. I'll tell ya, I'm leaning "No" because BC, but at the same time, AND/OR seem to be underutilized constructs and I *suspect* (having done zero research), that most existing uses would yield the same result as they do now. -Sara
  107682
October 25, 2019 00:00 andreas@dqxtech.net (Andreas Hennings)
On Fri, 25 Oct 2019 at 01:24, Sara Golemon <pollita@php.net> wrote:
> > On Thu, Oct 24, 2019 at 4:55 PM Ken Stanley <dohpaz@gmail.com> wrote: > > > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > > > > Will return boolean. > > > > > > > Just testing the waters: Is there any appetite to have AND and OR behave > more like Pythons operator?
Similar to javascript || and &&, although not exactly the same.
> Instead of now: > (a or b) => bool(true) if either of a or b are true > (a and b) => bool(true) is either of a or b are true > > Behave as: > (a or b) => Value of a if true, b if a is not true but b is, bool(false) > otherwise. > (a and b) => Value of b if both are true, bool(false) otherwise. > > Coincidentally, this change to T_LOGICAL_AND would server OP's purpose. > > I'll tell ya, I'm leaning "No" because BC, but at the same time, AND/OR > seem to be underutilized constructs and I *suspect* (having done zero > research), that most existing uses would yield the same result as they do > now.
At one point I started using these operators because they have different operator precedence than || and &&, allowing assignment in conditions without parentheses. I gave up on this only to comply with coding standards and to not confuse people. I would think we will make a lot of people angry if we change this. Imo, let's not. Besides, a lot of this can be achieved with the ?: ternary shortcut (not sure what's the name).
> (a or b) => Value of a if true, b if a is not true but b is, bool(false) $a ?: ($b ?: false) === ($a ?: $b) ?: false === $a ?: $b ?: false
> (a and b) => Value of b if both are true, bool(false) otherwise. $a ? ($b ?: false) : false === $a ? $b ?: false : false
https://3v4l.org/q8Al9 It is a bit more verbose, I admit. But in most cases we don't need to replicate the exact behavior, and a simple ?: will do the trick. -- Andreas
> > -Sara
  107694
October 25, 2019 10:26 claude.pache@gmail.com (Claude Pache)
> Le 25 oct. 2019 à 01:23, Sara Golemon <pollita@php.net> a écrit : > > Just testing the waters: Is there any appetite to have AND and OR behave > more like Pythons operator? > Instead of now: > (a or b) => bool(true) if either of a or b are true > (a and b) => bool(true) is either of a or b are true > > Behave as: > (a or b) => Value of a if true, b if a is not true but b is, bool(false) > otherwise. > (a and b) => Value of b if both are true, bool(false) otherwise. >
Besides BC concerns, it is probably not a good idea to introduce (more) subtle differences between `and` and `&&`. That is, if you change `and`, you should change `&&` in the same direction. Maybe simply introduce the `!?:` operator?... Nevermind. —Claude