I've been writing a lot of functions lately. I like allowing the user to declare options in my functions using name-value pairs, but I have not found a good clean method of interpreting varargin. Here are two methods I tend to use, but both feel a bit clunky:
% Method 1:
for k = 1:length(varargin)
if strcmpi(varargin{k},'fontname')
fontname = varargin{k+1};
varargin{k+1}=[];
varargin{k}=[];
end
end
% Method 2:
nk = 1:length(varargin);
for k = 1:length(varargin)
if strcmpi(varargin{k},'fontsize')
fontsize = varargin{k+1};
nk(k:k+1) = [];
end
end
varargin = varargin(nk);
Is there a better standard procedure for interpreting a list of varargin arguments?

 채택된 답변

Sean de Wolski
Sean de Wolski 2014년 5월 1일

3 개 추천

Yes... Use inputParser

댓글 수: 8

Justin
Justin 2014년 5월 1일
Nice, I didn't know that existed :) Thanks
It looks a little heavy if the input is validated before being passed to the function but if the function is independent or in a class it would be great to use.
Sean de Wolski
Sean de Wolski 2014년 5월 1일
You don't need to use it to validate. But if you're validating beforehand, why not use it for that too?
Justin
Justin 2014년 5월 1일
편집: Justin 2014년 5월 1일
I was thinking about a function that grabs some data and calls multiple other functions based on everything it got (maybe a database monitoring some activities and their output/status). When it first grabs the data I would validate and clean everything all at once so all the functions that are called don't have to worry about it.
Sean de Wolski
Sean de Wolski 2014년 5월 1일
If I was designing those other functions, every input location would be hardwired since the functions calling them should know how to use them. Thus no need for flexible name/value pairs (more of an interactive interface).
Justin
Justin 2014년 5월 1일
A specific instance I was thinking was when I would actually pass a set of table headers to the called functions (fun1(a, b, list{:}) ), and each table wasn't guaranteed to have the same values. The functions would generate notifications, reports, logs, and other stuff.
It worked out to be a pretty good solution to make the function react to the data available so any changes were automatically handled. More importantly it saved lots of coding time and most importantly it looked pretty slick ;)
well not as slick but you could have used a switch case statement that would check the varargin against the list of parameters you coded and call functions from there.
function ARGout = varargin_TEST(varargin)
for i =1:length(varargin)
switch cell2mat(varargin(i))
case 'bold'
n='set font stuff to bold function'
case 'ital'
n='do stuff here '
otherwise
n='dunno what to put here'
end
end
Sean: the inputParser looks promising, especially for a long list of possible inputs. If I were using it to get font name and size from a list of varargin it'd look like this :
p = inputParser;
defaultFontSize = 12;
defaultFont = 'times';
addParamValue(p,'font',defaultFont,@ischar);
addParamValue(p,'fontsize',defaultFontSize,@isnumeric);
parse(p,varargin{:});
font = p.Results.font;
fontsize = p.Results.fontsize;
Above I've used addParamValue instead of the recommended addParameter because R2012b does not recognize addParameter. Now, is there a way to keep track of which varargin arguments have been evaluated? In the original post I had lines that delete names and values from varargin because at the end of the function sometimes I like to put all the leftover varargin arguments into a function. For example,
function [h] = myfunction( varargin )
% Parse inputs:
p = inputParser;
defaultFontSize = 12;
defaultFont = 'times';
addParamValue(p,'font',defaultFont,@ischar);
addParamValue(p,'fontsize',defaultFontSize,@isnumeric);
parse(p,varargin{:});
font = p.Results.font;
fontsize = p.Results.fontsize;
% use leftover varargin:
h = plot(1:10,11:20,varargin{:});
text(5,14,'this is my text','fontsize',fontsize)
end
The function above does not work, but it's a design that I would like to get to work. I'd like to let the user create some plot with any plot options and format the text with a command like
myfunction('linewidth',5,'fontsize',30)
Cedric
Cedric 2014년 5월 2일
편집: Cedric 2014년 5월 2일
Hi Chad, almost there, look at the KeepUnmatched and Unmatched properties of the parser. You might also be interested in functions fieldnames and struct2cell if you want to build a comma separated list for passing unmatched param/values further.

댓글을 달려면 로그인하십시오.

추가 답변 (3개)

Kevin Schroeder
Kevin Schroeder 2021년 7월 20일

2 개 추천

If it is of any value to others, I have always used a switch case nested in a for loop.
function myFunction(varargin)
for setting = 1:2:nargin
switch varargin{setting}
case 'SettingName1'
value = varargin{setting + 1}
[]; %do stuff with value
case 'SettingName2'
value = varargin{setting + 1}
[]; %do stuff with value
case 'SettingName3'
value = varargin{setting + 1}
[]; %do stuff with value
otherwise
[];
end
end
end
Functionally it should be similar to the nested if statements, but it looks much cleaner.
Justin
Justin 2014년 5월 1일

0 개 추천

I'm always a fan of cellfun.
inputExist = find(cellfun(@(x) strcmpi(x, 'fontname') , varargin));
if inputExist
fontsize = varargin{inputExist+1};
end
I have used this or something similar before. You can wrap this in a for loop that goes through your expected inputs and instead of assigning them directly to fontsize you could assign it to a structure like:
inputs.(currentName) = varargin{inputExist+1};
Let me know if that makes sense.

댓글 수: 1

Cedric
Cedric 2014년 5월 2일
편집: Cedric 2014년 5월 2일
STRCMPI does work on cell arrays, so there is no need to use CELLFUN. Yet, it is likely not to be suited here, because Chad would have to test for all possible parameter names for both the function and the internal function. Using the parser and its Unmachted property is more flexible for this reason.

댓글을 달려면 로그인하십시오.

Alexander
Alexander 2016년 7월 17일

0 개 추천

Dont use inputParser if you need to codegen - it is not supported in R2016a.

댓글 수: 1

Sean de Wolski
Sean de Wolski 2016년 7월 19일
With codegen, you won't be using variable number of inputs since everything needs to be defined.

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Argument Definitions에 대해 자세히 알아보기

태그

질문:

2014년 5월 1일

답변:

2021년 7월 20일

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by