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
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
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
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
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.
On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker cmbecker69@gmx.de
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
On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker cmbecker69@gmx.de
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.
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 Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker cmbecker69@gmx.de
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/oKIklFurthermore, 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/TJYhqI 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/MVT85Looks interesting, but people have to type this! So, no unicode symbols.
Kind regards,
AidanIf 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.
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
What is going on here? I think I missed the original post.
On Thu, Jan 18, 2018 at 7:13 PM, Christoph M. Becker cmbecker69@gmx.de
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
What is going on here? I think I missed the original post.
https://externals.io/message/101620
Here you can find all messages.
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.
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.
The "Null Coalescing Assignment Operator" (or null coalesce assignment
operator) was proposed and accepted in
https://wiki.php.net/rfc/null_coalesce_equal_operatorI 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