null coalesce addition assignment operator ??+=

  101620
January 18, 2018 22:52 andreas@dqxtech.net (Andreas Hennings)
The "Null Coalescing Assignment Operator" (or null coalesce assignment
operator) was proposed and accepted in
https://wiki.php.net/rfc/null_coalesce_equal_operator

I propose even more such operators:
null coalesce addition assignment ??+= (for strings and numbers)
null coalesce subtraction assignment ??-=
null coalesce increment ??++
null coalesce decrement ??--
null coalesce multiplication assingment ??*=


## Details

Each block contains 3 equivalent statements.

$x ??+= 5;  // proposed new syntax
($x ??= 0) += 5;  // syntax with null coalesce assignment operator
$x = ($x ?? 0) + 5;  // syntax with simple null coalesce operator

$x ??+= 'suffix';  // proposed new syntax
($x ??= '') += 'suffix';  // syntax with null coalesce assignment operator
$x = ($x ?? '') + 'suffix';  // syntax with simple null coalesce operator

$x ??++;  // proposed new syntax
($x ??= 0)++;
$x = ($x ?? 0) + 1;

$x ??*= 2;  // proposed new syntax
($x ??= 1) *= 2;
$x = ($x ?? 1) * 2;

Note that in each case PHP needs to determine the "neutral element" of
the operation.
For string concat this is the empty string. For number addition this
is 0. For number multiplication it is 1.


## Example:

For me, the most common use case would be something like this:

$fruitpacks = [
  ['apples', 3],
  ['pears', 1],
  ['apples', 6],
  ['grapes', 22],
];

$totals_by_name = [];
foreach ($fruitpacks as [$name, $amount]) {
  $totals_by_name[$name] ??+= $amount;  // proposed new syntax
}

$totals_by_name_expected = [
  'apples' => 9,
  'pears' => 1,
  'grapes' => 22,
];

assert($totals_by_name === $totals_by_name_expected);


## Notes

In PHP, the "+=" operator already behaves almost like "??+=", but adds
a "Notice: Undefined offset" or "Notice: Undefined variable", if the
left side is not defined yet.
hhvm apparently does not produce this notice.
https://3v4l.org/l0l0K
  101621
January 18, 2018 22:58 smalyshev@gmail.com (Stanislav Malyshev)
Hi!

> I propose even more such operators: > null coalesce addition assignment ??+= (for strings and numbers) > null coalesce subtraction assignment ??-= > null coalesce increment ??++ > null coalesce decrement ??-- > null coalesce multiplication assingment ??*=
I think this is taking it too far. If you want language like that, you always have APL :) -- Stas Malyshev smalyshev@gmail.com
  101623
January 19, 2018 00:13 cmbecker69@gmx.de ("Christoph M. Becker")
On 18.01.2018 at 23:58, Stanislav Malyshev wrote:

>> I propose even more such operators: >> null coalesce addition assignment ??+= (for strings and numbers) >> null coalesce subtraction assignment ??-= >> null coalesce increment ??++ >> null coalesce decrement ??-- >> null coalesce multiplication assingment ??*= > > I think this is taking it too far. If you want language like that, you > always have APL :)
Why do we discuss extensions to an operator which has still (after nearly two years) not be implemented due to implementation difficulties? -- Christoph M. Becker
  101625
January 19, 2018 15:12 pollita@php.net (Sara Golemon)
On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote:
> On 18.01.2018 at 23:58, Stanislav Malyshev wrote: > >>> I propose even more such operators: >>> null coalesce addition assignment ??+= (for strings and numbers) >>> null coalesce subtraction assignment ??-= >>> null coalesce increment ??++ >>> null coalesce decrement ??-- >>> null coalesce multiplication assingment ??*= >> >> I think this is taking it too far. If you want language like that, you >> always have APL :) > > Why do we discuss extensions to an operator which has still (after > nearly two years) not be implemented due to implementation difficulties? > Am I the only one who looked at the original post and assumed he was
taking the piss? Similar to the jokes about spaceship assignment <=>= and equality/identicality assignment === (not to be confused with identical non-assign, which is ===) and ====. -Sara
  101633
