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

GDScript: Variadic functions (variable number of arguments/varargs) #16565

Closed
mhilbrunner opened this issue Feb 11, 2018 · 29 comments
Closed

GDScript: Variadic functions (variable number of arguments/varargs) #16565

mhilbrunner opened this issue Feb 11, 2018 · 29 comments

Comments

@mhilbrunner
Copy link
Member

Issue description:
Add support for variadic functions to GDScript.

This would mostly be syntactic sugar, transforming:

func f(args):
    for x in args:
        # Do something with x

f(["these", "are", "some", "arguments"])

into:

func f(args...):
    for x in args:
        # Do something with x

f("these", "are", "some", "arguments")
@LikeLakers2
Copy link
Contributor

Just so I'm understanding this correctly, are we talking something like ruby's splat operator?

@ghost
Copy link

ghost commented Feb 12, 2018

last time i suggested something for gdscript it got shut down & shunned by reduz pretty quick, so just a warning (i'm voting yes btw, gl!)

@mhilbrunner
Copy link
Member Author

@LikeLakers2 From a brief look, yes exactly.

@girng Well I'd hope that really depends on the feature suggested. Honestly, even this is more of a nice to have one; I can live without it, but it would make some common cases a little nicer.

@LikeLakers2
Copy link
Contributor

Ah, well then this idea gets my support. That splat operator is waaaaay too useful in Ruby.

@mattrobin
Copy link

The high level multiplayer rpc function already does this. Is the way it does it accessible in some way?

@anoadragon453
Copy link

Would like this to be able to implement a simple, custom logging function.

We can already do the following:

print("Score: ", score)

but it would be nice to be able to also do the following:

_log("Score: ", score)

where the output of log would produce:

[MyClass] Score: 500

@RichardEllicott
Copy link

Would like this to be able to implement a simple, custom logging function.

We can already do the following:

print("Score: ", score)

but it would be nice to be able to also do the following:

_log("Score: ", score)

where the output of log would produce:

[MyClass] Score: 500

can i plus one this... i also want to make a print function that will print normally like in python (strings and numbers etc) as i find the printing disagreeable but maybe other people like it

@Nukiloco
Copy link

I think this would be a really awesome feature in gdscript. Having the ability to pass in multiple of arguments without an array would be very helpful in cases like custom log functions!

@AlexDarigan
Copy link

AlexDarigan commented May 28, 2019

While you could argue you can get away with this as far as making a game goes (and you would be absolutely right), it would be an amazing beneficial feature for tool makers for Godot itself who want to """expose""" a flexible API to their users.

expose is in quotes because technically everything is exposed in a sense.

@Geequlim
Copy link
Contributor

I think this feature is really required as there are some functions are already varargs but we have no way to override them.

image

@menip
Copy link
Contributor

menip commented Jun 4, 2019

I'd love varargs in gdscript. Consider:

func rpc_game_info(node:Node, method:String, args:vararg):
    for id in players:
        node.rpc_id(id, method, args)

They only way I can think of implementing this currently, is copy pasting the two lines everywhere rpc_game_info would otherwise be called and supplying the method args as a comma separated list.

@rosshadden
Copy link
Contributor

rosshadden commented Jul 21, 2019

Is there at the very least a way to unroll/spread/expand an array? In other words, is there a way to get something like this working?:

func foo(bar: String, args = []):
  baz(bar, ...args)

@bojidar-bg
Copy link
Contributor

@rosshadden you can use Object::callv("method", [..args])

@alexkh
Copy link

alexkh commented Aug 6, 2019

I've been writing lots of C/C++/Js code for websites, backends, games since 2012, and I can't remember a situation where I absolutely needed to use varargs. It's a nice feature for logging debug messages, but other than that, I can't see any need for it. In fact, I've been making Godot games for more than a year now, and I'm quite happy with where gdscript now: it does everything I need and more. Instead of spending time adding extra bells and whistles to the language, I'd rather vote for improving efficiency of the existing functionality. Best regards, - Alexandre Kharlamov

@mitchcurtis
Copy link
Contributor

I've been writing lots of C/C++/Js code for websites, backends, games since 2012, and I can't remember a situation where I absolutely needed to use varargs. It's a nice feature for logging debug messages, but other than that, I can't see any need for it. In fact, I've been making Godot games for more than a year now, and I'm quite happy with where gdscript now: it does everything I need and more. Instead of spending time adding extra bells and whistles to the language, I'd rather vote for improving efficiency of the existing functionality. Best regards, - Alexandre Kharlamov

That's nice, but I'm sorry to say that your vote means nothing when it's likely that a volunteer will implement this on their own free will.

@bojidar-bg
Copy link
Contributor

@mitchcurtis Please, refrain from making comments which are not related to the issue discussed. Downplaying others does not contribute positively to the discussion.

@mitchcurtis
Copy link
Contributor

How is calling a feature that many are asking for "bells and whistles" not downplaying others? My comment is directly related to the issue at hand - it's an open source project and a lot of the commits are from contributors who choose what they want to work on.

Let's turn it around: does Alexandre's comment contribute positively to the discussion? Would it not have been better for him to find a specific feature that he was interested in and show support for that instead of downplaying features that others want?

@akien-mga
Copy link
Member

akien-mga commented Aug 7, 2019

Implementing features is not just about "who wants it" and "who can implement it". It's also important to know "who think it's not necessary (and why)", as we should avoid implementing features if we don't actually need them. They make code maintenance harder, can impact performance, reduce possibilities for optimization, etc. (especially in a scripting language).

So yes, @alexkh's feedback is an interesting one, even if you don't agree with it. Someone can come with a perfect PR for this feature tomorrow, core contributors will still need to spend quite some time thinking and debating whether this is worth adding from a technical and API design point of view.

Keeping the scope of GDScript small and easy to maintain is definitely one of the core design principles for the language. I'm not saying that this specific feature would not be a good addition, but we have to weigh the pros and cons, which implies listening to those who disagree with the proposal.

@mitchcurtis
Copy link
Contributor

Implementing features is not just about "who wants it" and "who can implement it". It's also important to know "who think it's not necessary (and why)", as we should avoid implementing features if we don't actually need them. They make code maintenance harder, can impact performance, reduce possibilities for optimization, etc. (especially in a scripting language).

So yes, @alexkh's feedback is an interesting one, even if you don't agree with it. Someone can come with a perfect PR for this feature tomorrow, core contributors will still need to spend quite some time thinking and debating whether this is worth adding from a technical and API design point of view.

Keeping the scope of GDScript small and easy to maintain is definitely one of the core design principles for the language. I'm not saying that this specific feature would not be a good addition, but we have to weigh the pros and cons, which implies listening to those who disagree with the proposal.

Fair points.

I think the amount of votes for this issues speaks for itself, but I will try to refrain from making such comments in the future.

@DamKoVosh
Copy link

DamKoVosh commented Nov 15, 2019

I've been writing lots of C/C++/Js code for websites, backends, games since 2012, and I can't remember a situation where I absolutely needed to use varargs. It's a nice feature for logging debug messages, but other than that, I can't see any need for it. In fact, I've been making Godot games for more than a year now, and I'm quite happy with where gdscript now: it does everything I need and more. Instead of spending time adding extra bells and whistles to the language, I'd rather vote for improving efficiency of the existing functionality. Best regards, - Alexandre Kharlamov

I am programming on various games, programms as well at home as on work for more than 15 years now, but only for like 1 month in godot an i can say, that i miss several features, that are already open as feature request at particular this feature. being able to accept and send variable numbers of arguments is something i need quite often and is decreasing the quality of the code dramatically if you have to work around it.

One example: => inheritance

class A
_init(arg0, arg1, arg2)

class B extends A
_init(arg0, arg1, arg2, arg4).(arg0, arg1, arg2)

Now imagine you have to change class A's argument list. You will have to find every class that inherites this class, that is dangerous. Despite the fact, that there is no named arguments, so mixing up the argument list ist a problem of itself

Another example are callbacks, i gues this goes without code ...

So my point is: godot does not everything you need yet, it just does everything that is crucial (well and of course quite some more :) ...). But it however is not yet at a point where stopping to add features would be the best case. However to be careful about what to add is a good decission.

