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.
Related
I'd like the constructor of a class to automatically determine the full path to the calling function, so that that class can write a file that's guaranteed to be in the caller's directory (instead of whatever happens to be the pwd()).
So, I have the following setup:
In some_path/test.m:
function test
SomeClass()
end
In some_path/some_subdir/SomeClass.m:
classdef SomeClass < handle
methods
function obj = SomeClass()
evalin('caller', 'mfilename(''fullpath'')')
end
end
end
When I call test(), I get the following:
>> test()
ans =
'some_path/some_subdir/SomeClass.m' % <- ...why?
I expected the call to mfilename() in evalin('caller', ...) to evaluate inside test(), but apparently, that doesn't happen...
Nesting evalins doesn't seem to help:
...
function obj = SomeClass()
evalin('caller', ' evalin(''caller'', ''mfilename(''''fullpath'''')'') ')
end
...
>> test()
ans =
'some_path/some_subdir/SomeClass.m'
The only way to get this to work is the far less intuitive dbstack():
...
function obj = SomeClass()
S = dbstack(1, '-completenames');
S(1).file
end
...
>> test()
ans =
'some_path/test.m'
What am I missing?
It looks like you cannot use evelin for this purpose. From the documentation:
evalin('caller', expression) finds only variables in the caller's workspace; it does not find functions in the caller.
From that I read that not the full context of the calling function is recovered before evaluating the expression, only variables in the workspace of the calling function are made available.
That same documentation page also mentions this limitation:
evalin cannot be used recursively to evaluate an expression. For example, a sequence of the form evalin('caller', 'evalin(''caller'', ''x'')') doesn't work.
That is consistent with the notion that only the caller's workspace is made available, not the full context. The expression is not actually evaluated as if it were written inside the calling function.
I have repeated your experiment with a simple M-file function, just to verify this indeed is not specific to classes or constructors, but generally applies to any function, anywhere.
The dbstack option is the way to go.
Lets say we have a custom extractor function
[features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1, param2)
I want to call bagOfFeatures function and pass custom extractor function:
extractorFcn = #exampleBagOfFeaturesExtractor;
bag = bagOfFeatures(imgSets,'CustomExtractor',extractorFcn)
In exampleBagOfFeaturesExtractor function I want to use different local descriptors extractor depending on param1.
How do I pass param1 to exampleBagOfFeaturesExtractor?
What is the best way to use different local descriptors in my custom extractor function?
Thank you for your help!
Edit
This is the custom extractor function I am currently using:
function [features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1,param2)
keypoint_detector = cv.FeatureDetector(param1);
descriptor_extractor = cv.DescriptorExtractor(param2);
kpts = keypoint_detector.detect(img);
[ features, kpts ] = descriptor_extractor.compute(img, kpts);
featureMetrics=ones(1,size(features,1))/size(features,1);
end
The expected kind of functions that the bagOfFeatures function requires can only be a single input, namely the input image. Therefore, if you want to create a custom feature extractor where you can vary the parameters, you will need to first create the parameters, then create an anonymous function that captures these parameters via lexical closure. This means that when you create the anonymous function, make sure the parameters are created so that when you reference them in your anonymous function, they capture the most up to date version of the parameters prior to creating the function.
Therefore, assuming param1 and param2 already exist in your workspace, create a function like so:
% Create param1 and param2 here
param1 = ...;
param2 = ...;
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
This creates an anonymous function that takes in a single input - your image. param1 and param2 are thus captured in your function, so the state of the variables is recorded and are made available within the anonymous function. Also note that the function doesn't take in additional inputs, only the input image. You can then call bagOfFeatures as normal. However, should you want to change param1 or param2, not only will you have to change these parameters, but you must re-declare the anonymous function again so that the latest stage of the variables is recaptured.
As a quick example, suppose I've created an anonymous function like so:
x = 5;
y = #(t) t + x;
This function y takes the current state of x and adds it with a variable t. For now, this acts like how we expect it:
>> x = 5;
>> y = #(t) t + x;
>> y(6)
ans =
11
We put in the value 6 and we get 11. If we try and change x then call y, it will not change this in the function as it captured the state of the variable before you created the function:
>> x = 10;
>> y(6)
ans =
11
Therefore, if you want to change the parameters, you must also re-declare the function again before calling bagOfFeatures, so:
param1 = ...; % Change this to something new
param2 = ...; % Change this if you like as well
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
In MATLAB terms, these variables persist in the anonymous function. You can read more about it here: https://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html#f4-71621
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
It is possible to use the function inputname to retrieve the workspace variable name passed in the call to the currently executing function. However, is there any equivalent function to obtain the name of the output arguments specified in the call to the currently executing function?
Imagine I have the following function:
function [a,b,c] = test(x)
disp([ouputname(1),ouputname(2),ouputname(3)])
end
When running this function:
[my,name,is] = test(x)
The expected result should be:
mynameis
Simply: no there isn't.
Complicated: Matlab code is "compiled" on run-time, and there is no way, that it knows [my,name,is] before it returns the result of test(x).
Workaround: if you want to ensure, that the strings used within the function are equal to the variables returned to the workspace, you can do the following using assignin:
function test(x, varnames)
a = 1;
outputname{1} = varnames{1};
assigin('base', outputname{1}, a)
...
c = 3;
outputname{3} = varnames{3};
assigin('base', outputname{3}, c)
disp([outputname{:}])
end
and call your function like:
text(x,{'my','name','is'})
and you will have exactly this variables in your workspace afterwards and your function output:
"mynameis"
I am trying to access the output of a function from another function. I have the following function:
function f = doSomething
f = 5+6;
In another function I'm calling doSomething as follows:
doSomething;
Is there a way to get the value of f? I want to read the output of doSomething and display it.
Write
output = doSomething();
to store the result to the variable "output", and
fprintf('%d\n',output);
to display it.