This currently only works in Matlab R14 SP3. In previous versions this does not work.
It is sometimes usefull to be able to obtain a function handle of a nested function in the calling scope. What this means is that you use
evalin('caller',...) to perform an operation which retrieves function handles from the caller. An example of this is my unit test tool for Matlab
MUnit which obtains a list of function handles whose names match the regular expression 'test_[A-Za-z0-9_]*'.
To do this first create a cell array of the function names you wish to grab. How you decide on what these names are are an application matter. In MUnit I scan the calling file and use regular expressions to find all function names that match the patterns.
In munit_testcase.m you will find
stk = dbstack('-completenames');
mname = stk(2).file;
fcn_names = scan(mname, {'setup' ,'teardown', 'test_[A-Za-z0-9_]*'});
where the scan function is defined as
% SCAN
%
% Scans and extracts function names from an m file
% using regular expression patterns.
%
% Arguments
% file - full path to an m file to scan
% patterns - A cell array of regular expressions for function names
% to extract
%
function names = scan(fname, patterns)
if iscell(patterns)
patterns = sprintf('(%s)|',patterns{:});
end
str = evalc(sprintf('mlint(''-calls'',''%s'')', fname));
names = regexp(str,'\d+\s*([AZa-z][A-Za-z0-9_]*)','tokens');
names = cellfun(@(x) x{1}, names, 'uniformoutput', false);
i = cellfun(@(x)~isempty(regexp(x, patterns)), names);
names = names(i);
end
The above is different to what is in MUnit which uses an older scanning method and caching approach to avoid scanning the file more than once.When you have your cell array, here stored in the variable
fcn_names execute the following code
fcns = evalin('caller',['@(){' sprintf('@%s ', fcn_names{:}) '}']);
fcns = fcns();
for i = 1:length(fcns);fcn = fcns{i};
test_case.(fcn_names{i}) = fcn;
end
If fcn_names contains
{'fun1' 'fun2' 'fun3'}
then the following expression will be evaluated in the
caller
@(){ @fun1 @fun2 @fun3 }
That is it generates an anonymous function that when evaluated, line 2, generates a cell array of function handles.
Line 3 to line 5 just copies the function handles to named fields on a structure which can be returned.
You may ask why I need the extra layer of the anonymous function. I don't really know. It should be enough just to evaluate the cell array of function handles in the caller but this just does not work. Matlab bug or feature???
The savvy among you may realize that you can use this trick to easily create an object framework in Matlab. For example my theoretical object function may look like.
function self = my_object(x)
self = create_object;
function y = m_incr(r)
x = x + r;
y = x;
end
function y = m_decr(r)
x = x - r;
y = x;
end
end
and create_object looks like
function self = create_object
stk = dbstack('-completenames');
mname = stk(2).file;
fcn_names = scan(mname, {'m_[A-Za-z0-9_]*'});
fcns = evalin('caller',['@(){' sprintf('@%s ', fcn_names{:}) '}']);
fcns = fcns();
for i = 1:length(fcns);fcn = fcns{i};
self.(fcn_names{i}) = fcn;
end
end
Now at the command line you should be able to
>> x = my_object(10);
>> x.m_incr(1)
ans =
11
>> x.m_decr(2)
ans =
9
Have fun