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

Python-like list unpacking/destructuring #7584

Closed
jkb0o opened this issue Jan 20, 2017 · 21 comments
Closed

Python-like list unpacking/destructuring #7584

jkb0o opened this issue Jan 20, 2017 · 21 comments

Comments

@jkb0o
Copy link
Contributor

jkb0o commented Jan 20, 2017

One of my favorite things in python is unpacking list to values.

a, b, c = [1,2,3]
# a == 1
# b == 2
# c == 3

first, *rest = [1,2,3]
# first == 1
# rest == [ 2, 3 ]

for a,b in [[1,2], [3,4]]:
    # 0: a == 1, b == 2
    # 1: a == 3, b == 4
    pass

I have a lot of GDScript code that looks ugly and woody without this feature. It makes me sad. I won't be sad.

I want to know your opinion about this feature and try to implement this if it proves popular.

@bojidar-bg
Copy link
Contributor

Note this this is probably partly doable with @karroffel's new match syntax:

match [1,2,3]:
  [var a, var b, var c]: # do stuff here

Anyway, duplicate of #3504 (albeit the other issue is a bit badly titled)

@akien-mga
Copy link
Member

Are those variables accessible outside the scope of the match block?

@bojidar-bg
Copy link
Contributor

@akien-mga Obviously no, but still a valid workaround 😃

@akien-mga
Copy link
Member

A bit fast to close the discussion then when it just has a bad workaround :)

@karroffel
Copy link
Contributor

I could try to implement that by reusing parts of the pattern parser

@bojidar-bg
Copy link
Contributor

bojidar-bg commented Jan 20, 2017

@akien-mga Did you actually misread the "duplicate" part or yes?

@akien-mga
Copy link
Member

Oops :)

@akien-mga
Copy link
Member

Reopening as #3504 was closed by its author, so now this issue is much clearer for further discussion of the feature.

@akien-mga akien-mga reopened this Jan 29, 2017
@karroffel
Copy link
Contributor

I want to throw an idea in here.

The pattern matcher could be used to archieve something like this. Many functional languages implement patterns on the left side of assignments too. So much of the code could be reused to implement something like this.

Example

var [a, b, c] = [1, 33, 7]
do_stuff(a, b, c)
...

could be transformed into

match [1, 33, 7]:
    [var a, var b, var c]:
        do_stuff(a, b, c)
        ...
    _:
         return # Usually you throw an error here if the pattern fails
                # but the rules could be loosened to just let it slip

@hubbyist
Copy link

hubbyist commented Jan 30, 2017

What about adding function to export variables to outer scope of match? This may add more branching possibilities.

match [1, 33, 7]:
    [var a, var b, var c]:
        export_vars_to_outer_scope(a, b, c)
    _:
        return
if(is_something(a):
    do_other_stuff(a)
do_stuff(a, b, c)

@bojidar-bg
Copy link
Contributor

We don't need to reuse the match syntax at all, though we might reuse some part of the parser, etc. 😃

@karroffel
Copy link
Contributor

That's what I meant, not reusing the syntax, just the parser and transformation functions

@bojidar-bg
Copy link
Contributor

bojidar-bg commented Mar 19, 2017

This is duplicate of the dissolved #3504 (bugsquad -- do not close). Given that there is interest throughout the community for it, I guess we can keep it around....

Counting how many people requested it so far: ~4-5 (including myself this time). One more needed for "many", according to @akien-mga. Volunteers?

@gokhansolak
Copy link

This ability also makes it easier to return multiple values from functions.

    def my_func:
      return "abc", 3

    a, b = my_func()

It makes the code more readable and decreases the dev time. Good feature 👍

@pgruenbacher
Copy link

Yea what bothers me in gdscript is that I can do this without syntax error or runtime error.

	var a
	var b
	[a, b] = [4, 5]
	print("A", a, "B", b)

and yet a and b stay nil

@manekinekodesu
Copy link

This would be very useful feature. I hope it'll be implemented sooner rather than later.

@Calinou
Copy link
Member

Calinou commented Nov 4, 2019

@manekinekodesu Please don't bump issues without contributing significant new information; use the 👍 reaction button on the first post instead.

@robbertzzz
Copy link

I came upon this issue after looking for something similar, but different: declaring multiple variables without assigning values to them. I was hoping to do this much like javascript:
var a, b, c;
Or possibly even this:
var a:int, b:int, c:int;
Which could be assigned values as follows:
var a:int = 1, b:int = 2, c:int = 3;
I feel like this might get very unclear to read in the python way when mixing variable types:
var a, b, c = [1.254, Vector2(-5, 64), "Hello World!"];

.. Of course, mixing variable types on a single line would probably be bad practice in all cases, but who knows when it might come in handy!

@Calinou
Copy link
Member

Calinou commented Jan 10, 2020

.. Of course, mixing variable types on a single line would probably be bad practice in all cases, but who knows when it might come in handy!

Then it might not be a good idea to implement it in the first place 🙂

@mnn
Copy link

mnn commented Jan 24, 2020

Yes, this would be very welcome. Example from real code:

var parsed = parse_fn(expr); var args = parsed[0]; var op = parsed[1]; var body = parsed[2]

It's intentionally on one line to not balloon a function body to be more than twice in LoC, obscuring parts of code actually doing something more useful.

What it could have been:

var [args, op, body] = parse_fn(expr)

I know I could modify parse_fn to return object/dict, but the function is not used anywhere else (and never will be) and I suspect an array might be faster. (But it's hard to tell, since obj/dict could be used directly without destructuring. It would probably depend on optimizations of compiler/runtime.)

It might be a good idea to add into the title "destructuring" (e.g. in parenthesis at the end), since that term is commonly used in popular languages like JS or Scala. I had to follow a trail of closed issues to arrive here.

Basic syntax (without rest) seems to be quite same in several langs:

> const [x, y] = [1, 2]
undefined
> x
1
> y
2
scala> val Array(x, y) = Array(1, 2)
x: Int = 1
y: Int = 2

scala> val (x, y) = (1, 2)
x: Int = 1
y: Int = 2
Prelude> let [x, y] = [1, 2]
Prelude> x
1
Prelude> y
2
Prelude> let (x, y) = (1, 2)
Prelude> x
1
Prelude> y
2

@Calinou Calinou changed the title Python-like list unpacking Python-like list unpacking/destructuring Jan 24, 2020
@akien-mga
Copy link
Member

akien-mga commented May 26, 2020

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Edit: It was opened here: godotengine/godot-proposals#2135

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

No branches or pull requests