January 20, 2018 01:25 andreas@dqxtech.net (Andreas Hennings)
On 19 January 2018 at 16:12, Sara Golemon <pollita@php.net> wrote:
> On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote: >> On 18.01.2018 at 23:58, Stanislav Malyshev wrote: >> >>>> I propose even more such operators: >>>> null coalesce addition assignment ??+= (for strings and numbers) >>>> null coalesce subtraction assignment ??-= >>>> null coalesce increment ??++ >>>> null coalesce decrement ??-- >>>> null coalesce multiplication assingment ??*= >>> >>> I think this is taking it too far. If you want language like that, you >>> always have APL :) >> >> Why do we discuss extensions to an operator which has still (after >> nearly two years) not be implemented due to implementation difficulties? >> > Am I the only one who looked at the original post and assumed he was > taking the piss? > Similar to the jokes about spaceship assignment <=>= and > equality/identicality assignment === (not to be confused with > identical non-assign, which is ===) and ====.
I can definitely say it was not a joke. I can see myself and others use the ??+= and also ??++, and would have used them in the past, if they had been available. The others, I don't care as much. For me, a good enough conclusion of this conversation would be one of: A: Yeah seems useful, but let's wait (or work) until ??= is implemented and released, and observe how it is being used. B: No one will ever use it, and it would hurt the language.
  101634
January 20, 2018 03:29 aidantwoods@gmail.com (Aidan Woods)
On 20 January 2018 at 01:25, Andreas Hennings <andreas@dqxtech.net> wrote:

> On 19 January 2018 at 16:12, Sara Golemon <pollita@php.net> wrote: > > On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> > wrote: > >> On 18.01.2018 at 23:58, Stanislav Malyshev wrote: > >> > >>>> I propose even more such operators: > >>>> null coalesce addition assignment ??+= (for strings and numbers) > >>>> null coalesce subtraction assignment ??-= > >>>> null coalesce increment ??++ > >>>> null coalesce decrement ??-- > >>>> null coalesce multiplication assingment ??*= > >>> > >>> I think this is taking it too far. If you want language like that, you > >>> always have APL :) > >> > >> Why do we discuss extensions to an operator which has still (after > >> nearly two years) not be implemented due to implementation difficulties? > >> > > Am I the only one who looked at the original post and assumed he was > > taking the piss? > > Similar to the jokes about spaceship assignment <=>= and > > equality/identicality assignment === (not to be confused with > > identical non-assign, which is ===) and ====. > > I can definitely say it was not a joke. > I can see myself and others use the ??+= and also ??++, and would have > used them in the past, if they had been available. > The others, I don't care as much. > > For me, a good enough conclusion of this conversation would be one of: > A: Yeah seems useful, but let's wait (or work) until ??= is > implemented and released, and observe how it is being used. > B: No one will ever use it, and it would hurt the language. > > Going by the example, would this operator's behaviour be a little confusing?
As I understand it the (maybe) upcoming `??=` operator will assign in the case that the lhs is *not defined*. But for `??+=` incrementing appears to be desired when the lhs *is defined*, (with assignment to the operator related identity element in the case that the lhs is undefined). While the use-case seems to add value in the scenario, I think it is possibly inconsistent with the way `??=` works? Furthermore, I think you can generalise this in user-land and end up with a better result. When dealing with structured data (i.e. when you expect strings mapping to ints in your example) you may consider writing a simple class for making such type guarantees. Something simple like https://3v4l.org/5Sh04 would produce the desired result, and let you obtain the result in one line at point of use. Nothing ties you into using a class for the storage though, you could simplify even further and just create some abstract class representing an "array toolbox" for these kind of operations, e.g. https://3v4l.org/ZJcom So that the array initialisation, foreach loop, and operator are replaced with a single line again at point of use (after defining the arraytools class once). If you wanted it to work more generally, you could use a reference to delay lookup, and keep your current code structure https://3v4l.org/TJYhq If you wanted it to look the part you could even sneak some unicode symbols in to make it look like some sort of operator ;-) https://3v4l.org/MVT85 Kind regards, Aidan
  101635
