Skip to content
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

Allow to define variables inside conditions #2727

Open
KoBeWi opened this issue May 14, 2021 · 14 comments · May be fixed by godotengine/godot#98538
Open

Allow to define variables inside conditions #2727

KoBeWi opened this issue May 14, 2021 · 14 comments · May be fixed by godotengine/godot#98538

Comments

@KoBeWi
Copy link
Member

KoBeWi commented May 14, 2021

Describe the project you are working on

Complex project using GDScript.

Describe the problem or limitation you are having in your project

This was actually suggested in the past (e.g. godotengine/godot#7222 and partially godotengine/godot#20634), but I've just encountered a case where it could be very convenient and after brief consideration it has a few advantages.

So my problem I encountered just now is:
I have a method, let's say get_value() which returns an int. I used it like

if get_value(sth):
  do_something()

BUT, I now want to use the value from the method. I have to do:

var val = get_value(sth)
if val:
  do_something2(val)

This code has several problems:

  • it's one line longer
  • val is not needed in my scope, only inside the condition
  • consequently, if I want to use it multiple times in the same scope, I can't copy-paste it
var val = get_value(sth)
if val:
  do_something2(val)
var val = get_value(sth2) # value is re-declared. Need to drop var part
if val:
  do_something3(val)

As you can see, it's pretty meh.

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

The problem disappears when declaring variable inside condition is allowed. However, instead of doing if a = something: I propose something a bit different: if var a = something:

The above code changes into

if var val = get_value(sth):
  do_something2(val)
if var val = get_value(sth2):
  do_something3(val)
  • val exists only inside condition
  • I can easily copy-paste-change it
  • it's shorter
  • the var part ensures that you don't make the common mistake of accidental asignement inside condition

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

Just allow if var a = value syntax.
EDIT: while var a = value would be useful too (see #2727 (comment))

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

The point is to avoid these lines.

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

Can't be an addon.

@Xrayez
Copy link
Contributor

Xrayez commented May 15, 2021

I think this makes sense, but not 100% sure about the syntax yet, so let me brainstorm...

If we take for loops, they also introduce variables that exist only side for loops, without var:

for i in 100:
    do_something(i)

Using var inside if breaks this expectation:

if var val = get_value(sth):
  do_something2(val)

That said, perhaps other parts could allow var syntax, even if not necessary (for consistency):

for var i in 100:
    do_something(i)

while var state = get_state(sth):
    do_something(state)

I mean, I guess in any case this would touch expressions parsing in general, so should be applicable to other control flow operators, not just conditionals.

@mieldepoche
Copy link

my two cents:

  • while var x = 5: is ambiguous: is x set to 5 on each loop or only at initialisation/when entering the loop?

  • I Would find it hard to read personnaly, since the condition would not next to the while/if/... anymore.
    I would prefer something like if x > 5 with var x := 12: and while current != "" with var current = dir.get_next()
    Parentheses would go like this if needed: if(...) with(...) and while(...) with(...).

  • Also, how would it behave when 2+ variables are needed?

@KoBeWi
Copy link
Member Author

KoBeWi commented May 16, 2021

Using var inside if breaks this expectation:

Not really, because you are assigning the variable. for and while don't use =.

@Xrayez
Copy link
Contributor

Xrayez commented May 16, 2021

Using var inside if breaks this expectation:

Not really, because you are assigning the variable. for and while don't use =.

Sorry, what I meant is that it would break expectation if you are going to use if var syntax everywhere, but then find out that other control flow operators/expressions don't use this syntax (the other way around).

@Xrayez
Copy link
Contributor

Xrayez commented May 16, 2021

  • I Would find it hard to read personnaly, since the condition would not next to the while/if/... anymore.
    I would prefer something like if x > 5 with var x := 12: and while current != "" with var current = dir.get_next()
    Parentheses would go like this if needed: if(...) with(...) and while(...) with(...).

I like this idea, but people prefer to have less keywords in GDScript...

  • Also, how would it behave when 2+ variables are needed?

Probably not needed, it's something which does not cater to common use case as described in this proposal.

@KoBeWi
Copy link
Member Author

KoBeWi commented May 17, 2021

Ok, I found use-case for = in `while, and it was in Godot's codebase:

while ((key = color_map[p_theme_type].next(key))) {
    p_list->push_back(*key);
}

So with this we could do

dir.dir_list_begin()
while var file = dir.get_next():
    stuff

instead of

dir.dir_list_begin()
var file = dir.get_next()
while file:
    stuff
    file = dir.get_next()

@YuriSizov
Copy link
Contributor

Tree is another example of a linked list where this can be used.

@Xrayez
Copy link
Contributor

Xrayez commented May 17, 2021

Tree is another example of a linked list where this can be used.

Looks like implementing this proposal could indeed improve the linked list usage via script: #1522.

@MaaaxiKing
Copy link

I know, it's complicated, but I do like the =-syntax. The reason for that is that I'd adore if no == existed, just = which is either an assigment, a comparison or both in one!

@jonbonazza
Copy link

jonbonazza commented Feb 5, 2024

I like go’s syntax:

if foo := bar(); foo ==blah” {
    // foo is “blah. Do something
}

obviously this syntax isn’t very gdscript-like and could be massaged to fit conventions, but yea, i like that you can define a variable and have an explicit condition in a single line. It’s more verbose than the proposed solution but its far more flexible. Obviously, you can use any condition after the ; it doesnt just need to be a single equality check or w/e.

@anonymalek
Copy link

anonymalek commented Apr 24, 2024

In C# syntax it would be something like

if(thing is Type thingAsType)

in gd could be something like

if thing is Type var thing_as_type:

@MaaaxiKing
Copy link

in gd could be something like

if thing is Type var thing_as_type:

Although I do like C#'s equivalent to Java's Pattern Matching for instanceof, I don't agree with your idea since it could be difficult to do static typing here.

@anonymalek
Copy link

in gd could be something like

if thing is Type var thing_as_type:

Although I do like C#'s equivalent to Java's Pattern Matching for instanceof, I don't agree with your idea since it could be difficult to do static typing here.

you mean technically difficult because of how gdscript works?

@MaaaxiKing
Copy link

you mean technically difficult because of how gdscript works?

yeah, basically (because of the colon operator for specifying the type)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants