godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add a method to get a Callable's argument count #8596

Closed dugramen closed 8 months ago

dugramen commented 11 months ago

Describe the project you are working on

Editor plugins

Describe the problem or limitation you are having in your project

Callable.unbind() allows unbinding a number of arguments, but there is no way to dynamically know how many arguments are allowed/should be unbound

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

A new method on Callable, called get_argument_count() or get_allowed_arguments_count() that returns the number of arguments allowed by the callable

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

Here are 2 example usages:

To unbind some unknown Callable for a signal:

signal.connect(callable.unbind(callable.get_bound_arguments_count() - callable.get_allowed_arguments_count()))

Example of a reusable, JavaScript style, array mapper. Only possible if this is implemented (optional index and array)

class_name Utility 
static func map(arr: Array, callable: Callable):
    var result := []
    for (i = 0; i < arr.size(); i += 1):
        result.push_back(
            callable.callv(
                [arr[i], i, arr].slice(0, callable.get_allowed_argument_count())
            )
        )
    return result 

Which could be used like so:

Utility.map(
    [1, 2, 3],
    func(num): return num * 2
)
Utility.map(
    [0, 5, 10],
    func(num, i): return str(i) + ": " str(num)
)
Utility.map(
    [8, 15, 11],
    func(num, i, arr): return num / arr.size()
)

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

It's only possible with known Callables, but it's not currently possible to implement something like the above utility function

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

I don't think an add-on can do this

IntangibleMatter commented 10 months ago

Commenting to boost this, I need to be able to get this data and more about arbitrary callable's signatures.

AThousandShips commented 10 months ago

@IntangibleMatter Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

AThousandShips commented 10 months ago

Will take a look at possibly implementing this, will see how it goes

AThousandShips commented 9 months ago

Made quite a bit of progress, will probably open a PR soon

ThaddeusWilliams commented 7 months ago

This is already possible with the following code:

func GetMethodArgCount(m: Callable):
    for f in get_method_list():
        var fn = get(f.name)
        if m.get_method() == f.name:
            return f.args.size()
    return 0
AThousandShips commented 7 months ago

That doesn't cover everything, you can't use it for lambdas or for example, also it doesn't matter now since this has been added as a feature so you can just use the method