January 20, 2018 05:47 andreas@dqxtech.net (Andreas Hennings)
On 20 January 2018 at 04:29, Aidan Woods <aidantwoods@gmail.com> wrote:
> On 20 January 2018 at 01:25, Andreas Hennings <andreas@dqxtech.net> wrote: >> >> On 19 January 2018 at 16:12, Sara Golemon <pollita@php.net> wrote: >> > On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> >> > wrote: >> >> On 18.01.2018 at 23:58, Stanislav Malyshev wrote: >> >> >> >>>> I propose even more such operators: >> >>>> null coalesce addition assignment ??+= (for strings and numbers) >> >>>> null coalesce subtraction assignment ??-= >> >>>> null coalesce increment ??++ >> >>>> null coalesce decrement ??-- >> >>>> null coalesce multiplication assingment ??*= >> >>> >> >>> I think this is taking it too far. If you want language like that, you >> >>> always have APL :) >> >> >> >> Why do we discuss extensions to an operator which has still (after >> >> nearly two years) not be implemented due to implementation >> >> difficulties? >> >> >> > Am I the only one who looked at the original post and assumed he was >> > taking the piss? >> > Similar to the jokes about spaceship assignment <=>= and >> > equality/identicality assignment === (not to be confused with >> > identical non-assign, which is ===) and ====. >> >> I can definitely say it was not a joke. >> I can see myself and others use the ??+= and also ??++, and would have >> used them in the past, if they had been available. >> The others, I don't care as much. >> >> For me, a good enough conclusion of this conversation would be one of: >> A: Yeah seems useful, but let's wait (or work) until ??= is >> implemented and released, and observe how it is being used. >> B: No one will ever use it, and it would hurt the language. >> > > Going by the example, would this operator's behaviour be a little confusing? > > As I understand it the (maybe) upcoming `??=` operator will assign in the > case that the lhs is *not defined*. > But for `??+=` incrementing appears to be desired when the lhs *is defined*, > (with assignment to the operator related identity element in the case that > the lhs is undefined). > > While the use-case seems to add value in the scenario, I think it is > possibly > inconsistent with the way `??=` works?
I think it depends how you see it. // shortcut return $x ??= 5; return $y ??+= 5; // spelled out, looks inconsistent return isset($x) ? $x : ($x = 5); return isset($y) ? ($y += 5) : ($y = 5); // spelled out, looks a bit more consistent (despite being broken) return (isset($x) ? $x : ($x = 5)); return (isset($y) ? $y : ($y = 0)) += 5; // invalid code, because ternary is not a valid lhs. The line is invalid, but shows the mental model or the excuse that allows us to claim this is consistent. But yeah, I can see how someone would expect a different behavior: return isset($x) ? $x : ($x = 5); return isset($y) ? $y : ($y += 5); This would not make sense or be useful because: For $y === NULL, this would evaluate as return $y = NULL + 5: Still, your argument raises a valid concern that the operator might be misunderstood. If we get ??=, I previously thought we could use it like this, to replicate ??+=: return ($y ??= 0) += 5; Unfortunately, I think we can expect that ??= won't be a valid lhs, because neither is *= or += etc. E.g. this is invalid: ($y *= 3) += 1; https://3v4l.org/oKIkl
> > Furthermore, I think you can generalise this in user-land and end up with a > better result.
comments below.
> > When dealing with structured data (i.e. when you expect strings mapping to > ints in your example) you may consider writing a simple class for making > such type guarantees. Something simple like https://3v4l.org/5Sh04 would > produce the desired result, and let you obtain the result in one line at > point > of use. > > Nothing ties you into using a class for the storage though, you could > simplify > even further and just create some abstract class representing an "array > toolbox" > for these kind of operations, e.g. https://3v4l.org/ZJcom > So that the array initialisation, foreach loop, and operator are replaced > with a > single line again at point of use (after defining the arraytools class > once). > > If you wanted it to work more generally, you could use a reference to delay > lookup, and keep your current code structure https://3v4l.org/TJYhq
I was never a big friend of those array functions with callback arguments, which force me to remember a signature. I find a simple foreach() to be more readable. I think it is also faster. So yeah, I prefer this example to the previous ones.
> > If you wanted it to look the part you could even sneak some unicode symbols > in to make it look like some sort of operator ;-) https://3v4l.org/MVT85
Looks interesting, but people have to type this! So, no unicode symbols.
> > Kind regards, > Aidan
If I were to do it in userland, it would either be - in my own custom library or application, where it would not be used by others, or - in a shared package, which other packages could add as a dependency. I think usually people will decide against adding a dependency for a bit of syntax sugar. E.g. if the existing null coalesce operator was provided as a userland solution, I don't think this package would have become popular. Instead, code that uses such a package would become less readable, not more readable. I remember when I was dealing with CiviCRM, which had those "something smart with arrays" functions. Maybe they had the same purpose as what we discuss here, or they did something else. The result was: Whenever I had to look at such a call, I was confused, and had to re-confirm what it does. Maybe it could have gotten used to it, but I did not spend that much time with CiviCRM. Nowadays I prefer native features, even if they are more verbose. They also need to be learned / gotten used to, but at least this experience will be the same for everyone. I also often do these kinds of array-crunching operations in throwaway code for debugging, e.g. to build a statistic for a bunch of values. In such cases I don't want to add a new dependency to the application.
  101636