Edit: Just realised another good example is godots own Object.call() method ;)

@alexkh
Copy link

alexkh commented Nov 22, 2019

DamKoVosh, please tell me, how many lines of code was your biggest game? Every single time I make a game I'm disappointed how few coding it requires. The bulk of the work is always the content, testing, balancing the gameplay. You are saying that rewriting is dangerous. If nothing else, rewriting your code makes you better at writing future-proof interfaces and data structures!

As stated in the first message in this thread, the whole discussion is exactly about syntactic sugar for something that can already be easily implemented using an array in place of implementing a variadic function.

@mrimvo
Copy link

mrimvo commented May 6, 2020

@alexkh

As stated in the first message in this thread, the whole discussion is exactly about syntactic sugar for something that can already be easily implemented using an array in place of implementing a variadic function.

As previously stated by Geequlim, this is not only syntactic sugar, but actually breaks the ability to override functions that use varargs, like rpc, emit_signal, ... I just ran into that issue when I tried to change rpc to my needs.

@mhilbrunner
Copy link
Member Author

mhilbrunner commented May 6, 2020

Yes, it is syntactic sugar. It being syntactic sugar doesn't mean they're good or bad, however. Control flow like if, else and even functions are only sugar on top of GOTO too if you will. That doesn't mean you don't want those.

