-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement a null-coalescing operator (??
)
#1321
Comments
I would allow only one syntax for this, so we don't have multiple ways to achieve the same thing (due to style guide complexity, among other reasons). I'm not sure if we should go for |
I would choose
What about operators |
The same goes for |
I would advocate for adding The operator Adding I, personally, love both For example, getting data from a possible child node could be reduced from 6-ish lines to one with both operators in use: # Current method of getting child data
var tex
var sprite = get_node("Sprite")
if sprite:
tex = sprite.texture
if not tex:
tex = load("res://...")
...
#### VS ####
# Null coalesce method
var tex = get_node("Sprite")?.texture ?? load("res://...")
... Just adding Also, using var a = a if b else c else d
# Which do you mean?
var a = a if (b else c) else d
var a = a if b else (c else d) Not saying folks should use that syntax, just that parsing it out seems problematic. |
??
)
As a side note, it's nice if you can do multiline so it flows. In the below example, if a line ever results in null then the execution moves to the next line. var tex_size = \
get_node("Sprite")?.texture?.get_size() ??
get_node("Sprite_2")?.texture?.get_size() ??
Vector2.ZERO Having it flow like that makes it real easy to read and track. Pretty sure this may require |
You can also use parentheses to wrap long statements without requiring var tex_size = (
get_node("Sprite")?.texture?.get_size() ??
get_node("Sprite_2")?.texture?.get_size() ??
Vector2.ZERO
) |
Oh, yeah, haha. That works. |
Side note for future implementer: |
I agree that |
This is being discussed at #1902 |
Hey guys I was thinking about this right now and I have a slighty different solution. Vnen suggested I should provide my solution in this post. It occured to me we could modify the ternary operator to behave like a nullish coalescing operator when it has no
Would return "default" if a is == null otherwise returns a so is equivalent to The missing else already exists as an error check so you could re-purpose and use it to switch ternary behavior to a nullish coalescing behavior. You could also make the |
Godot has so many null things that I, personally, would like to see more than just null coalesce. There's the coalescing dot operator, the coalescing accessor, etc. The proposals that use words I feel lack foresight for those other operators and offer no more clarity than the null operators that are becoming ubiquitous already. Also, |
It sounds like this operator would only return the right value if the left value was Because EDIT: Other possible symbols could be |
This might be closed if the discussion over at: #162 gets resolved. |
Is Maybe |
I think just var a = null
var b := 5
# Previously would be `true` with `c` being a `bool`
# Would suddenly become `5` with `c` being `int`
var c := a or b |
In my opinion, naming the operator var a = null ?? 42 # expected 42, because left is null
var b = 0 ?? 42 # expected 0, because left is non-null
# BUT:
var c = 0 or 42 # expected 42 because left is falsy While the const default_value = 42
var user_entered_number = 0 # null if nothing entered, or parsed number if there's something entered
# ?? operator
var value = user_entered_number ?? default_value # 0 (user entered value)
# or operator
var value = user_entered_number or default_value # expected to be 0 (user entered value) but it's 42 (default_value) In this scenario, a stricter null check is necessary to ensure correct handling of null values. Using the While the exact naming is not critical, I believe it should not be named |
|
I personally prefer var value = user_input ?? 42; # using ??
# or
var value = user_input default 42; # using 'default' |
I quite like the suggestion of |
I don't think folks are reading the comments and the issue hasn't been updated to reflect them. Using an operator makes more sense than a word, as more should be supported than just The operators Since both Also, inventing new conventions means re-teaching everyone. Using existing conventions means new folks can be sent to preexisting guides that happen to fit. For the love of Hal9000... please don't re-invent this wheel. |
This comment was marked as off-topic.
This comment was marked as off-topic.
I propose considering the null-coalescing operator purely as syntactic sugar. It should maintain backward compatibility, so using "or" as the operator is not a good idea. A novel symbol could be beneficial for clarity. I will use "elthen" in this case. And it should be very easy to implement. So I think it can convert into a ternary operator in gdscript parsing procedure. For example: var result = happy elthen "sad" will turn into var result = happy if happy else "sad" Such an addition should pose no issues. Aas an optional operator, it enhances readability and understanding. |
Rolling out a pipeline operator is definitely more useful than just ?. or ?[]. Plus, it works super well with the null coalescing operator. Check out the JavaScript proposal for the pipeline operator for more info: https://tc39.es/proposal-pipeline-operator/ Like, take C# for example, where you might access something with: var answer = Hitchhiker?.galaxy?.answer ?? 42 With a pipeline function, it would be: var answer = Hitchhiker then prev.galaxy then prev.answer elthen 42 Pipe operator can do even more: var answer = await get_answer_from_website() then prev.parse_json() then prev.answer elthen 42 Pipeline operator is more versatile than ?. and ?[], and they're not that complex, syntax-wise. |
So if I understand correctly, "or" cant be option because of backward compatibility? What about "otherwise?" I suppose ?? will work, but if you don't come from a language that uses it, you will need to look it up in the docs. |
You'll likely guess wrong if you mistake it for the
This can trip people off, it's better to use |
Hmmm. That's true. So I suppose I will just recommend
Going off of that, I think In conclusion: |
@nathanfranke It may help to change the title to "Implement Null-coalescing Operators That may help with the comments? I don't expect everyone to read the whole comment thread, but anything we could do to help stem how often it repeats itself would be nice. (Though I suspect some comments are just bumps in disguise, which can't be stopped.) |
Yes please use the symbols rather than words. And it's Regarding I believe I've seen a language (can't remember which) not allow a a?.b.c # would be a nullability error with left-to-right precedence
(a?.b).c # added parenthesis shows BAD precedence implementation! .c MUST NOT run if a is null!
a?.b?.c # you would be forced to do this, checking null twice The correct way is that a?.b.c # valid syntax; a is nullable, but b and c are not nullable
a(?.b.c) # added fake parenthesis to explain CORRECT precedence for the above
a.b.c if a != null else a # meaning Regarding
So IMO null-safe operators should be:
|
Note that # Calling foo or syntax error after cast
if foo as Bar?():
pass
# Indexing into `Bar` or syntax error after cast
if foo as Bar?[2]:
pass
# Typed array of `Bar?` or invalid indexing into a boolean
if foo is Bar?[]:
pass Typescript completely forbids |
@bbb651 Remember, typed array syntax in GDScript is the "generics" syntax
Well, in Regarding Regarding |
It may help to keep an eye on https://peps.python.org/pep-0505/ They have had intense discussions around 505 and hashed out a lot of the discussion here already. |
Supersedes godotengine/godot#7223
CC @Zylann
Describe the project you are working on:
This can work on any project, but currently I want to implement a "Fallback" color if the given color is null.
Describe the problem or limitation you are having in your project:
The ternary operator can be used as a fallback, but it is...
a if a else b
rather thana else b
.a() if a() else b()
callsa()
twice.http_get() if http_get() else cached_value
(Edit: Specific example doesn't make sense here)Describe the feature / enhancement and how it helps to overcome the problem or limitation:
The enhancement would be to implement an operator that simplifies this workflow. See the code example below.
Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
To avoid ambiguity from boolean
or
, I propose operatorelse
with alternate symbol counterpart??
.If this enhancement will not be used often, can it be worked around with a few lines of script?:
This will be used often. Currently, the workaround for slow or non-const function is:
Is there a reason why this should be core and not an add-on in the asset library?:
It would not be possible to implement this in an add-on so that the code is brief. The only simplification would be a coalescing function like
Even with the function,
b
would always be evaluated even ifa
is valid.The text was updated successfully, but these errors were encountered: