How to get a list of local functions
Within a function such as top_level_function you can use getcallinfo to get a full list of function names that are locally defined:
local_functions = getcallinfo([mfilename('fullpath'),'.m']);
local_functions_names = {local_functions(2:end).name};
The first output of getcallinfo is the main function of the file, which is why we skip it. So this gives us a list of all functions, local and nested.
The undocumented function getcallinfo gives lots if information about the local functions in a file (we'll use it again later in this answer). Note that, being undocumented, this function can change or disappear without notice. See Undocumented Matlab for more details. Type edit getcallinfo rather than help getcallinfo to read the non-public documentation.
How to tell if a local function shadows a global function
If you know that string or char vector name contains the name of a local function (it's one of the values in local_functions_names), then which(name, '-all') will return either a single element (the local function) or a longer list (the local function plus the global function plus any additional overloads). So simply counting how many values are returned is sufficient:
if numel(which(name, '-all')) == 1
disp('This function only exists locally')
end
An alternative to see if a function is defined locally
Instead of comparing the name of the function against local_functions_names, you can follow Wolfie's implied solution and compare the output of which to that of mfilename:
path1 = which(name);
path2 = [mfilename('fullpath'),'.m'];
if strcmp(path1, path2)
disp('This function is defined locally')
end
How to distinguish a local function from a nested function
(This is the original answer here, though it seems that it doesn't answer OP's question at all.)
The function getcallinfo can tell us if a function is nested or local.
Let's assume a file called so.m with the following code as an example:
function so()
function nested_helper
end
end
function local_helper
end
(This is similar to that in the OP, but with more explicit names.)
Starting off with this line from Wolfie's answer:
w = which('nested_helper', 'in', 'so');
We get w = '<path>/so.m'. We can now do:
m = getcallinfo(w);
This returns a struct m with three elements, one for each function in the file. We find the element corresponding to our function, and get its type:
m(strcmp('nested_helper', {m.name})).type
m(strcmp('local_helper', {m.name})).type
This returns the string (char array) 'nested-function' for nested_helper, and 'subfunction' for local_helper.
Another alternative to see if a function is defined locally, and whether it's nested or local
The internal function functions also gives us the desired information, but it works with a function handle, not a name. Within a function top_level_function, we can do
fun = eval(['@', name]);
m = functions(fun);
if strcmp(m.type, 'nested')
disp('it is a nested function')
elseif strcmp(m.type, 'scopedfunction')
disp('it is a local function')
else
disp('it is not a local function')
% note that this case also happens if `name` is not a valid function at all
end
Instead of eval(['@', name]) to create a function handle from the name of a function, you can use the function str2func. But str2func doesn't seem to be able to create a handle for a nested function; it does work with local functions.
Note that, being an internal function, functions might change. But it's been around for a long time and depended on for so many tools that this is not likely.
which(...,'all')?helper1is a local function defined in just thetop_level_functionin question. But ifhelper1is globally available, I'd like to avoid it. My current use case is to output local functions asfunction_handlewithout creating the granular interface per top level function. The current purpose is for testing.top_level_functionis returning as function handle. but i dont want to type a dictionary of local functions. i want it to just be able to output them as function_handle as long as the caller has the correctchar vecfor the function name, while also having some primitive safety that only function_handle created from local function can be returned.