Anonymous functions saved as variables cannot be loaded while parent script has errors

6 views (last 30 days)
short summary
I save anonymous function handles in variables so I can access both my data and the functions for plotting them, but it appears that MATLAB stores info about where the function was created and attempts to re-load it from there. If I manage to load it, I can remove the link and the anonymous function works as intended, but otherwise it will somehow try to run my script where the function was defined and crashes if that script is not working (e.g. when I'm writing code in it). But I can remove that link and the function appears to run just fine.
In my main file M5_hga_features_and_power.m, I create an anonymous local function handle named title_fun(S,fb)
function correlate_pow_in_hga_absolute_weights
...
fname = {'delta', 'theta', 'alpha', 'beta', 'gamma'}; %frequency band names
A.mydata = somedatathatihave;
A.title_fun = @(S,fb) title(sprintf('subject %d, frequency band %s', S, fname{fb}));
save('mylocaldata', '-struct', 'title_fun', etc...);
...
end
Then I have another function which loads data and plots it
function plot_my_data
for S=1:2 %loop through my test subjects
for fb = 1:5 %loop through the frequency bands
A = load('mylocaldata', 'title_fun', etc...);
figure; plot(A.mydata);
A.title_fun(S,fb);
end
end
It is very convenient to have a title-function handle saved together with the data I want to plot and generally works fantastic. I can just loop through subjects and frequency bands and use these indices for my anonymous function without having the long formatting in the plot function. However, if I load 'mylocaldata' while having errors in my script file 'M5_hga_features_and_power.m', then the load-function gives me this error:
Error using load
Error: File: M5_hga_features_and_power.m Line: 166
Column: 1
Function definitions in a script must appear at the end
of the file.
Move all statements after the
"correlate_pow_in_hga_absolute_weights" function
definition to before the first local function definition.
It appears that when I load 'mylocaldata', the function handles somehow tries to access the script file (M5_hga_features_and_power.m) where I defined the anonymous function. I ran s = functions(A.title_fun), and found that it had saved the path to my script file.
s =
struct with fields:
function: '@(S,fb)title(sprintf('s%d %s mean hGA Weights (NFT sessions)',S,fname{fb}))'
type: 'anonymous'
file: '--long path--\analys\M5_hga_features_and_power.m'
workspace: {[1×1 struct]}
within_file_path: ''
But I don't need that path. If I clear it (set it empty), then I can load 'mylocaldata' without any errors, and the frequency band names are saved in 'workspace'. So my questions are:
  1. why does the anonymous function try to run the original script when I load it from a file? Does it try to update the function?
  2. Where is the information for the function handle saved? i.e. is the workspace variable somehow saved with the handle in my 'mylocaldata'-file?
I haven't found an answer on mathworks documentation on 'functions', 'Create Function Handle', 'Function Handles', 'Anonymous Functions' or other similar sites on mathworks website.
Also, if this kind of coding is crazy and you have a better idea for keeping functions with data, I'll gladly take your advice.
Kind Regards, Jonatan Tidare
  1 Comment
Stephen23
Stephen23 on 12 Jul 2022
"if this kind of coding is crazy and you have a better idea for keeping functions with data, I'll gladly take your advice."
If storing a function handle is good for your workflow, then go for it. The fact that TMW probably has a bit more work to make that happen... well, so be it. Of course any data type has some special edge-cases, as you are finding out :)

Sign in to comment.

Accepted Answer

Jonatan Tidare
Jonatan Tidare on 14 Jul 2022
It might be fixed in a future release of MATLAB.

More Answers (2)

Steven Lord
Steven Lord on 13 Jul 2022
But I don't need that path.
Prove that statement using static analysis, just looking at the contents of the struct array s.
I know what you're probably going to say, that it's obvious. But it's not if you look at it through the eyes of MATLAB. Here's your anonymous function:
@(S,fb)title(sprintf('s%d %s mean hGA Weights (NFT sessions)',S,fname{fb}))
How do you know that there was no local function or private function named either title or sprintf in scope at the time this anonymous function was created? Remember, if you "don't need that path" you can use neither the contents of the file in which that anonymous function was defined nor what's in that directory (including whether or not there's a private subdirectory or a title.m or sprintf.m in the directory that shadows the title or sprintf functions built into MATLAB) in your answer.
The alternative is to never let the m-file that created my anonymous function break (i.e. don't develop that file), which is what I will do for now.
I agree with the first part of your statement but not your parenthetical aside. As long as your code is syntactically valid I would expect loading the function handle to work. And if your code isn't syntactically valid, you're not going to be able to run it so what good is it doing you?
  3 Comments
Stephen23
Stephen23 on 14 Jul 2022
Edited: Stephen23 on 15 Jul 2022
"I know that I don't need the path in "file", because ..."
No, that is not static analysis:
Presumably MATLAB uses that information somehow, otherwise they probably would not be lugging it around with the function handle. Most likely this is a side-effect of a weakly-typed language.
Jonatan Tidare
Jonatan Tidare on 14 Jul 2022
I don't think you understand the problem. Let me give you an example.
step 1)
create and run a script file named 'save_myfun.m' with the code (only 2 lines):
myfun = @(x) x;
save('myfun', 'myfun');
step 2)
Now change save_myfun.m to have the following code (so it cannot be run)
? %this will make the script un-runnable
myfun = @(x) x;
save('myfun', 'myfun');
step 3)
type load('myfun') in the command window. It will now give the following error:
>> load('myfun', 'myfun');
Error using load
Error: File: save_myfun.m Line: 1 Column: 2
Invalid expression. Check for missing or extra characters.
step 4)
delete save_myfun.m. Now you can run load('myfun') with a warning
Warning: Could not find appropriate function on path loading function handle C:\Users\*myname*\Downloads\test\save_myfun.m>@(x)x
step 5)
type save('myfun', 'myfun'); and then load('myfun') in the command window. Now myfun loads without errors.
I would like to be able to remove the arbitrary link between myfun and save_myfun.m, but it is impossible to access the structure behind the anonymous function handle. I sent a ticket to mathworks regarding this and the answer was that it was odd, but that it might be fixed in a more generic update of Matlab in the future.
Thank you for taking your time replying.

Sign in to comment.


Jonatan Tidare
Jonatan Tidare on 13 Jul 2022
I've continued to look around for any way to clear the "file" field in my anonymous function, but there is no documentation to explain that. What happens is that if I load my anonymous function, it attempts to run the m-file in the field "file" (from functions.m). If I don't have that file on path, it will be cleared, and I can manually re-save my function with a clear file-field. Then it is great.
However, I don't want to manually remove path, load anonymous function, re-save, add path. The alternative is to never let the m-file that created my anonymous function break (i.e. don't develop that file), which is what I will do for now. I just wish I could access and change the file-field in my anonymous function. I really hope mathworks fixes this in the future.

Categories

Find more on Function Creation in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!