godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.17k stars 98 forks source link

Add a C#-style casting shorthand to GDScript #10749

Open btarg opened 2 months ago

btarg commented 2 months ago

Describe the project you are working on

A game making heavy use of GDScript

Describe the problem or limitation you are having in your project

Casting into a variable safely currently requires quite a bit of boilerplate.

if (my_variable is MyCustomType):
    var my_custom_type := my_variable as MyCustomType # here we need to cast even after checking
    my_custom_type.hello_world()

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I believe GDScript casting should be more like C#.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

In C# and Java, this can be shortened as

// my_custom_type is set within the if statement
if (my_variable instanceof MyCustomType my_custom_type) {
    my_custom_type.hello_world()
}

Here is an example of how we can adopt a similar syntax in GDScript:

if my_variable is MyCustomType my_custom_type:
    print(my_custom_type.function())
elif my_variable is AnotherCustomType another_custom_type:
    print(another_custom_type.function())
    # so on and so forth...

If this enhancement will not be used often, can it be worked around with a few lines of script?

This is an enhancement to the current way of doing things rather than a brand new feature.

Is there a reason why this should be core and not an add-on in the asset library?

This is part of GDScript

dalexeev commented 2 months ago

See also:

Jesusemora commented 2 months ago

The C# way looks confusing. The gdscript way looks much cleaner.

btarg commented 2 months ago

The C# way looks confusing. The gdscript way looks much cleaner.

I'm not suggesting instanceof be the syntax if that's what you mean. Otherwise I find it much easier and quicker to work with - especially if you have to otherwise cast multiple times! For example:

if my_variable is MyCustomType my_custom_type:
    print(my_custom_type.function())
elif my_variable is AnotherCustomType another_custom_type:
# so on and so forth...

6941 is definitely worth looking at. That proposal is very much in line with what I want added to GDScript! There is also some overlap of discussion in that thread on the very same syntax I'm suggesting here. I'm not sure if there's a way of consolidating the two however.

dalexeev commented 2 months ago

The last time we discussed this, we came to the conclusion that it would be nice to have the static analyzer take into account local control flow, including type checking. This seems more consistent with GDScript's design goals (simplicity and readability) than explicit type narrowing syntax.

aXu-AP commented 2 months ago

A small nitpick, but to my knowledge there is no instanceof keyword in C#, it's is and it's used just as you suggested for gdscript:

if (vehicle is Car car) 
    car.drive();

Also you can do this in gdscript without double casting:

var car = vehicle as Car
if car: # null if not Car.
    car.drive()

That said, I do like C# syntax for is, but would prefer even more if it worked via magic/static analysis as mentioned above due to dynamic nature of gdscript. Also the syntax in C# feels more idiomatic: you declare variables with Car car;, so using similiar statement in tandem with is is natural. In gdscript, you declare with keyword var, so the resulting code doesn't look like normal gdscript.

btarg commented 2 months ago

A small nitpick, but to my knowledge there is no instanceof keyword in C#, it's is and it's used just as you suggested for gdscript:

if (vehicle is Car car) 
    car.drive();

Also you can do this in gdscript without double casting:

var car = vehicle as Car
if car: # null if not Car.
    car.drive()

That said, I do like C# syntax for is, but would prefer even more if it worked via magic/static analysis as mentioned above due to dynamic nature of gdscript. Also the syntax in C# feels more idiomatic: you declare variables with Car car;, so using similiar statement in tandem with is is natural. In gdscript, you declare with keyword var, so the resulting code doesn't look like normal gdscript.

My apologies, I didn't realise you could do that in GDScript. Perhaps the lack of autocomplete was an editor issue on my end. And yeah, looks like I was mixing up c# and Java when discussing is.

sockeye-d commented 2 months ago

Alternative syntaxes:

# I think this is the most "fluent"
if some_var is SomeType create new_var:

# kinda strange
if some_var is SomeType scope new_var:

# uhh not totally sure about this one 
if new_var: SomeType stores some_var:

# this might be getting somewhere
if new_var: SomeType holds some_var:

(not saying it should be like this, just another option)