I have a matlab function like:
function [f, fdx] = twice(x)
f = x * 2;
if nargout > 1
fdx = 2;
end
end
I want to call this function from another function, keeping the optional second-argument semantics. However, this is messy:
function [g, gdx] = twiceplusinverse(x)
% this starts to get messy if the arguments to double are long
if nargout > 1
[f, fdx] = twice(x);
else
f = double(x)
end
g = f + 1/x;
if narargout > 1
gdx = fdx + -1/x^2;
end
end
How can I avoid duplicating every function call that has multiple return values? What's a way to write the following that doesn't violate DRY?
if nargout > 1
[f, fda, fdb, fdc] = longfunction(some_func_producing_a(), b, another_func_for_c());
else
f = longfunction(somefunc_like_above(), b, another_func_for_c());
end
You can use varargout as the output of your function and then use a comma-separated list to assign the outputs of the other function. Since you use 1:nargout as the indices in the comma-separated list, the number of output arguments requested from your function will be passed onto the other function automatically.
function varargout = myfunc(x)
[varargout{1:nargout}] = other_func(x);
end
Related
I am writing a function and I need some help.
This is my function:
function [varargout] = myfunc(x, y, z, optional)
There are two possible outputs: A and B. By setting the compulsory input variables (x,y,z), you get A. If you also set the optional argument, you should get A and B as well.
So, this is the way I am trying to do it:
if (nargin == 4)
varargout{1} = A;
varargout{2} = B;
else
varargout{1} = A;
end
This is not working... Where am I making the mistake?
Thank you in advance!
I don't see a problem with it. The only problem will come if you attempt:
[a,b] = myfunc(1,2,3)
in which case your function will complain that you're trying to assign to a second variable that hasn't been defined. So you need to have some more input / output checking (e.g. via nargout) and act accordingly. (i.e. either specify a custom error, or return b=[], etc.
PS. I'm assuming your function is defined something like:
function varargout = myfunc(x, y, z, optional)
if (nargin == 4); varargout{1} = 1; varargout{2} = 2;
else varargout{1} = 1;
end
end
You need two outputs with varargout. Try this:
[A,varargout] = myfunc(x, y, z, optional)
and
if (nargin > 3)
varargout{1} = B;
end
There are a couple of issues with this code:
First, you haven't put the keyword "function" before declaring
myfunc.
Second, optional is set as the 4th argument. However, this way you
cannot include more than 4 arguments.
Third, you have to be careful with varargout, since it increases the
number of output argument, but it doesn't change the first one
(which is always equal to one).
I don't know which of the above was your main concern, however, the following code should be working:
function varargout = myfunc2(x, y, z, varargin)
if nargin == 4
varargout{1} = 1; % where A=1 and B = 2
varargout{2} = 2;
else
varargout{1} = 1;
end
end
Please have a look to the attached links for more details about varargin and varargout:
http://uk.mathworks.com/help/matlab/ref/varargin.html
http://uk.mathworks.com/help/matlab/ref/varargout.html
I solved it! I'll post here the solution, it could be useful for others. Thank you all!
function [A, varargout] = myfunc(x, y, z, optional)
A = somefunction(x,y,z)
if nargout == 2 && nargin == 4
i = find(A > optional);
B = somefunction(A,i);
varargout{1} = B;
end
In this way, you have an optional output associated to an optional input variable. It works :)
Let A be the following matrix:
1 3
2 4
if I call the lu( ) function and save the return values like this:
[L, U] = lu(A);
MATLAB returns L, U such that L * U = A:
>> L * U
ans =
1 3
2 4
While when I save the return values like this:
[L, U, P] = lu(A);
L * U is not equal to A:
>> L * U
ans =
2 4
1 3
because lu( ) returns L, U, P such that L * U = P * A
My questions:
How can the lu( ) function know how many return parameters I have asked for?
Can I replicate this behavior in my code?
You can use the nargout function to detect how many output arguments have been requested.
In addition, you can use varargout to fill your argument list appropriately.
For example:
function varargout = myfun(a,b)
switch nargout
case 1
varargout{1} = a;
case 2
varargout{1} = b;
varargout{2} = a;
end
end
When called with one output argument, the first (and only) output will be a. When called with two, the first will be b, the second a.
You can also use nargoutchk (or in older versions nargchk) to assert that the number of output arguments requested is within specified limits.
lu does something similar to this, but is implemented in compiled C rather than MATLAB.
Yes, this can be replicated using varargout. Similarly you can use varargin if you want variable number of inputs.
function varargout = my_fun(a,b,c);
varargout{1} = b;
varargout{2} = c;
varargout{3} = a;
end
Now, this function can be called
x = my_fun(1,2,3)
x = 2
[x, y] = my_fun(1,2,3)
x = 2
y = 3
[x, y, z] = my_fun(1,2,3)
x = 2
y = 3
z = 1
As Sam Roberts points out, this does not help you create a function that behaves differently for different numbers of outputs. If that's what you want, you should check out nargout in combination with a switch-statement. Similarly, you can use nargin if you want to alter the behavior depending on the number of input variables. Please check out Sam Roberts' answer to see how this can be done.
Is there a built-in way to automatically propagate the nargout of a calling function to the called function? (Or some for a called function to figure out the nargout of the calling function?)
For example, say that
% foo.m
function [X, Y] = foo()
[X, Y] = bar();
end
and
% bar.m
function [X, Y] = bar()
X = 1;
if upstream_nargout() < 2
Y = 0;
else
Y = big_nasty_time_consuming_monster();
end
end
Of course, one could always define foo like this
% foo.m
function [X, Y] = foo()
if nargout < 2
X = bar();
else
[X, Y] = bar();
end
end
...or define bar with an extra argument to carry the caller's nargout, but I'm wondering if there's a reasonable way to achieve the same effect without resorting to this.
varargout and nargout works as follows:
% foo.m
function varargout = foo()
[varargout{1:nargout}] = bar();
end
% bar.m
function varargout = bar()
varargout{1} = 1;
if nargout > 1,
fprintf('bar: computing second output\n');
varargout{2} = rand(); % OR big_nasty_time_consuming_monster();
end
end
Then:
>> X = foo
X =
1
>> [X,Y] = foo
bar: computing second output
X =
1
Y =
0.5647
NOTE: The version of foo in the question following "Of course, one could always define foo like this" would certainly work, but this alternative allows you to have a single line in foo calling bar, rather than another if/else. That was the point of the question as I read it.
I don't see any reason to propagate the callers nargout, this should match your requirements:
function [X, Y] = foo()
if nargout < 2
X = bar();
else
[X, Y] = bar();
end
end
.
function [X, Y] = bar()
X = 1;
if nargout < 2
Y = 0;
else
Y = big_nasty_time_consuming_monster();
end
end
If you really need the calles nargout use evalin('caller','nargout'), but I would never combine nargin/nargout with evalin('caller', you can easily produce code which is impossible to debug.
I have a function
function toto(a,b)
[out,~] = evalc(a)
% here I would like to call another function
myFunc(x,y,file);
end
How could I pass this function as args to toto function as sometimes I want to call toto(a,b) and some other times toto(a,b,#()myFunc(x,y) ?
(Answer before question edit: assumes fixed number of inputs to toto)
If you want to call an arbitrary function from within function toto: first define a handle to that function:
f = #myFunc;
and then pass that handle as input argument to toto, so that you can use it within toto:
function toto(a,b,f)
[out,~] = evalc(a)
f(x,y,file); %// call function whose handle is f
end
Define your function with an input to pass a function handle:
function toto(a,b,fun)
...
% You must know how many inputs and outputs to expect
% but nargin and nargout do work for function handles
% so you can handle different cases if needed.
[y1,y2,...] = fun(x1,x2,...);
...
Call the function and pass in a handle to the function:
toto(a,b,#FunName)
Or:
FunHandle = #FunName;
toto(a,b,FunHandle)
You can pass in additional parameters by using an anonymous function:
Param = 'FileName';
AnonFunHandle = #(x1,x2)FunName(x1,x2,Param);
toto(a,b,AnonFunHandle)
If you want to be able to use both the toto(a,b) and toto(a,b,f) or similar function calls, you need to use varargin and nargin (and their output counterparts). Here is a very basic example; it ignores any more than two outputs or any more than three inputs, and does not do any input checking etc.
function [vargout] = toto(a,b,varargin)
if nargin >2
func = vargin{1};
fout = func(a,b);
else
fout = [] % if no third argument is given returns empty
end
if nargout > 0
varargout{1} = a+b;
end
if nargout > 1
varargout{2} = fout;
end
end
So for example you can call this as x = toto(2,3) (returns x = 5), [x y] = toto(2,3) (returns x = 5, y = []), [x y] = toto(2,3,#(x,y)(x*y)) (returns x = 5, y = 6).
The syntax for nlfilter in MATLAB is:
B = nlfilter(A, [m n], fun)
I am considering creating a M-File with several subfunctions to be called using test function here; i.e., I wanted a choice such that each time I can choose what subfunction gets called under fun.
% Main Function
function test
B = nlfilter(A, [m n], fun)
% Subfunction 1
function sub1
.......
% Subfunction 2
function sub2
.......
% Subfunction 3
function sub3
.......
Will it be possible to generalize fun in such a way that I can call either sub1 or sub2 or sub3 from test.
EDIT
My function:
function funct(subfn)
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
fh = {#dirvar,#diagvar};
feval(fh{subfn});
A = nlfilter(I, [7 7], subfn);
% Subfunction
function [h] = dirvar(I)
c = (size(I)+1)/2
EW = I(c(1),c(2):end)
h = length(EW) - ld
end
% Subfunction
function [h] = diagvar(I)
c = (size(I)+1)/2
NE = diag(I(c(1):-1:1,c(2):end))
h = length(NE) - ld
end
end
When I run funct(1) now this is the output with error:
Enter the lag = 1
ld =
1
??? Input argument "I" is undefined.
Error in ==> funct>dirvar at 12
c = (size(I)+1)/2
Error in ==> funct at 6
feval(fh{subfn});
I am puzzled as to what is the problem now?
If you know the name of the subfunction, you can use str2func:
Change the test function to accept a string which holds the subfunction name:
function test (subfunNm)
And call nlfilter like this:
B = nlfilter(A, [m n], str2func (subfunNm));
Now you can call test:
test ('sub1')
etc.
EDIT
In the case of nested functions, you can hold a cell array of the function handles, and pass in an index (instead of a string):
function test(fnInd)
fh = {#f1,#f2,#f3};
feval(fh{fnInd});
function f1
disp('f1')
end
function f2
disp('f2')
end
function f3
disp('f3')
end
end
And call it using test (1) etc.
Take a look at str2func and/or function handles.
I'd personally stay away from strings to pass functions, but you might just need to use that.