January 20, 2018 06:08 andreas@dqxtech.net (Andreas Hennings)
As mentioned earlier:
In hack (hhvm), operators like +=, *= etc do allow the left side to be
undefined.
(However, ++ and -- do not allow the left side to be undefined.)

I wonder if this is intended, or by accident.

On 20 January 2018 at 06:47, Andreas Hennings <andreas@dqxtech.net> wrote:
> On 20 January 2018 at 04:29, Aidan Woods <aidantwoods@gmail.com> wrote: >> On 20 January 2018 at 01:25, Andreas Hennings <andreas@dqxtech.net> wrote: >>> >>> On 19 January 2018 at 16:12, Sara Golemon <pollita@php.net> wrote: >>> > On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> >>> > wrote: >>> >> On 18.01.2018 at 23:58, Stanislav Malyshev wrote: >>> >> >>> >>>> I propose even more such operators: >>> >>>> null coalesce addition assignment ??+= (for strings and numbers) >>> >>>> null coalesce subtraction assignment ??-= >>> >>>> null coalesce increment ??++ >>> >>>> null coalesce decrement ??-- >>> >>>> null coalesce multiplication assingment ??*= >>> >>> >>> >>> I think this is taking it too far. If you want language like that, you >>> >>> always have APL :) >>> >> >>> >> Why do we discuss extensions to an operator which has still (after >>> >> nearly two years) not be implemented due to implementation >>> >> difficulties? >>> >> >>> > Am I the only one who looked at the original post and assumed he was >>> > taking the piss? >>> > Similar to the jokes about spaceship assignment <=>= and >>> > equality/identicality assignment === (not to be confused with >>> > identical non-assign, which is ===) and ====. >>> >>> I can definitely say it was not a joke. >>> I can see myself and others use the ??+= and also ??++, and would have >>> used them in the past, if they had been available. >>> The others, I don't care as much. >>> >>> For me, a good enough conclusion of this conversation would be one of: >>> A: Yeah seems useful, but let's wait (or work) until ??= is >>> implemented and released, and observe how it is being used. >>> B: No one will ever use it, and it would hurt the language. >>> >> >> Going by the example, would this operator's behaviour be a little confusing? >> >> As I understand it the (maybe) upcoming `??=` operator will assign in the >> case that the lhs is *not defined*. >> But for `??+=` incrementing appears to be desired when the lhs *is defined*, >> (with assignment to the operator related identity element in the case that >> the lhs is undefined). >> >> While the use-case seems to add value in the scenario, I think it is >> possibly >> inconsistent with the way `??=` works? > > I think it depends how you see it. > > // shortcut > return $x ??= 5; > return $y ??+= 5; > > // spelled out, looks inconsistent > return isset($x) ? $x : ($x = 5); > return isset($y) ? ($y += 5) : ($y = 5); > > // spelled out, looks a bit more consistent (despite being broken) > return (isset($x) ? $x : ($x = 5)); > return (isset($y) ? $y : ($y = 0)) += 5; // invalid code, because > ternary is not a valid lhs. > > The line is invalid, but shows the mental model or the excuse that > allows us to claim this is consistent. > > But yeah, I can see how someone would expect a different behavior: > > return isset($x) ? $x : ($x = 5); > return isset($y) ? $y : ($y += 5); > > This would not make sense or be useful because: > For $y === NULL, this would evaluate as > return $y = NULL + 5: > > Still, your argument raises a valid concern that the operator might be > misunderstood. > > > > If we get ??=, I previously thought we could use it like this, to > replicate ??+=: > > return ($y ??= 0) += 5; > > Unfortunately, I think we can expect that ??= won't be a valid lhs, > because neither is *= or += etc. > E.g. this is invalid: > ($y *= 3) += 1; > https://3v4l.org/oKIkl > > >> >> Furthermore, I think you can generalise this in user-land and end up with a >> better result. > > comments below. > >> >> When dealing with structured data (i.e. when you expect strings mapping to >> ints in your example) you may consider writing a simple class for making >> such type guarantees. Something simple like https://3v4l.org/5Sh04 would >> produce the desired result, and let you obtain the result in one line at >> point >> of use. >> >> Nothing ties you into using a class for the storage though, you could >> simplify >> even further and just create some abstract class representing an "array >> toolbox" >> for these kind of operations, e.g. https://3v4l.org/ZJcom >> So that the array initialisation, foreach loop, and operator are replaced >> with a >> single line again at point of use (after defining the arraytools class >> once). >> >> If you wanted it to work more generally, you could use a reference to delay >> lookup, and keep your current code structure https://3v4l.org/TJYhq > > I was never a big friend of those array functions with callback > arguments, which force me to remember a signature. > I find a simple foreach() to be more readable. I think it is also faster. > > So yeah, I prefer this example to the previous ones. > >> >> If you wanted it to look the part you could even sneak some unicode symbols >> in to make it look like some sort of operator ;-) https://3v4l.org/MVT85 > > Looks interesting, but people have to type this! So, no unicode symbols. > >> >> Kind regards, >> Aidan > > If I were to do it in userland, it would either be > - in my own custom library or application, where it would not be used > by others, or > - in a shared package, which other packages could add as a dependency. > > I think usually people will decide against adding a dependency for a > bit of syntax sugar. > E.g. if the existing null coalesce operator was provided as a userland > solution, I don't think this package would have become popular. > Instead, code that uses such a package would become less readable, not > more readable. > > I remember when I was dealing with CiviCRM, which had those "something > smart with arrays" functions. > Maybe they had the same purpose as what we discuss here, or they did > something else. > The result was: Whenever I had to look at such a call, I was confused, > and had to re-confirm what it does. > Maybe it could have gotten used to it, but I did not spend that much > time with CiviCRM. > > Nowadays I prefer native features, even if they are more verbose. > They also need to be learned / gotten used to, but at least this > experience will be the same for everyone. > > I also often do these kinds of array-crunching operations in throwaway > code for debugging, e.g. to build a statistic for a bunch of values. > In such cases I don't want to add a new dependency to the application.
  101660
