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.
Related
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
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.
I have a function that returns two values, like so:
[a b] = myfunc(x)
Is there a way to get the second return value without using a temporary variable, and without altering the function?
What I'm looking for is something like this:
abs(secondreturnvalue(myfunc(x)))
not that i know of. subsref doesn't seem to work in this case, possibly because the second variable isn't even returned from the function.
since matlab 2009b it is possible to use the notation
[~, b] = function(x)
if you don't need the first argument, but this still uses a temporary variable for b.
Unless there is some pressing need to do this, I would probably advise against it. The clarity of your code will suffer. Storing the outputs in temporary variables and then passing these variables to another function will make your code cleaner, and the different ways you could do this are outlined here: How to elegantly ignore some return values of a MATLAB function?.
However, if you really want or need to do this, the only feasible way I can think of would be to create your own function secondreturnvalue. Here's a more general example called nth_output:
function value = nth_output(N,fcn,varargin)
[value{1:N}] = fcn(varargin{:});
value = value{N};
end
And you would call it by passing as inputs 1) the output argument number you want, 2) a function handle to myfunc, and 3) whatever input arguments you need to pass to myfunc:
abs(nth_output(2,#myfunc,x))
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.
In my matlab m-file I am using some logic (string concat) to build variables like this:
c = 'CalcPrediction(1,10)'
That means I have a string that is a function and some parameters. How can I do that function call?
Trying run(c) results in:
>> run(c)
??? Error using ==> run at 71
CalcPrediction(1,10) not found.
Note: run(c) works fine if there is no parameters. E.g.
c='CalcPrediction';
run(c);
The command you are looking for is eval() instead of run()
Without actually seeing the script it's hard to generalize, but...
Where squareRoot is an m-file containing only :y=sqrt(x)
Then executing :
x=[2,0];
c='squareRoot';
run(c);
gives :
y =
1.4142 0
This example is to say you can define the script to use a declared variable (x in this case) and then declare the variable before running the script.
Without the script I don't know what you're doing with the parameters. If this doesn't answer your question, post your script.
You want to use str2func. This function takes a string and returns a function handler that can be called with your parameters. Check out the examples on the linked page.
fh = str2func('CalcPrediction')
fh(1, 10)