Sometimes, adding a little syntatic sugar makes code way more readable and is worth the added complexity.

but actually breaks the ability to override functions that use varargs, like rpc, emit_signal

Curious, that those functions use varargs and not arrays. ;-) Note how the Godot API itself uses varargs in various places? There's probably a reason for that.

Also curious how many languages implement variadic functions. Maybe they are useful even if they can be "easily implemented using an array"?

I'm missing them dearly in GDScript whenever I use it, and it's one of the reasons I'm preferring C#. Or C++. Or Java. Or Python. Or Go.

Honestly, I think GDScript is the only language I've worked in that doesn't have them. Besides, maybe, Lua? Ah, I checked and they seem to exist there too. Not saying we should aim to add everything those languages have to GDScript, but if all of those have a feature in common, there may be some worth to it.

I can't judge how much complexity it would add to the GDScript backend, and thus can't say much about the complexity tradeoff, but writing them off because they're "just syntactic sugar" is wrong, because that can be said about a lot of things.

Again, note how many things in Godot use them.

@alexkh
Copy link

alexkh commented May 7, 2020

Yes, it is syntactic sugar. It being syntactic sugar doesn't mean they're good or bad, however. Control flow like if, else and even functions are only sugar on top of GOTO too if you will. That doesn't mean you don't want those.

GOTO does not replace if because it is an unconditional jump. Are you even a programmer?

but actually breaks the ability to override functions that use varargs, like rpc, emit_signal

once in a year someone somewhere will want to override rpc function. While thousands others every day are wishing to see Godot 4 released.

Also curious how many languages implement variadic functions. Maybe they are useful even if they can be "easily implemented using an array"?

I'm missing them dearly in GDScript whenever I use it, and it's one of the reasons I'm preferring C#. Or C++. Or Java. Or Python. Or Go.

C++ does not have a standard array type that can store values of different types like GDscript does. Even though C++ supports variadic functions, their use is discouraged because it is type unsafe. It's a C legacy, and in C itself it was a syntactic sugar, because printf was used a lot, especially for debugging - where you want to quickly type temporary code to output some data. It was totally justified, because it was used all the time - a real time saver! But did you ever write your own variadic function in C or C++?

Again, note how many things in Godot use them.

