Handling Umnatched Arguments with Function Argument Validation
古いコメントを表示
My goal is to understand how to capture and passthrough name-value arguments that are not strictly defined in an agruments block, but that I would want to fall through/repass to a inner function call. For those familar with python I'm trying to understand how to get a functionality similar to the syntax def foo(..., **kwargs):; where kwargs holds any "extra" name-value arguments that are not explicitly described in the function definition.
Here's an example of a relavent implemantation case done with the inputParser. With my question being: How do I make this work in a robust way with arguments block syntax?
inputParser implementation
% fancyAverage.m
function output = fancyAverage(varargin)
ip = inputParser();
ip.KeepUnmatched = true;
ip.addRequired('X');
ip.addParameter('Weights', []);
ip.parse(varargin{:});
inputs = ip.Results;
disp('`fancyAverage` parsed inputs:')
disp(inputs)
x = inputs.X;
if ~isreal(inputs.X)
output = fancyAverageComplex(varargin{:});
return
end
if isempty(inputs.Weights)
w = 1;
else
w = inputs.Weights;
end
output = mean(w .* x);
end
function output = fancyAverageComplex(varargin)
ip = inputParser();
ip.addRequired('X');
ip.addParameter('Weights', []);
ip.addParameter('ImWeights', []);
ip.addParameter('DoAverageAbsoluteVal', false);
ip.parse(varargin{:});
inputs = ip.Results;
disp('`fancyAverageComplex` parsed inputs:')
disp(inputs)
x = inputs.X;
if isempty(inputs.Weights)
xWeighted = x;
else
w = inputs.Weights;
if isempty(inputs.ImWeights)
xWeighted = w .* x;
else
iw = inputs.ImWeights;
xWeighted = (w .* real(x)) + 1i * (iw .* imag(x));
end
end
if inputs.DoAverageAbsoluteVal
xWeighted = abs(xWeighted);
end
output = mean(xWeighted);
end
Evaluations
%{
>> fancyAverage([1, 10])
`fancyAverage` parsed inputs:
Weights: []
X: [1 10]
ans =
5.5000
>> fancyAverage([1, 10], 'Weights', [10, 1])
`fancyAverage` parsed inputs:
Weights: [10 1]
X: [1 10]
ans =
10
>> fancyAverage([1 + 1i, 10 + 10i])
`fancyAverage` parsed inputs:
Weights: []
X: [1.0000 + 1.0000i 10.0000 +10.0000i]
`fancyAverageComplex` parsed inputs:
DoAverageAbsoluteVal: 0
ImWeights: []
Weights: []
X: [1.0000 + 1.0000i 10.0000 +10.0000i]
ans =
5.5000 + 5.5000i
>> fancyAverage([1 + 1i, 10 + 10i], 'Weights', [10, 1], 'ImWeights', [1, 1])
`fancyAverage` parsed inputs:
Weights: [10 1]
X: [1.0000 + 1.0000i 10.0000 +10.0000i]
`fancyAverageComplex` parsed inputs:
DoAverageAbsoluteVal: 0
ImWeights: [1 1]
Weights: [10 1]
X: [1.0000 + 1.0000i 10.0000 +10.0000i]
ans =
10.0000 + 5.5000i
%}
How to implement this with the arguments block syntax? Maybe the following:
arguments implementation
% fancyAverage_2.m
function output = fancyAverage_2(x, nvInputs, varargin)
arguments
x
nvInputs.Weights = []
end
arguments (Repeating)
varargin
end
disp('`fancyAverage` name-value inputs:')
disp(nvInputs)
if ~isreal(x)
nvInputsCell = namedargs2cell(nvInputs);
output = fancyAverageComplex_2(x, nvInputsCell{:}, varargin{:});
return
end
% ...
end
function output = fancyAverageComplex_2(x, nvInputs)
arguments
x
nvInputs.Weights = []
nvInputs.ImWeights = []
nvInputs.DoAverageAbsoluteVal = false
end
disp('`fancyAverageComplex` name-value inputs:')
disp(nvInputs)
% ...
end
Evaluations
%{
>> fancyAverage_2([1 + 1i, 10 + 10i], 'Weights', [10, 1], 'ImWeights', [1, 1])
File: fancyAverage_2.m Line: 15 Column: 4
Function argument definition error in fancyAverage_2. Functions with positional
and name-value arguments must define positional arguments first.
%}
This evaluation leads to an error because varargin is interpreted as a positional argument which gets defined after the name-value argument (which is not allowed). I do understand that it would be possible to define the name-value arguments of the called function in the calling function's arguments block; however this seems a bit unmaintainable/hacky to me. I am wondering if there is a better way to do this.
Extending to Positional Arguments
Further it seems that neither the inputParser syntax or the arguments syntax can handle capturing unmatched optional positional arguments. I guess this part of my submission is more of a feature request; however I'd like to be able to do something along the lines of:
% fancyAverage_3.m
function output = fancyAverage_3(x, weights, varPosArgIn, varNamedArgIn)
arguments
x
weights = []
end
arguments (PositionalUnmatched)
varPosArgIn
end
arguments (NamedUnmatched)
varNamedArgIn
end
if ~isreal(x)
varArgInputsCell = [varPosArgIn, namedargs2cell(varNamedArgIn)];
output = fancyAverageComplex_3(x, weights, varArgInputsCell{:});
return
end
% ...
end
function output = fancyAverageComplex_3(x, weights, imWeights, nvInputs)
arguments
x
weights = []
imweights = []
nvInputs.DoAverageAbsoluteVal = false
end
% ...
end
Please let me know your thoughts or any existing work-arounds that I might have missed.
採用された回答
その他の回答 (0 件)
カテゴリ
ヘルプ センター および File Exchange で Argument Definitions についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!