MATLAB: Parsing varargin for a function called with values only instead of name-value pairs


Suppose I am writing code to maintain a bird-watching database. Each optional input to this function has a rather short list of possible options:
'bird' : 'robin', 'cardinal', 'bluejay'
'where' : 'Mendon Pond', 'Grand Canyon', 'Seattle'
'when' : 'morning', 'afternoon', 'dusk', 'evening'
Because there are only a few options for the values for each name in the varargin, it seems to me that a function call like:
add_to_database(db, 'robin', 'Grand Canyon', 'dusk');
is as clear and easy to parse as
add_to_database(db, 'bird', 'robin', 'where', 'Grand Canyon', 'when', 'dusk');
That is, when an input parser sees 'robin', it knows that it is a value for the name 'bird,' and so there is no point in passing the 'bird' name first.
1) inputParser and the contributed packages on the MATLAB Central File Exchange don't seem to be designed for this sort of input parsing… is that a correct assessment?
2) Is there a reason why contemplating parsing varargin in this way is a bad / un-MATLAB-y idea? If the dictionary of options grows over time and then the same value could be used for more than one name, then obviously the jig is up… but barring that, is there a reason that an input parser for something like this doesn't exist?

Best Answer

  • I like name-value pairs because it makes it easier to extend in the future if you need a new option. With the ability to have auto suggestions added in 18a, it makes it easier to quickly tab through them as well. So even if there's more typing, the command is clearer and order doesn't matter if you forget it; e.g:
    addBird('robin', 'when', 'dusk','where','feeder')
    addBird('eagle', 'where', 'squirrel nest', 'when', 'evening')
    For the above the inputParser would have addRequired for bird, and addParameter for when, where. Note, I'm running this in 18b where double quote "strings" are supported everywhere. Earlier releases you may need to use cellstr/char arrays.
    p = inputParser;
    p.FunctionName = 'addBird';
    p.addRequired('Bird',@(x)validateattributes(x, {'string'}, {'scalar'}));
    p.addParameter('When',"morning",@(x)validateattributes(x, {'string'}, {'scalar'}));
    p.addParameter('Where',"seattle",@(x)validateattributes(x, {'string'}, {'scalar'}));
    bird = validatestring(p.Results.Bird, ["robin","eagle","sparrow"])
    when = validatestring(p.Results.When, ["morning","dusk","evening"])
    where = validatestring(p.Results.Where, ["seattle", "feeder"])
    You can use the addOptional or addRequired options with inputParser to get the behavior you described in your post.
    Also look at validatestring() as the validator.