Call function inside another function - matlab

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).

Related

Forwarding varargout in matlab non-verbosely

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

Matlab optional input and output arguments in a function

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 :)

Matlab coder fzero function

I am trying to convert a MATLAB code to C code using "MATLAB Coder", but anonymous functions are not allowed.
How can I convert for example an fzero function as
myfun = #(x,c) cos(c*x); % parameterized function
c = 2; % parameter
fun = #(x) myfun(x,c); % function of x alone
x = fzero(fun,0.1)
into a normal function, for instance, to convert the whole code to C.
You have "anonymous" functions, not "undefined" functions, just to clear up the terminology.
To convert the following to a named function:
myfun = #(x,c) cos(c*x); % parameterized function
write this:
function result = myfun(x,c)
result = cos(c*x);
end
For the second function, write this:
function result = myfun2(x)
c = 2;
result = cos(c*x);
end
Finally, call fzero like this:
x = fzero(#myfun2, 0.1);

How to terminate a function without 'Output argument "varargout" not assigned 'error?

I have a function with a variable number of arguments and outputs, and I want it to exit at a certain point if there is an additional argument:
function [out, varargout] = myfunction(a,varargin)
% do stuff
out = 1;
if nargin > 1
return
end
% do extra stuff if there is no additional argument
varargout{1} = 'optional output';
end
I get the error
Output argument "varargout" not assigned during call to "C:\...\myfunction"
How can I solve this?
How about something like this?
function varargout = my_function(a,varargin)
% do stuff
varargout{1} = 1;
if nargin > 1
if nargout > 1
varargout(2:nargout) = {[]};
end
return
end
% do extra stuff if there is no additional argument
varargout{2} = 'optional output';
end
Test:
[a b] = my_function(2)
a =
1
b =
optional output
[a b] = my_function(2,3)
a =
1
b =
[]
The problem is, you can't call a function with more outputs than it creates. Therefore, calling you original function a = my_function(2,3) would work fine, while [a b] = my_function(2,3) will cause an error.
Thus you have (at least) two alternatives:
Make sure the number of output and input variables match every time you execute the function.
Do as I did above.

nlfilter: Choosing nested subfunctions?

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.

Categories