List subfunctions defined in function file within calling environment - matlab

I have a function defined like the following in a .m file:
function main_fn()
...
end
function sub_fn1()
...
end
function sub_fn2()
....
end
...
function sub_fnN()
...
end
i.e. standard structure with main function first followed by subfunctions accessible by the main function when it is called.
I know that you can use whos within the function calling environment to return the variables stored in the function call stack. I would like to retrieve the sub-functions defined within the function file, and return them as a cell array of function handles.
Is this possible?
EDIT: the answer by #nirvana-msu has made my original request possible. However, now I find that it is more convenient to store these functions in a struct, so that I can refer to them by name:
For example:
fcn =
struct('sub_fn1', #sub_fn1, ...
'sub_fn2', #sub_fn2, ...
...
)
EDIT 2:
It is simply to convert the cell array obtained in the answer to a struct, simply use func2str:
fcns = cell2struct(fncs, cellfun(#func2str, fncs, 'uni', 0));

Use localfunctions - introduced in R2013b:
function main_fn()
fcns = localfunctions();
end
function sub_fn1()
end
function sub_fn2()
end
function sub_fnN()
end
It returns a cell array of function handles to all local functions in your file:
fcns =
#sub_fn1
#sub_fn2
#sub_fnN

Related

Modify structure array from nested function with function handle

I am trying to modify a structure array from within a nested function, where the nested function is 'returned' through a function handle. From what I know, you cannot modify the structure array from the 'outer' function, since MATLAB pass arguments by values and not by references. However, you should be able to do it from within a nested function as the nested function can access the 'parent' scope. However when I 'address' the function using function handle it does not work.
Here is the code:
function object = objectReader()
object.counter = 0;
object.getData = #GetData;
function data = GetData(input)
object.counter = object.counter+1;
data = input*1.23456789;
end
end
From what I found, it could be that when making the function handle, it also makes a copy of the 'current' scope so the function since than lives in 'isolated environment'.
So the question is, how can I do modify a structure array from within a nested function, while maintaining the outside interface? By outside interface I mean that you can do:
object = objectReader();
data = object.getData(1);
and object.counter increments each time you call object.getData() function.
Add to your example the counter as output and you will see the increments:
function object = objectReader()
object.counter = 0;
object.getData = #GetData;
function data = GetData(input)
object.counter = object.counter+1;
data = [input*10 ,object.counter];
end
end
And the example:
myobject = objectReader();
disp(myobject.getData(1)); % 10 1
disp(myobject.getData(1)); % 10 2
Read more about closure here:
https://research.wmz.ninja/articles/2017/05/closures-in-matlab.html
And it is more natural to do it using class with properties and methods: https://uk.mathworks.com/help/matlab/matlab_oop/create-a-simple-class.html

MATLAB : dynamic variables not updated directly in the workspace

I have a problem with some varaibles.
I create variables dynamically in a loop.
for i=1:nbr
assignin('base', ['x_',num2str(i)],0)
end
And after, I would like to put the result of my function in these variables. But the variables in the base of the workspace are not updated directly so I have an error "Undefined function or variable". How can I fix my problem ?
for i=1:nbr
['x_',num2str(i)]= fonction(input);
end
Thank you in advance
Best regard
Instead, use a cell array:
x{i} = function(input);
Then return the entire cell array back to the caller, so that you never need to use assignin. The whole function body would look like this:
function x = myfunction(someinput)
for i=1:nbr
x{i} = someotherfunction(input);
end
% Cell array x is returned from the function

MATLAB: Function Handle of Nested Function

Is there a way to create a function handle to a nested function that includes the parent function in the function handle?
As an example, say I have:
function myP = myParent()
myP.My_Method = myMethod;
function myMethod()
disp "hello world"
end
end
In another file, I could call the method by doing something like:
myP = myParent();
myP.My_Method();
But, if I have another function that takes function handles as a parameter and then calls the function, how do I pass in the function handle to myMethod in this case, since this new function can't create a myParent variable.
The following seems to work:
function myP = myParent()
myP.My_Method = #myMethod;
function myMethod()
s=dbstack;
fprintf('Hello from %s!\n',s(1).name);
end
end
Running it as follows:
>> myP = myParent()
myP =
My_Method: #myParent/myMethod
>> feval(myP.My_Method)
Hello from myParent/myMethod!
>> myP.My_Method()
Hello from myParent/myMethod!
It is also fine to run it from another function:
% newfun.m
function newfun(hfun)
feval(hfun)
Test:
>> newfun(myP.My_Method)
Hello from myParent/myMethod!
Depending on what you are doing, this should be enough. Note that each handle you create is unique since it contains information about externally scoped variables (variables pulled in the parent):
When you create a function handle for a nested function, that handle stores not only the name of the function, but also the values of externally scoped variables.

Passing matrices from function to function in MATLAB

I'm pretty new to MATLAB and I have a simple question. What if I have the following structured functions:
function[A] = test(A)
test1(A);
test2(A);
end
function test1(A)
#% do something with A
end
function test2(A)
#% do something else with the newly modified A
end
How do I pass around A from function to function keeping it's modified nature? (Suppose A is a matrix)
EDIT: let's make the situation a little simpler. Suppose my main function is:
function[a]=test(a)
test1(a);
#%test2(a);
end
and test1() is defined as:
function[a] = test1(a)
a=5;
end
Then, I call the function test with test(3), and I want it to report ans = 5, yet it still reports ans = 3.
Thanks!
Variables in MATLAB are passed using "call by value" (with some exceptions), so any value that you pass to a function and modify has to be returned from the function and either placed in a new variable or the old variable overwritten. Returning the value of a variable from a function is simple: you just place the variable name in the output argument list for the function.
For your example, you would do this:
function A = test(A)
A = test1(A); %# Overwrite A with value returned from test1
A = test2(A); %# Overwrite A with value returned from test2
end
function A = test1(A) %# Pass in A and return a modified A
#% Modify A
end
function A = test2(A) %# Pass in A and return a modified A
#% Modify A
end
One thing to be aware of is variable scope. Every function has its own workspace to store its own local variables, so there are actually 3 unique A variables in the above example: one in the workspace of test, one in the workspace of test1, and one in the workspace of test2. Just because they are named the same doesn't mean they all share the same value.
For example, when you call test1 from test, the value stored in the variable A in test is copied to the variable A in test1. When test1 modifies its local copy of A, the value of A in test is unchanged. To update the value of A in test, the return value from test1 has to be copied to it.
Return the object from the function and then pass it on to the next function.

routine to either evaluate code or transmit via udp

I have a set of code that, depending on how the program is initiated, will either be executed locally or sent to a remote machine for execution. The ideal way I imagine this could work would look something like the following:
line_of_code = 'do_something_or_other();';
if execute_remotely
send_via_udp(line_of_code);
else
eval(line_of_code);
end
The thing is, I know that the eval() function is ridiculously inefficient. On the other hand, if I write out line_of_code in each section of the if block, that opens the door for errors. Is there any other way that I can do this more efficiently than by simply using eval()?
EDIT: After more consideration and some discussion in the comments, I have my doubts that function handles can be transmitted via UDP. I'm therefore updating my answer, instead suggesting the use of the function FUNC2STR to convert the function handle to a string for transmission, then using the function STR2FUNC to convert it back to a function handle again after transmission...
To get around using EVAL, you can use a function handle instead of storing the line of code to be executed in a string:
fcnToEvaluate = #do_something_or_other; %# Get a handle to the function
if execute_remotely
fcnString = func2str(fcnToEvaluate); %# Construct a function name string
%# from the function handle
send_via_udp(fcnString); %# Pass the function name string
else
fcnToEvaluate(); %# Evaluate the function
end
The above assumes that the function do_something_or_other already exists. You can then do something like the following on the remote system:
fcnString = receive_via_udp(); %# Get the function name string
fcnToEvaluate = str2func(fcnString); %# Construct a function handle from
%# the function name string
fcnToEvaluate(); %# Evaluate the function
As long as the code (i.e. m-file) for the function do_something_or_other exists on both the local and remote systems, I think this should work. Note that you could also use FEVAL to evaluate the function name string instead of converting it to a function handle first.
If you need to create a function on the fly, you can initialize fcnToEvaluate as an anonymous function in your code:
fcnToEvaluate = #() disp('Hello World!'); %# Create an anonymous function
And the code to send, receive, and evaluate this should be the same as above.
If you have arguments to pass to your function as well, you can place the function handle and input arguments into a cell array. For example:
fcnToEvaluate = #(x,y) x+y; %# An anonymous function to add 2 values
inArg1 = 2; %# First input argument
inArg2 = 5; %# Second input argument
cellArray = {fcnToEvaluate inArg1 inArg2}; %# Create a cell array
if execute_remotely
cellArray{1} = func2str(cellArray{1}); %# Construct a function name string
%# from the function handle
send_via_udp(cellArray); %# Pass the cell array
else
cellArray{1}(cellArray{2:end}); %# Evaluate the function with the inputs
end
In this case, the code for send_via_udp may have to break the cell array up and send each cell separately. When received, the function name string will again have to be converted back to a function handle using STR2FUNC.