Passing a function as argument to another function - matlab

I see a function passing like
sigma = 3*e-2
svmTrain(...,#(X,y)gaussianKernel(X,y,sigma),...);
What is going on with such a function passing, would someone explain ?

The syntax #(X,y) gaussianKernel(X, y, sigma) creates an anonymous function by binding the third argument of this existing function guassianKernel(X, y, s) to specifically be the value sigma.
If you inspect the svmTrain function signature, you'll see that it allows passing in a function, which is where this anonymous function is going.

Two things happen here:
First is function passing. For example, you had a function foo in your code, and you want to pass it as a parameter. In this case, you use # operator.
function MainScript
goo(#foo);
end
function goo(fHandle)
fHandle();
end
function foo
disp('Hello world!');
end
The second is anonymous functions. Anonymous function is a function much like every other function, except that it is defined at runtime, it has no name, and it binds to itself a local copy of variables that are passed to it. (For more information, see Closure). For example:
function MainScript
foo = #() (disp('Hello world!'));
goo(#foo);
end

Related

Passing names of functions to another function with parameters as input in MATLAB

Problem Statement: I am trying to write MATLAB code for a main caller function (like run_experiment below) to specify which computations I want to execute where computations are made sequentially using other MATLAB functions. Those other functions are to be evaluated based on parameters passed with the main caller function. The said functions used in computations are to be specified with name of the scripts they are written in.
Example Desired Code Behavior: For example, a command like the following should run the preprocess_data, initialise_model and train_model scripts.
>> run_experiment('dataset_1_options', '|preprocess_data|initialise_model|train_model|');
And this command should run only the train_model script but also evaluates its performance:
>> run_experiment('dataset_1_options', '|train_model|evaluate_model|');
In the above examples "|" is used as a delimiter to specify separate function names to be evaluated. Those functions use the options specified with dataset_1_options. Please do not focus on how to separate that part of the input into meaningful function names; I know how to do it with strsplit.
Constraints and Specifications: The function names to be passed as input to the main caller function are NOT anonymous functions. The purpose is to be able to pass such multiple function names as input AND to evaluate them with the options like the above example. They return output to be evaluated in other parts of the research code (i.e. passing data matrices to other functions within the research code as results of the computations carried out within them.)
Question: Given the desired behavior and constraints mentioned above, can anybody help in how to pass the separate function names from another caller function along with options/parameter to those functions? How should the main caller function evaluate the function names passed in as input with the options specified during the call?
Thank you in advance.
You can pass functions to functions in matlab. You just need to use the # sign when you pass it. In your case it would be run_experiment('dataset_1_options', #train_model) inside a script. You could keep your options in a cell array or something. The run_experiment function would just be a regular function,
function [output] = run_experiment(options, train_model, ...);
train_model(options{1}, ...)
.
.
.
end
What you need to do this is create a cell array with your function names and another array with the corresponding options as below
% Function name array
fn_array = {#fn_1, #fn_2, ...};
% Option array
option_array = {{fn1_opt1, fn2opt2, ...}; {fn2_opt1, fn2_opt2, ...};, ...};
These two need to be passed to your run_experiment function which will evaluate them as below
function run_experiment(fn_array, option_array)
num_fn = length(fn_array); %Finds number of functions to evaluate
for ii = 1:num_fn %Evaluates each function
fn_array{ii}(option_array{ii}{:});
end

MATLAB: Script with all my functions

Maybe it's a basic question but here I go. I would like to have a .m with all the functions that will be accessed by other scripts and functions.
I tried just doing a script with all the functions and call it in other functions code.
And I got and error. Could you please explain me how can I solve this?
I'm trying this, which gives me no error, and does what I want it to do, still, is it a good way to do it? Any suggestions?
function PruebasLlamaFuncion
funcionFEM=#PruebasTodasFunciones;
a=funcionFEM('OVERPOWER',1,5)
b=funcionFEM('POWEROVERWELMING',2)
end
...
function a=f(nombre,varargin)
f=str2func(nombre)
a=f(varargin{1:end});
end
function d=OVERPOWER(J,c)
d=J*c;
end
function e=POWEROVERWELMING(J)
e=J;
end
Function placement
Matlab, unlike a number of other languages, permits a single file to contain only one main function that is visible to the rest of the system. The main function is the first function. (Documentation)
Any functions that are defined after the main function body are called local functions. These functions each create their own separate workspace (scope) and can be called by one another and, of course, by the main function.
Any functions that are defined within the main function body are called nested functions. These functions have their own workspace but are also able to access and change the variables of their parent function under certain conditions. Nested functions at the same nesting level can call each other and local functions, but local functions cannot call nested functions since they are out of scope.
Workarounds
There are several options available to you depending on how you would like to proceed.
At the risk of giving too many options but desiring to be exhaustive, I'll put the list from what I would do first to what I would do last.
For most things, I would recommend 1 or 2.
The other options are more for creating libraries/APIs, but I included them to show what can be done.
Define Function1 and Function2 in separate m-files on the Matlab path or in the present working directory to call them normally.
Wrap the main body of your work (the one calling the functions) in a function itself and define the other functions as local functions or nested functions. Example:
function output = main(a,b,c)
Result=Function1(a,b,c);
Result2=Function2(b,d);
...
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
You can get a bit more fancy and have a function that returns function handles (pointers) to the local or nested functions and then use the (in the example) struct to call the functions in another script:
function Functions = GetFunctions()
Functions.F1 = #(a,b,c) Function1(a,b,c);
Functions.F2 = #(a,b) Function2(a,b);
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
If you have R2013b or above, you can do the same thing as above using the localfunctions function to create a cell array of handles to all local functions (in this case, the definitions are required to be outside the main function body).
function Functions = GetFunctions()
Functions = localfunctions(); % R2013b+ only
end
% Define Function1 and Function2 here for local functions
You can also create a class with static functions:
classdef Functions
methods(Static)
% Define Function1 and Function2 here and call them just like the struct above.
end
end
I hope that makes sense and hopefully helps.
I think you're misunderstanding something. A script is for calling a series of functions/other scripts in sequence. If you just want your functions to be accessible in other code, you only need to make sure they're on the path. You would never need a "script containing all the functions". You may be thinking of local functions, but these are the exact opposite of what you want (they can't be called from outside the function where they're defined or other local functions in the same file).
e.g. if Function1 and Function2 are on your path, you could write a script like this, perhaps as a demo for how to use those two functions:
a = 0;
b = 1;
c = 2;
d = 'Unicorns';
Result=Function1(a,b,c);
Result2=Function2(b,d);
It does not and should not have any function definitions in it. If your script can't find the functions, use addpath (see docs), to put the folder where these function files reside into your path. The m files should be given the same name, e.g. the following needs to go in a file called myfunc.m
function result = myfunc(a,b,c)
Functions in your working directory can also be called even if that directory isn't on your path.

MATLAB: Access variables of a script in a function

This is a very basic question, but somehow, I am struck up with this.
Suppose there is a script
Script1.m
a = 1;
b = 2;
function1()
And a function, function1 in function1.m
function1.m
a = a/b;
end
Now when I run this, I get an error: 'Undefined function or variable "a".
I am familiar with C/C++, and I know that I can pass a, b as arguments to the function. But suppose 'a' contains a lot of data , which if passed through the function would consume a lot of time. So it won't be feasible to pass the variable.
Is there any other approach to achieve the same?
Edit 1:
Suppose I am using Pattern Search, or some other function which takes a function1 handle as an argument, then how do I pass variables local to script1 to function1.

Declaring variables before declaring a function

Suppose I want to declare some variables then declare a function:
x = 2;
function y = function(x)
y = (x^2)+1;
end
y = function(x);
disp(y)
Matlab returns the error "Function keyword use is invalid here..."
Why can't I declare variables or write any text before declaring a function? Is there good reason or is it a quirk?
EDIT:
To clarify, I do know how to get around this problem (but thanks for the suggestions nonetheless) but I suppose I'm asking why the Matlab team made this decision. By making a function declaration the first line of a file, does it have implications for memory management, or something?
The REPL prompt of Scala can have a function defined after a variable. So this is a choice (a quirk if you want) from Matlab's inner internals.
If a function is defined in a file, there are two possibilities:
The main function of that file. Then the file must begin with the function declaration: in your example, function y = fun(x). I'm using fun as the function's name. I don't think function can be used as a function's name.
See here for more details.
A nested function. In this case, the function declaration and definition can be within another function of the preceding case.
See here for more details.
As you can see, in either case the file begins with a function declaration (namely that of the main function).
The function can also be defined as an anonymous function. Then no declaration is needed, and the function can be defined anywhere. But there's a restriction: the function can contain only a single statement (so it cannot define internal variables other than the output). Therefore this method can only be used for simple functions.
In your example, the function could be defined anonymously as fun = #(x) x^2+1.
See here for more details.
Others have given good info about nested functions and such.
But the reason for the error you get is that "function" is a reserved word in Matlab. You cannot have a function with this name.
function y = my_function(x)
y = (x^2)+1;
end
And stick it in another file called my_function.m

Anonymous functions calling functions with multiple output forms

I'm trying to define an anonymous function that calls a version of a function that returns multiple outputs.
For example, the function find has two possible output forms:
[row,col] = find(X);
and
[ind] = find(X);
Say I would like to choose the first form inside of an anonymous function.
I have tried
1)
get_columns = #(x) x(2);
and 2)
get_columns = #(x,y) y;
But when I call:
get_columns(find(x))
The first version of get_columns thinks I am calling find as [ind] = find(X) and not as [row,col] = find(X);, while the second one complains with "Not enough input arguments".
Is there a way to trigger a specific output form of a function inside an anonymous function?
Directly, no. Unfortunately, there are a number of features which are inaccessible via anonymous functions, and accessing multiple output arguments is one of them. (The other one I frequently find is that you cannot define an if statement inside an anonymous function. This appears to be a limitation of Matlab syntax more than anything else.
However, a pretty simple helper function can make this possible.
function varargout = get_outputs(fn, ixsOutputs)
output_cell = cell(1,max(ixsOutputs));
[output_cell{:}] = (fn());
varargout = output_cell(ixsOutputs);
This function takes a function handle plus an array of output indexes, and returns the indexed outputs.
If you create this file (hopefully better commented) and put it on your path, then you can access the second output of the find function as by defining the following function
find_2nd = #(x)get_outputs(#()find(x),2)
And now you can find the find the indexes of an array which equal 1 as
>> find_2nd([4 3 2 1]==1)
ans =
4
And now you should be able to access alternative output arguments at-will from within anonymous functions.
This get_outputs function above could be widely useful for brief anonymous functions. Very nice.
Also, regarding the comment that an "if" can't be used in MATLAB, this is only partially true. Identical behavior can easily be implemented anonymously. For instance, here's an anonymous if:
anonymous_if = #(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
Use:
out = anonymous_if(condition1, action1, condition2, action2, ...);
The action corresponding to the first true condition is executed. For instance, this prints 'hello'.
anonymous_if(false, #() disp('hi'), ... % if false, print 'hi'
true, #() disp('hello')) % else if true, print 'hello'
Granted, it's a bit complicated at first sight, but I keep something like this on my path so I can use an "if" in an anonymous function. Much more complex anonymous functions can be built in this way.