January 22, 2018 22:14 pollita@php.net (Sara Golemon)
On Fri, Jan 19, 2018 at 8:25 PM, Andreas Hennings <andreas@dqxtech.net> wrote:
> I can definitely say it was not a joke. > Alrighty then...
> A: Yeah seems useful, but let's wait (or work) until ??= is > implemented and released, and observe how it is being used. > Funnily enough, ??+= would be easier to implement than ??= because in
the case of ??+= we always want to evaluate the RHS, while in the case of ??= the RHS's evaluation is conditional.
> B: No one will ever use it, and it would hurt the language. > "hurt" is subjective here, and for every X participants to this thread
you'll get X+1 answers on what that means. :p -Sara
  101637
January 20, 2018 11:02 mtkocak@gmail.com (=?UTF-8?Q?Midori_Ko=C3=A7ak?=)
What is going on here? I think I missed the original post.

On 19 January 2018 at 16:12, Sara Golemon <pollita@php.net> wrote:

> On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker <cmbecker69@gmx.de> > wrote: > > On 18.01.2018 at 23:58, Stanislav Malyshev wrote: > > > >>> I propose even more such operators: > >>> null coalesce addition assignment ??+= (for strings and numbers) > >>> null coalesce subtraction assignment ??-= > >>> null coalesce increment ??++ > >>> null coalesce decrement ??-- > >>> null coalesce multiplication assingment ??*= > >> > >> I think this is taking it too far. If you want language like that, you > >> always have APL :) > > > > Why do we discuss extensions to an operator which has still (after > > nearly two years) not be implemented due to implementation difficulties? > > > Am I the only one who looked at the original post and assumed he was > taking the piss? > Similar to the jokes about spaceship assignment <=>= and > equality/identicality assignment === (not to be confused with > identical non-assign, which is ===) and ====. > > -Sara > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  101638
January 20, 2018 11:43 andreas@dqxtech.net (Andreas Hennings)
On 20 January 2018 at 12:02, Midori Koçak <mtkocak@gmail.com> wrote:
> What is going on here? I think I missed the original post.
https://externals.io/message/101620 Here you can find all messages.
  101622
