Python provides the ability for any function to be called with either positional or keyword [1] arguments. Here is a particularly brutal example:
args={'a':1,'b':2,'c':3} def f(a,b,c): return (a,b,c) def g(b,c,a): return (a,b,c) for j in [f,g]: print j(1,2,3) for j in [f,g]: print j(a=1,b=2,c=3) for j in [f,g]: print j(*args.values()) for j in [f,g]: print j(**args)
I see nothing in pdd 03 that provides any guidance as to how to handle this. What makes this issue so critical is that any solution will potentially affect *every* function.
Upon sleeping on it, a potential solution came to me. There actually are multiple, related, problems: positional arguments, keyword arguments, defaults, passing arguments in a list expression, and passing arguments in a dictionary expression.
What Parrot defines is a mechanism to define and call a subroutine with a variable number of positional arguments. So, we will focus on making that subset interoperable. Everything else is - by definition - Python specific.
When compiling the function itself, you know the names, positions, number of arguments, and any defaults that may be provided. Functions, themselves, are PMCs, so names a defaults can be stashed into properties. Code to check the number of actual parameters and to fill in missing ones with defaults will need to be emitted. Net cost: a small one time cost of saving keywords in all cases, and a small overhead for defaults that only occur when they are actually defined and/or used.
When compiling a call to a function, you know the number and positions of the actual arguments, as well as optionally a set of keyword and expresions. If only positional arguments are used, then Parrot standard calling conventions are to be used, and everything just works, including defaults.
If keyword arguments are used, then a completely separate interface is required. This will be provided by the __call__ method, which takes two arguments: a list of arguments and a dictionary of keyword/value pairs. The __call__ method can enforce all of the python semantics for binding arguments.
The merits to this approach is that interoperability and performance are only impacted to the extext that given features are used.
- - -
Comments welcome. The question Parrot needs to answer is whether keyword arguments should be a part of the interoperable core (register P4 looks very tempting ;-)), or are a language specific extension.
- Sam Ruby