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 Comment

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.

Sign in to comment.

 Accepted Answer

Stephen23
Stephen23 on 10 Jan 2018
Edited: Stephen23 on 10 Jan 2018
"how to write lot of inputs in a function"
One robust answer: don't.
Put all of the data into one structure, and then pass that. Inside the function access the data directly from the structure. You can do the same with the output. This is usually the easiest way of passing lots of names arguments, rather than trying to rely on the fiddly positional input arguments of a function.
Or, if you really really want to keep all of those input arguments, simply use a comma-separated list:
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{:});

8 Comments

ok I tried using struct but i got an eror
values.s={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.s{:});
how ever i also get an eror
Stephen did not mean putting all variables in one field, but to use different fields:
Value.C1 = ...
Value.C = ...
Value.R = ...
etc.
Result = basic_matrix_numeric(Value);
And now Result should be replied as struct also having the fields like Result.A.a, Result.A.b etc.
With a long list of inputs it is too hard to detect swapped variables.
so you would recommend working with cells and not struc ?
Stephen23
Stephen23 on 10 Jan 2018
Edited: Stephen23 on 10 Jan 2018
@tomer polsky: neither Jan Simon nor I mentioned cell arrays, and did not recommend using them.
You should use a structure as I advised, with one field for each variable as Jan Simon showed you.
Note: accessing fields of a struct is a little slower than accessing parameters passed in. Accessing parameters passed in is one of the fastest forms of access.
@Walter: This is important, if the function is called very frequently. tomer has problems with the readability of the code already. So saving microseconds of runtime might be less important than improving the clarity of the code to save an hour of debugging.
Sorry, I know, that you know this. I mention this for the OP.
Value.C1 = ...
Value.C = ...
Value.R = ...
etc.
Result = basic_matrix_numeric(Value);
hi i tried what your saying ,how ever i get this eror : Undefined function for input arguments of type 'struct'
@tomer polsky: MATLAB does not magically convert the fields of the structure into separate input arguments, so you need to rewrite the function to:
  • accept one input argument (a structure).
  • use the fields of that structure inside the function.

Sign in to comment.

More Answers (1)

Simon Parten
Simon Parten on 11 Jan 2018
Edited: Simon Parten on 11 Jan 2018
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 Comments

Stephen23
Stephen23 on 11 Jan 2018
Edited: Stephen23 on 11 Jan 2018
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.
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.
"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.
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.

Sign in to comment.

Categories

Find more on Construct and Work with Object Arrays in Help Center and File Exchange

Asked:

on 10 Jan 2018

Commented:

on 12 Jan 2018

Community Treasure Hunt

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

Start Hunting!