godot: GDScript idea: add a null-coalescing operator, which returns first non-null value
In Python, Lua and Javascript (I think?), you can write this shortcut:
a = None
b = "Hello"
print(a or b)
prints “Hello”, and still evaluates to True if used in an if.
Booleans behaviour is unchanged.
In GDScript, print(str(a or b)) would be readable and shorter to write than:
var result = a
if a == null:
result = b
print(str(result))
And even shorter than ternary, and also allows to write and evaluate a only once instead of two.
it could be chained as well:
a or b or c or d would fall back to the first one that is not null.
What do you think?
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 17
- Comments: 45 (27 by maintainers)
Let me re-propose using the
elseoperator from ternaries instead of theoroperator. The rationale is that it has not function on its own currently, except to spam errors.The examples from the last comments would look like this:
If you think about it,
a else bis probably one of the most natural syntax sugars fora if a else b.I am going to go forth and reopen this issue, just because it has attracted a lot of comments. This does not mean it would be implemented though, since it is here for discussion.
I find it very confusing. you can simply do:
or, to be more explicit (and include the empty string):
What’s wrong with C++'s ternary operator syntax?? It is great, easy and intuitive.
But you had to write a twice^^
I would expect that
prints “Hello” if either a or b evaluates to true
I think it would make more sense to write
It’s not that useful, it’s just syntax sugar for the regular ternary operator.
I’m against using the
orkeyword for this.a or bis a boolean operation, it’s already taken. I propose using??like C# does. e.g.:a ?? b.@vnen On the other hand, it is very helpful to avoid conditional branching logic when all you really want to do is express the value of something that could be null.
versus
versus
This is not about trying to get instructions on a single line. This is about 1. avoiding having to use conditional branching control flow when all you really want to do is express the value of something, and 2. nesting ternaries is terrible.
This example, expressing fallback values for a variable, is pretty much its primary use case. However, this comes in handy surprisingly often when working with a language that allows null values.
It is also useful when you want a function to have default values for an argument that need to be initialized.
That said, the ternary expression can also be used for this, though it is ugly:
It comes down to the fact that the ternary expression is not a good fit for these cases because we don’t actually want a 3-ary operation. We just want to short circuit null values.
No, it’s not. If you did, say,
a() if a() != null else b(), it would run a() twice (if it’s not null), because it doesn’t remember the value, making for an unnecessary and maybe big slow operation. You can replicate the null coalescing operator with, but
a or b/a ?? bis way shorter, which is the point.My thoughts precisely. I was also not aware that Python and Lua support such a syntax, but at first sight it seems highly confusing to me. What would be the output of
print("Hello" or "world")? Orprint(null and "Hello")?IMO it makes more sense to stay consistent and treat
a or banda and bas conditionals in all situations, such they should always resolve to True or False.What you suggest in the OP can be achieved with
print(a if a else b), which is IMO clearer thanprint(a or b).I would be looking forward to this feature as well, with either the “else” or “??” syntax. Both sound good to me.
@mwerezak I wouldn’t advise for making new features to the language right now, because they would have to either wait or block the typed gdscript PR (probably). I might help you do it (or do it outright, if you don’t want) after it is merged 😃.
Superseded by https://github.com/godotengine/godot-proposals/issues/1321
I guess I didn’t say enough. If the precedence was
a if (a else b) else c, wouldn’t it be harder to parse? It’d break existing code:a if a else b(normally done) would be interpreted asa if (a else b), which is invalid, unless the parser can backtrack a bit. I said a bool is more common, as one reason the precedence should bind the firstelseto theif, whether the parser is smart or not.@neikeq you are not supposed to use the two together without some parenthesis.
There are many operators which are order-dependent or hard to reason about without parentheses. E.g., is
"a" + 2 + 3going to produce"a23"or"a5"? What abouta and b or c?I have very recently written some code wishing that I had something like Dart’s null-aware operators.
So for example, an excerpt from the code I wish I had null-aware operators for…
Without Null-aware Operators
With Null-aware Operators
Ok, let’s get started counting if there are many people who want it. As @akien-mga said:
So far I count 3 ± 1 people, still not enough for a hand.
Now with ternary-if we can do something like this:
a = something if something else 3and it looks kinda funny. Some syntax sugar could be nice.expression else valueproposed by @bojidar-bg seems to nice be idea:a = something else 3@Dillybob92 Well, it would default to 5 in case it isn’t set in the scene (you can unset it via the “refresh” button next to the value).
We might make the
expression else valueoperator evaluate the expression as normal, but, instead of failing on errors, make it take on thevaluepart, WDYT? (instant try-catch, but, who cares…)(sorry stupid misclick)
@bojidar-bg in your example you would need a “tryget”, not a “get”. But GDScript Dictionaries don’t have such a thing as far as I know.
tryget is not the same topic but also has the advantage of fetching the item only once in case of a read and be able to use it in a one-liner (so instead of
if d[key]: d[key]you can writed.tryget["key"]which returns null if not found).I see you wrote a helper to generate the entry, so you could write this if you really want to:
But this is a bad specific example, I would just have a helper doing this:
I think that @ajacobsen’s binary-ternary-else idea is pretty good actually.
Php has it as the “elvis operator”:
In GDScript it would look like:
Finally, in JavaScript this is used and overused all the time, so it might be either somewhat good or terribly bad…
print("Hello" or "world")would print “Hello”, andprint(null and "Hello")would print null, just as in Python and Lua. The logic behind is that the operators don’t return True or False, but the last evaluated argument (that was evaluating as True or False anyways). However if you use comparison operators in the expression (<>=!=not) then you’ll get booleans as usual.I’ve mostly used this in Lua, where ternary doesn’t exist http://lua-users.org/wiki/TernaryOperator. I was just doing the suggestion because I’ve seen this technique used not only in Lua, but also in Javascript, and the fact Python supports it could mean it could have been requested and used for a reason.
I’m ok with explicit ternaries, just wanted to know the community opinion.
Edit: another point is that the first operand is evaluated only once.