For debug output - by all means! But if print() was not variadic, instead of print("Hello ", "World), you'd have to type print(["Hello ", "World"]) - not a big difference at all...

@mhilbrunner
Copy link
Member Author

mhilbrunner commented May 7, 2020

GOTO does not replace if because it is an unconditional jump

Well, right. I was talking about conditional jumps, of course. Which... you probably could infer. Still, point stands: we have built higher level functionality on top to be able to convey some things more cleanly.

C++ does not have a standard array type that can store values of different types like GDscript does.

Okay, argue against Python, Lua or Go (or any host of other languages) then that have those and still have variadic functions.

But if print() was not variadic, instead of print("Hello ", "World), you'd have to type print(["Hello ", "World"]) - not a big difference at all

Sure, in that simple test case. In more complex ones, it gets uglier, especially once you start having data from multiple sources and now need to manually stuff those into an array first. I agree it's not a huge loss; still, variadic functions make for cleaner code in some cases.

But...

But did you ever write your own variadic function in C or C++?

Are you even a programmer?

As above, I don't feel like you're arguing in good faith. In which case I'm not really interested in talking to you anymore, so... no, I'm just listed as a engine contributor because I make for a good mascot, please move on.

@Spartan322
Copy link
Contributor

Spartan322 commented May 9, 2020

GOTO does not replace if because it is an unconditional jump. Are you even a programmer?

For the most part conditional statements, especially loops, are just a specialized jump statement, which is mostly the same as a goto statement, in a practical sense most basic sequence control statements you find are an extension of that. This is a foolish argument to support yourself from, (as it doesn't actually make an argument, it just argues semantics which is useless) and that second part is disrespectful.

C++ does not have a standard array type that can store values of different types like GDscript does. Even though C++ supports variadic functions, their use is discouraged because it is type unsafe. It's a C legacy, and in C itself it was a syntactic sugar, because printf was used a lot, especially for debugging - where you want to quickly type temporary code to output some data. It was totally justified, because it was used all the time - a real time saver! But did you ever write your own variadic function in C or C++?

While C++ does not have a standard array type for varargs (or untyped arrays generally) there does first exist manners to deal with this for about a decade now, (technically you could do this even before C++11 however it was very macro heavy and rather hacky) and secondly with varadic templates you can completely skip the typing problems. There are manners to deal with varargs in C++ using varadic templates. Those who still believe in varargs in C++ are probably starting from the wrong point these days.

I don't much care for the discussion personally (aside from I'd personally find it more clean and organized to have some type of array-based varadic arguments in GDScript instead of sitting in the backend, I think language features should be implemented for the language, not just its execution, but that's just me) but these comments needed to be corrected, and that aside you are acting rather rude in this case, you don't strengthen your point of view in the minds of your audience when you respond negatively to opposition that should be handled objectively like this.

@alexkh
Copy link

alexkh commented May 10, 2020

GOTO does not replace if because it is an unconditional jump. Are you even a programmer?

For the most part conditional statements, especially loops, are just a specialized jump statement, which is mostly the same as a goto statement, in a practical sense most basic sequence control statements you find are an extension of that. This is a foolish argument to support yourself from, (as it doesn't actually make an argument, it just argues semantics which is useless) and that second part is disrespectful.

K, I am disrespectful to people who waste my time. His point was: why not use GOTO instead of if, and I said that GOTO does not replace if. GOTO is not a conditional statement and if you want to replace conditional statement, just type in what exactly you want to replace it with. Any examples already?

C++ does not have a standard array type that can store values of different types like GDscript does. Even though C++ supports variadic functions, their use is discouraged because it is type unsafe. It's a C legacy, and in C itself it was a syntactic sugar, because printf was used a lot, especially for debugging - where you want to quickly type temporary code to output some data. It was totally justified, because it was used all the time - a real time saver! But did you ever write your own variadic function in C or C++?

While C++ does not have a standard array type for varargs (or untyped arrays generally) there does first exist manners to deal with this for about a decade now, (technically you could do this even before C++11 however it was very macro heavy and rather hacky) and secondly with varadic templates you can completely skip the typing problems. There are manners to deal with varargs in C++ using varadic templates. Those who still believe in varargs in C++ are probably starting from the wrong point these days.

I don't much care for the discussion personally (aside from I'd personally find it more clean and organized to have some type of array-based varadic arguments in GDScript instead of sitting in the backend, I think language features should be implemented for the language, not just its execution, but that's just me) but these comments needed to be corrected, and that aside you are acting rather rude in this case, you don't strengthen your point of view in the minds of your audience when you respond negatively to opposition that should be handled objectively like this.

K, but that's exactly my point: GDscript has a standard type that you can iterate that can hold different types in it, so you don't need to mess with all the hackery needed to get the variadic functions working in C++, and that's why, perhaps, in C++ variadic templates are justified.

@akien-mga
Copy link
Member

K, I am disrespectful to people who waste my time.

Then I'll let you waste your time on other projects as you are now blocked from interacting on @godotengine repositories for 30 days.

We have a Code of Conduct, and it definitely doesn't allow being disrespectful to anyone.

@Calinou
Copy link
Member

Calinou commented May 27, 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!

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