how to write lot of inputs in a function
이전 댓글 표시
hello i have this call for function in my main program :
[A_a,A_b,B_a,B_b,C_a,C_b]=basic_matrix_numeric(C1,C,R,R2,R_C1,R_C,R1,L1,L2,V_diode,U);
how ever as you can see there are a lot inputs , i tried to make it look better for exmaple write all the inputs in a cell like this:
values ={C1,C,R,R2,R_C1,R_C,R1,L1,L2,V_diode,U}
[A_a,A_b,B_a,B_b,C_a,C_b]=basic_matrix_numeric(values);
but as you can see i get an eror any other ideas ?
댓글 수: 1
Adam
2018년 1월 10일
Usually if you need that many inputs for a function it is a strong suggestion that you should split it into multiple functions instead, each taking a more specific set of inputs.
채택된 답변
추가 답변 (1개)
Simon Parten
2018년 1월 11일
편집: Simon Parten
2018년 1월 11일
Interestingly, I'd probably disagree with Stephen's answer here. If the function has to know about the structure of the data it's being passed, you have a leaky abstraction. At some point in the future, this is going to be rather difficult to explain to anyone else / test / make robust / debug / remember what the hell was going on.
How much this matters, depends how long lived your code is going to be, and how many other people you expect to use it ...
My personal suggestion is to pass meaningful name / value pair arguments, as a varargin, then parse and validate them using The InputParser, and set a series of sane defaults for those you don't need. This is also 'self documenting' for when you forget how it all works in the future...
function blahblah = Blaher(varargin)
p = inputParser;
p.FunctionName = 'Blaher';
p.CaseSensitive = true;
p.StructExpand = true;
addParameter(p, 'sayBlah', 'Blah' , @(x) validateattributes(x,{'char'},{'nonempty'}) );
addParameter(p, 'sayBob', 'bob' , @(x) validateattributes(x,{'char'},{'nonempty'}) );
addParameter(p, 'sayHi', 'hi' , @(x) isa(x,{'char'},{'nonempty'}) ;
addParameter(p, 'SaySo', true , @(x) validateattributes(x,{'logical'},{'nonempty'}));
p.parse(varargin{:});
this.sayBlah = p.Results.sayBlah;
this.sayBob = p.Results.sayBob;
this.sayHi = p.Results.sayHi;
this.SaySo = p.Results.SaySo;
% now say blah as appropriate.
end
댓글 수: 4
This method also has several major disadvantages, starting right from the usage of varargin. Contrary to your claim that it is "self documenting" by using varargin you create a function that does not show the input names when the function is being called:
Using named arguments shows the names when being called:

whereas using varargin shows nothing useful at all:

What you proposed is of course also slower due to using the inputParser object, which might be an important consideration in some cases. I tried using the inputparser but gave up because it ended up taking all the runtime.
In any case, the worst that can happen with a structure is an error at some line saying "non-existent field XXX" - solving this will be pretty simple for anyone with some MATLAB experience. Not that much different to what you are proposing, really, and not nearly as scary as you seem to find it.
"At some point in the future, this is going to be rather difficult to explain to anyone else..."
That is what the help is for.
Writing help is the correct way to document a function (including its inputs and outputs). The help can be displayed in the command window or in the MATLAB help dialog box, complete with links to related functions. It can be shown in when using tab completion, or by pressing f1.
Just because some inputs exist and have some numeric characteristics tells me absolutely nothing about what they are for, what units, etc.. Only by inspecting your code do I get an idea what I need to supply to that function: your concept actually just made it harder to get the information I need to use the function!
Without an actual description of the inputs it is impossible in future to know if a particular input condition is correct or not. Should x be positive? Can x be zero? There is no way to know because there is no description of what x actually represents. Do I have to depend on diving into the code and reverse engineering? Is that the "self documenting" that you were talking about?
"If the function has to know about the structure of the data it's being passed, you have a leaky abstraction"
You might like to tell that to TMW, who use structures to pass control parameters to many ODE, optimization, etc. functions.
Summary: of course what MATLAB really needs is (non-positional) named arguments.
Guillaume
2018년 1월 11일
I disagree with the disagreement :), in particular "If the function has to know about the structure of the data it's being passed, you have a leaky abstraction". The fields of the structure are parts of the function definition, it's no more leaky than positional arguments or arguments passed through inputParser.
There are however downsides to using a structure to pass a bunch of arguments:
- you get no tab completion for the field of the structure, so you have to get them from the documentation, or remember what they're called and how they are spelled. With mathworks inconsistent casing and habit of abbreviating everything, a hard task!
- if you misspell a field, a default value may be used instead and unless the function test for unused fields, you won't even know about it.
In cases like this and where speed of execution is not the priority, I use function objects (classes). When you have functions with lots of arguments, usually some of them are options that control how the function behaves. These become properties of the object. Others are inputs that change each call, these stay as inputs to the functor:
classdef myfun
properties
method char = 'linear';
direction = 1;
end
methods
function doit(this, arg)
switch(this.method)
...
end
end
end
end
You get automatic tab completion for the properties. No more guessing the spelling.
With the newish property validation of classes you may not even have to write a validation function for your properties, but if you need to, it's trivial and it goes in its own method for each property, making the code clearer.
Walter Roberson
2018년 1월 11일
"If the function has to know about the structure of the data it's being passed, you have a leaky abstraction."
That argument would suggest that one should not use object-oriented objects, since the code that processes those objects needs to know the properties and methods of the data being passed. Indeed, it is common for the implementation of object-oriented objects to be a struct.
Adam
2018년 1월 12일
I tend to avoid varargin as I have never liked it, but I have used it with 'name', 'value' pairs on some occasions, when validating a class constructor that is some parameter-holding class with defined defaults that for many properties do not need to be changed.
Where the problem is just the number of inputs rather than that some or all of them are wanted to be optional, I just name them all as individual arguments usually. I use parameter classes though so my function that is doing something won't generally take a vast number of arguments, but the construction of my parameter class may. It's just moving where the arguments are defined really.
Still, if you simply have a problem with feeling you have too many inputs to name individually then it is a strong indication that you simply have too many inputs and need to design the code differently.
I almost never use structs though, ghastly christmas tree structures that you can hang anything off and easily accidentally create new fields with typos instead of getting error messages as a class would give you.
카테고리
도움말 센터 및 File Exchange에서 Construct and Work with Object Arrays에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!