How can I force a function handle to use its specified path?

25 views (last 30 days)
When I create a function handle pointing to a function not on the path, it can't be called if there is another function with the same name on the path. (But if there isn't another function with the same name on the path it works just fine.)
To recreate the problem you need two files:
C:\somepath\@someFunc\someFunc.m:
function someFunc()
disp('called original someFunc!');
end
C:\somenewpath\@someFunc\someFunc.m:
function someFunc()
disp('called new someFunc!');
end
Both C:\somenewpath\ and C:\somenewpath\ should be on the path, with somenewpath having higher precedence.
Demo:
>> path
MATLABPATH
C:\somenewpath
C:\somepath
... snipped ...
>> cd C:\ % go anywhere
>> someFunc %show that new func is being called by default
called new someFunc!
>> cd C:\somepath
>> someFunc %show that old func is now being called
called original someFunc!
>> fh = @someFunc; %get file handle to old function
>> functions(fh) %show that fh has original path
ans =
function: 'someFunc'
type: 'simple'
file: 'C:\somepath\@someFunc\someFunc.m'
>> fh() %call fh and show it points to original function
called original someFunc!
>> feval(fh) %call fh and show it points to original function
called original someFunc!
>> cd C:\ %go anywhere else
>> fh() %call fh and show it points to new function (even though the fh path points at the old one)
called new someFunc!
>> feval(fh) %call fh and show it points to new function (even though the fh path points at the old one)
called new someFunc!
>> functions(fh) %show that fh still has original path
ans =
function: 'someFunc'
type: 'simple'
file: 'C:\somepath\@someFunc\someFunc.m'
Note that the file handle is still pointing to the original function, but when it is invoked it calls the new function. Is this a bug?
I am testing on Matlab 2015a.
Note that simply cd'ing to the original directory will not work for me, since the original function is recursive, but I need it to call the new function (see below for more details).
More background (in case someone has an alternative suggestion):
I am trying to override a protected recursive class function (a .p that calls itself), then call the original from the overloaded function. The reason is that a 3rd party package I'm using lost functionality in a newer version, and I would like to handle/override specific cases so that it is compatible with existing code.
It seems that the solution should be to create a function pointer to the original function, then call it from the new function. Unfortunately, this doesn't work -- even when the function pointer is pointing to the original path, it still calls the new function (or the function with the same name that has precedence on the path).
Note that the original function can be called from the new one by changing directories to the original function then calling it. However, in this case when the original function calls itself recursively, it doesn't call the new function.

Answers (1)

Steven Lord
Steven Lord on 22 Jun 2015
See the section "The Role of Scope, Precedence, and Overloading When Creating a Function Handle" in this page from the documentation. What you're doing by changing directories is determining which version of the method of the someFunc class is "visible" to MATLAB, and when you invoke the method MATLAB calls the version of that method that is "visible" at the time of invocation, even if a different version was "visible" when a function handle was created. So this is not a bug.
If I understand what you're trying to do, you may be able to do what you want using a private function in the class directory since that's higher precedence than object methods. [You may also want to complain to the author of the third party package for breaking your code.]
  2 Comments
cwshep
cwshep on 22 Jun 2015
Edited: cwshep on 23 Jun 2015
Thanks for the reply and suggestion!
I tried the private function in the simple example above. While I was able to get the original function to call its private func, I wasn't sure how to call the original (public) function from the private function. Any suggestions?
Regardless, when I tried applying this to the protected class function I noticed it wouldn't call the private function. It turns out that the protected function is not directly recursive -- it calls another function which then calls it again, which means the private function suggestion won't work, unfortunately.
So I guess the question still remains: Is there a way to force a function handle to call the function defined by its path ('file')?
More generically, I need a way to call a function that doesn't have precedence on the path.
Walter Roberson
Walter Roberson on 23 Jun 2015
Steve, I do see the line in that documentation that says,
Precedence — MATLAB selects which function(s) to associate the handle with, according to the function precedence rules described under Determining Which Function Gets Called.
but even after reading that additional material, I do not understand how multiple functions can get associated under the function precedence rules.
The additional material appears to give the rules for selecting one function out of all of the possibilities, not for selecting multiple. There is nothing in points 2 to 10 about function handles, so if function handles are treated differently than variables there is nothing there that tells us how to know the priority of function handles. If we assume that means that function handles are considered last, the implication would be that if you happen to have another function of the same name anywhere in the path then that other function would be called, which would make function handles much less useful.
But we cannot skip over point 1, about variables. A function handle in scope is a variable.
That point 1 only talks about variables in the current workspace, though, implying that if the variable that is the function handle is defined in a shared scope that the name will not be treated as a function handle and that a normal search for functions would be done instead. That is of course not correct, so the documentation is inadequate.
When a name does match a variable that is a function handle, there is nothing at all in that precedence list that would lead to the interpretation that the function being referred to would need to go through an additional resolution layer. And that's because it doesn't happen!
Have a look through the scope tests in my attached file testscope.m . It shows that (excluding any effects of classes or private functions)
  1. it is always an error for there to be a variable (that might be a function handle) in the same inner scope as a nested function with the same name, and this is the case whether the variable was created by assignment or as an argument name
  2. if there is a nested function with the name of the function handle, the nested function is called even if there is a function handle of the same name that is in an outer scope (nested functions override variables in outer scope)
  3. in all other cases, the routine invoked is the one that was in scope at the time the function handle was created, and this applies no matter whether the handle was passed as a parameter or is in an outer scope, and applies even if the variable name matches the name of a function (such as sin) that is overloaded for various fundamental MATLAB data types
There are some duplicate cases in the file; I was emphasizing different aspects to myself at different times. I also mis-read my outputs and thought that I had seen overloading taking place and then spent a bunch of effort trying to nail down the circumstances under which it would take place when it actually did not take place at all.
The only multiple resolution that is clearly mentioned in the documentation is:
Overloading — If additional files on the path overload the function for any of the fundamental MATLAB classes, such as double or char, then MATLAB associates the handle with these files, as well.
I tested that and could not find any circumstances under which the overload was invoked and not the routine I had created the reference to. It does appear to imply that a list of potential resolutions is carried along, but I could not get it to invoke anything other than the obvious.
The documentation you referred to talks about the absolute path being recorded and gives no indication that the path might be overridden aftewards "as long as the program file for the function still exists at this location". Notice that it is absolute path, not relative path.
So... if what the poster is seeing is not a bug, it certainly isn't consistent with the interpretation that you seem to be implying of the documentation you referenced.

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!