Comments (6)
I raised this question with Gilad in March, and I believe that is what prompted him to change the semantics from a = a ?? b
to ((v) => v == null ? a = b : v)(a)
. (Note that the spec changes that were made in https://codereview.chromium.org//1031323002 are consistent with the tests). So yes, it was a deliberate change and my preference would be to keep it the way it's currently spec'ed (and tested).
For context, here's the line of reasoning that motivated me to suggest the change:
- Given the short-cutting semantics of
??
(RHS is only evaluated when necessary), I think it's reasonable for a user to expect further short-cutting of??=
(assignment is only performed when necessary). - It's very rare (outside of contrived tests) to write code where
a = a
has deliberate side-effects. So for practical purposes the only difference between the two possible interpretations of??=
is execution speed. And unfortunately, we can't rely on the implementation to optimize away the redundant assignment. Consider the sophistication of analysis that has to be performed in order to determine that the assignment is redundant in the case ofa[b] ??= c
. In addition to proving some subtle invariants about the implementation of Map (or whatever the type ofa
is), you also have to check that the evaluation ofc
won't affecta
. The practical upshot of this is that if we interpreta ??= b
as shorthand fora = a ?? b
, then??=
will often be slower than what the user intends, making the benefit of the syntactic sugar dubious. - If we interpret
a ??= b
asa = a ?? b
, thena?.b ??= c
becomesa?.b = a?.b ?? c
, which has the very odd semantics that if a is null, then c is evaluated and then its result is thrown away! It's far more likely that what the user intends is(a == null ? null : a.b ??= c)
.
from nullawareoperators.
Thanks for the detailed answer Paul - and thanks for the link to the spec changes! I was only aware of the proposal in this repo, I didn't know the changes were already added to the actual spec, I'll take a look there as well.
Regarding:
which has the very odd semantics that if a is null, then c is evaluated and then its result is thrown away!
Not sure I follow this, given that a?.b = exp
semantics are:
((x) => x == null ? null : x.b = exp)(a)
It seems that desugarizing a ??= b
as a = a ?? b
should yield the same result in this case:
((x) => x == null ? null : x.b = a?.b ?? c)(a)
from nullawareoperators.
Follow up question: how many times do we print read
in this code?
var _x = new A();
get x {
print('read');
return _x;
}
main() {
x?.y ??= 3;
}
It seems like under the old semantics we'd print it twice:
x?.y ??= 3
// is equivalent to:
x?.y = x?.y ?? 3
// which corresponds to:
t1 = x; // (x in the lhs, prints "read")
if (t1 != null) {
t2 = x; // (x in the rhs, prints "read")
if (t2 != null) {
t3 = t2.y;
}
if (t3 == null) t3 = 3;
t1.y = t3;
}
It appears that under the new semantics we print it 3 times:
x?.y ??= 3
// expands to:
t1 = x?.y; // prints "read"
if (t1 == null) {
x?.y = x?.y ?? 3 // prints read twice like above.
}
is that correct?
from nullawareoperators.
Regarding a?.b ??= c
, you are right; please ignore what I previously said about this case.
Regarding the question of how many times "read" should be printed in the expression x?.y ??= 3
, it should only be printed once. Using the equivalent expression in the spec (https://codereview.chromium.org/1031323002/diff/1/docs/language/dartLangSpec.tex#newcode4481):
x?.y ??= 3
// expands to:
((z) => z == null ? null : z.y ??= 3)(x)
(to avoid confusion I used z
instead of x
for the parameter in the function literal). This means that the getter for x
is only called once, prior to invoking the function expression.
In general all the null-aware operators should evaluate subexpressions once if necessary, and zero times otherwise. Otherwise subexpressions with side effects will behave unexpectedly. Consider that a user might want to do myList[i++]?.y ??= 3
, in which case they expect i
to be incremented exactly once. I believe all the equivalent expressions in the spec achieve this; if you find one that doesn't I'd love to hear about it.
from nullawareoperators.
Sorry I didn't point you to the spec changes earlier. I've updated the tracking bugs dartbug.com/23454 and dartbug.com/23455 to point to the spec changes so that hopefully Matthias won't fall into the same trap.
from nullawareoperators.
Thanks Paul!
from nullawareoperators.
Related Issues (10)
- Please also support operators HOT 4
- typo in example
- Would prefer Groovy's Elvis operator "?:" instead of "??" HOT 2
- Single operator (a??b) covers all cases, and more HOT 3
- Change ?= to ??= for consistency with other compound assignment operators HOT 5
- Support ?.. for cascades HOT 6
- semantics of assigning to a?.x HOT 4
- semantics with statics and prefixes HOT 1
- Application to named parameters HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nullawareoperators.