-
Notifications
You must be signed in to change notification settings - Fork 463
Argument handling
MathWorks have evolved the way they handle optional parameters. It used to be additional parameters to the function and handled by varargin
and nargin
. It was often difficult to remember the order and meaning of additional parameters.
They later standardised on keyword-value pairs, where the keyword is a string. For example:
plot(x, y, 'Color', 'red', 'LineWidth', 2)
where the keyword is a character array (single quotes) or a string (double quotes).
Code support in MATLAB was originally quite sketchy but from 2007 there is inputParser
which is a bit like Python's argparse
for command line arguments.
Since their support was sketchy I wrote tb_optparse
to do the job, but it's not strict about keyword-value pairs. In addition it lets you handle keyword-only options like:
R = rotx(30, 'deg')
that can have a negative form like:
R = rotx(30, 'nodeg')
or enum like form
R = rpy2r(angles, 'xyz')
R = rpy2r(angles, 'zyx')
Full details are given at the end of this page. The arguments and their defaults are expressed quite concisely using a MATLAB struct.
Python allows both positional or keyword based arguments, and distinguishes between the two. Consider the case of Link
. Using just positional arguments it would be
Link(0, 1, 2, 3)
which makes it difficult for the reader to know what's going on. It also makes it difficult to handle defaults.
Using keyword-value arguments, in MATLAB or Python, would be:
Link('d', 0, 'theta', 1, 'alpha', 2, 'a', 3)
which is easy to read, but a bit cumbersome to write. For MATLAB tb_optparse
makes it easy to handle the arguments.
function Link(varargin)
opt.d = 0
opt.theta = 0
opt.alpha = 0
opt.a = 0
opt = tb_optparse(opt, varargin)
and for Python we could convert the argument into a list of keyword-value tuples by:
def Link(*pos):
kwval = [(pos[i], pos[i+1]) for i in range(0, len(pos), 2)]
and then process the tuples.
The Pythonic way would be to use named arguments
Link(d=0, theta=1, alpha=2, a=3)
We could handle both keyword-value and named arguments with a signature like
def Link(*pos, d=0, theta=0, a=0, alpha=0):
but it would require a lot of logic to work out which types of arguments are being passed, to handle malformed or mixed parameter specifications etc.
We need to make a decision on RTB-M compatibility (a good thing) with ugly code and non-Pythonic expression.
We should decide this relatively early. Do we:
- cut the cord
- keep the cord for a few select functions, but then what's the algorithm to choose those?
- keep compatibility for all functions
- in the spirit of 2to3 do we make the mother of all
awk
scripts to do this for users
Consider a class MyClass
which mimics some class in MATLAB but has Pythonic keyword arguments. We could create a MATLAB compatible version of this from a matlab
package which defines the same class but with MATLAB style arguments
matlab/MyClass.py
:
import MyClass as mc
class MyClass
def __init__(self, *varargs):
# parse the arguments in varargs to a dict kwargs
self.pythonic = mc.MyClass(**wkargs)
def method1(self, *varargs):
# parse the arguments in varargs to a dict kwargs
return self.pythonic.method1(**wkargs)
We could probably also do something funky with decorators...
% The software pattern is:
%
% function myFunction(a, b, c, varargin)
% opt.foo = false;
% opt.bar = true;
% opt.blah = [];
% opt.stuff = {};
% opt.choose = {'this', 'that', 'other'};
% opt.select = {'#no', '#yes'};
% opt.old = '@foo';
% opt = tb_optparse(opt, varargin);
%
% Optional arguments to the function behave as follows:
% 'foo' sets opt.foo := true
% 'nobar' sets opt.foo := false
% 'blah', 3 sets opt.blah := 3
% 'blah',{x,y} sets opt.blah := {x,y}
% 'that' sets opt.choose := 'that'
% 'yes' sets opt.select := 2 (the second element)
% 'stuff', 5 sets opt.stuff to {5}
% 'stuff', {'k',3} sets opt.stuff to {'k',3}
% 'old' synonym, is the same as the option foo
- Frequently asked questions (FAQ)
- Documentation Style Guide
- Typing Style Guide
- Background
- Key concepts
- Introduction to robot and link classes
- Working with Jupyter
- Working from the command line
- What about Simulink?
- How to contribute
- Common Issues
- Contributors