Skip to content

Configurable: Support positional only arguments #61

@boeddeker

Description

@boeddeker

At the moment is any callable a configurable, when it supports key value arguments.
While this is verbose and most factories and classes are supported, there are a few we don't support.

Maybe the most relevant example for padertorch is torch.nn.Sequential(*args).
To use this class, at the moment we have to use a wrapper around that class.
A native support would be nice.

In a small group, we discussed this offline, but haven't found the solution, that we want to realize.

First priority is, that the implementation is no breaking change, so all examples that follow, won't break current configs.

Here some examples, how it could be realized:

First, lets assume, we have these factories:

def foo(*numbers):
    ...
def bar(a, b, \):  # positional only, like operator.add
    ...

and we want to call them as

foo(1, 2)
bar(1, 2)

now follow some ideas, how the config could look like:

1. Reserved keyword 'args', 'factory_args' or '*'

{'factory': 'foo', 'args': [1, 2]}
{'factory': 'bar', 'args': [1, 2]}
{'factory': 'foo', '*': [1, 2]}
{'factory': 'bar', '*': [1, 2]}

2. Signature check with "assignment"

Ignore that the arguments is a positional only in the config and simply do an assignment style in the config.
In the implementation, we then to the mapping to the positional argument.

{'factory': 'foo', 'numbers': [1, 2]}
{'factory': 'bar', a=1, b=2]}
{'factory': 'foo', '*numbers': [1, 2]}
{'factory': 'bar', a=1, b=2]}

3. Lisp style

The factory can be a list, the first argument is then the function, while the others are the arguments:

{'factory': ['foo', 1, 2]}
{'factory': ['foo', 1, 2]}

My opinion

The 2. is nice for positional only arguments like operator.add.
But this rarely happen in practice, because it was only supported for C and C++ functions until py37 (PEP 570).
For *args I don't like it. It looks strange and is not robust against renaming.

For the first my favorite key would be args, but it could happen, that someone uses args as normal keyword:

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
scipy.optimize.minimize_scalar(fun, bracket=None, bounds=None, args=(), method='brent', tol=None, options=None)[source]

We didn't find a relevant example, but it would be better to prevent the conflict.

At the moment I am unsure, if I like {'factory': ['foo', 1, 2]} or {'factory': 'foo', '*'=[1, 2]} more.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions