More null-aware operators (comparison & assignment)
I'm truly sorry if this issue is a duplicate, I tried searching for this but I couldn't find anything. Maybe I don't know enough language jargon.
Take this Dart code:
int? value = getValue();
if (value > 0) { // operator > can't be unconditionally invoked because the receiver can be 'null'
print("greater than 0");
}
So, we can't do if (bool?), only if (bool), which makes sense. However, it would be convenient if there were null-aware comparison operators. Surely we can get more use of the ? right guys?
Currently, you can do:
int? value = getValue();
if ((value ?? 0) > 0) { // doesn't work without nested parenthesis
print("greater than 0");
}
but it's a bit messy, in my opinion.
Idea:
Explicit
My main idea is just to place the question mark either before or after an operator symbol like so: value ?> 0 which would only continue if value is NOT null.
// To be clear, both of these operators do the same thing, I'm just proposing one or the other
// depending on what makes more sense (the position of the '?'.)
// Unless, there's significant interest in introducing both of these operators and
// having them behave differently (one guards against null and the other allows null.)
if (val >? 0) {}
if (val ?> 0) {}
Implicit
Alternatively, we could just have this behavior for operators right now, like what C# does:
int? val = null;
if (val > 0) { // no error
Console.WriteLine("greater than 0"); // doesn't run
} else {
// this runs instead
}
I'm not sure how breaking that would be though.
Assignment:
We can also do this for assignment operators:
int? val = null;
val ?+= 10; // Only adds 10 if 'val' is NOT null
val ?-= 10;
val ?*= 10;
val ?/= 10;
It's not new to want some null awareness with operators. Not sure this precise version has been suggested as its own issue before. (I cannot find things using GitHub search either.)
An immediate issue with if (val ?> 0) … is that the obvious value of that expression of val is null is null, and null is not valid where a bool is required.
There are ways to fix that:
- Allow
nullto meanfalsein any condition. That's error-prone. - require you to write
(val ?> 0) ?? false. That's more verbose, closer to where you could just writeval != null && val > 0. - say that
val ?> 0evaluates tofalseifvalisnull. But>is user-definable, it doesn't have to returnbool. - Not allow it, and defer to patterns:
val case >0?.
My favorite if we were to generalize null-awareness:
- introduce "null aware context"s that catch null-checks and define what they mean.
- let
?expr, andexpr?followed by a selector or operator, be an expression, which bails out to the nearest surrounding null aware context if the value isnull. - a condition context would introduce a null-aware context which converts a null-bailout to
false. - a null-aware selector will introduce a null-aware context for the rest of the chain, if not already inside one, which converts bailout to
null, like today'sfoo?.bar(), but also allowingfoo?.bar(?val). - elements are null-aware contexts that omit the element on bailout, like today's
[?val], but also[foo(?val)]. - you can introduce an explicit null-aware context using
(?expr), so any failing null-aware check inside will bail out to this expression and evaluate tonull.
Assignment expressions may still need their own syntax, or expr?+= could preserve expr being assignable, only affecting the read of the composite operation.
this one is very usefull