January 18, 2018 23:06 andreas@dqxtech.net (Andreas Hennings)
Some background / personal experience
(cross-posting with Stanislav, but I am sending it anyway)

I regularly see code with arrays in loops, where the ??+= or ??++
would be nice to have.
I do not remember seeing use cases for *=.
In all the cases I remember, the left side was an array offset, not a
plain variable.

I think the spec has to be for plain variables first, even if the main
use case is arrays.
I only added the ??*=, ??-=, ??++, ??-- for completeness, but I can
live without.


On 18 January 2018 at 23:58, Stanislav Malyshev <smalyshev@gmail.com> wrote:
> I think this is taking it too far. If you want language like that, you > always have APL :)
It looks a bit cluttery (one character too many for an operator?), but I think it is useful and intuitive. If you understand ??, ??= and +=, you also understand ??+=. But let's see what others say. On 18 January 2018 at 23:52, Andreas Hennings <andreas@dqxtech.net> wrote:
> The "Null Coalescing Assignment Operator" (or null coalesce assignment > operator) was proposed and accepted in > https://wiki.php.net/rfc/null_coalesce_equal_operator > > I propose even more such operators: > null coalesce addition assignment ??+= (for strings and numbers) > null coalesce subtraction assignment ??-= > null coalesce increment ??++ > null coalesce decrement ??-- > null coalesce multiplication assingment ??*= > > > ## Details > > Each block contains 3 equivalent statements. > > $x ??+= 5; // proposed new syntax > ($x ??= 0) += 5; // syntax with null coalesce assignment operator > $x = ($x ?? 0) + 5; // syntax with simple null coalesce operator > > $x ??+= 'suffix'; // proposed new syntax > ($x ??= '') += 'suffix'; // syntax with null coalesce assignment operator > $x = ($x ?? '') + 'suffix'; // syntax with simple null coalesce operator > > $x ??++; // proposed new syntax > ($x ??= 0)++; > $x = ($x ?? 0) + 1; > > $x ??*= 2; // proposed new syntax > ($x ??= 1) *= 2; > $x = ($x ?? 1) * 2; > > Note that in each case PHP needs to determine the "neutral element" of > the operation. > For string concat this is the empty string. For number addition this > is 0. For number multiplication it is 1. > > > ## Example: > > For me, the most common use case would be something like this: > > $fruitpacks = [ > ['apples', 3], > ['pears', 1], > ['apples', 6], > ['grapes', 22], > ]; > > $totals_by_name = []; > foreach ($fruitpacks as [$name, $amount]) { > $totals_by_name[$name] ??+= $amount; // proposed new syntax > } > > $totals_by_name_expected = [ > 'apples' => 9, > 'pears' => 1, > 'grapes' => 22, > ]; > > assert($totals_by_name === $totals_by_name_expected); > > > ## Notes > > In PHP, the "+=" operator already behaves almost like "??+=", but adds > a "Notice: Undefined offset" or "Notice: Undefined variable", if the > left side is not defined yet. > hhvm apparently does not produce this notice. > https://3v4l.org/l0l0K