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
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.