I would love to have a "null-aware" operator for adding an element to a list if it is non-null.
[
foo,
?bar,
]
This would be equivalent to:
[
foo,
if (bar != null) bar,
]
I've been trying out the new "UI-as-code" features in the angular codebase, and find that I can't convert a common pattern to use the new element syntax.
We often iterate over a list, adding elements to a new list when the value is non-null.
var result = [];
for (var node in nodes) {
var value = convert(node);
if (value != null) result.add(value);
}
It would be pretty nice if I could instead use the new syntax:
var result = [
for (var node in nodes) ?convert(node);
]
In the short term, you can nest the if inside the for:
var result = [
for (var node in nodes) if (node != null) convert(node)
]
@bwilkerson I want to check the value of convert(node), not node for nullability. You're example would require me to call convert twice, which I do not want to do:
var result = [
for (var node in nodes) if (convert(node) != null) convert(node)
]
cc @munificent
This is an interesting corner. We could do some kind of single-value null-aware element syntax like you suggest. I'm very hesitant to pile more semantics onto ? because it's already quite overloaded in the grammar (postfix for nullable types, in null-aware operators, and in conditional expressions).
In many cases, you can use the other UI-as-code features like Brian suggests, but in this case you want to avoid any redundant computation. Of course, the natural way to do that is with a local variable, which makes me think building the list imperatively like you do today probably is the best approach.
We could introduce a let construct.
[ let tmp = something in if (tmp != null) tmp ]
which is obviously not as short as [? something], but it is more generally useful.
The current existing workaround is
[ for (var tmp in [something]) if (tmp != null) tmp ]
or
[... [something].where(isNotNull)]
or (after NNBD)
[... [something].whereType<Object>()]
All of these will likely introduce an intermediate list, with only the first example being likely to have that optimized away.
See also #219. Is there any difference?
I think the only difference is that in #219, you propose allowing ? to elide arguments in argument lists as well. Otherwise, I think they're the same.
I was just trying to find more use cases for an operator, and the discussion mentioned even more potential uses, but this has to be filtered, for sure. Maybe there's a way to merge these 2 discussions?
Most helpful comment
We could introduce a
letconstruct.which is obviously not as short as
[? something], but it is more generally useful.The current existing workaround is
or
or (after NNBD)
All of these will likely introduce an intermediate list, with only the first example being likely to have that optimized away.