I am trying to update an old code.
The code has many lines with "cellfun" function and i use anonymous functions.
It worked well at R2012b version but it dowsnt work at R2018a version.
examples:
  • cellfun(@(x) logical(exist(x,'var')), handles.Names); % . The names in it are variables that exist in the workspace.
  • cellfun(@(x) eval(['handles.' x ' =cell(size(Size_Parameter));']), handles.Names);
  • cellfun(@(x) save([FullFileName],'-struct','handles',x,'-append'),handles.Names);
handles.Names is cell array in my GUI.
All these work well in R2012b but not in R2018a.
I will be glad to get some help. Do i have to replace all these command lines into loops?

6 Comments

Stephen23
Stephen23 on 26 Nov 2018
Edited: Stephen23 on 26 Nov 2018
"It worked well at R2012b version but it dowsnt work at R2018a version"
That code actually never worked "well". It is slow, complex, hard to debug, badly designed code. Introspective commands like exist are slow. Commands like eval that magically access variable names are slow, pointlessly complex, inefficient, and make debugging hard.
Read this to know why:
The best thing to do would be to rewrite that code using simpler, more efficient methods. For example, using eval to assign fields of a structure is not required at all, because you can do this much simpler and more efficiently using dynamic fieldnames:
In my opinion, putting all of those commands into cellfun calls was not a way to write clear, neat code anyway. Loops are perfectly neat and efficient, so why not use them?
Hi Stephen,
I am used to write loops but the code that I update was written by someone else.
The code works well and fast on MATLAB R2012b, even thogh it has these commands.
Replacing all lines that have the "cellfun" command will take long time.
Do you know why these lines are not working? Is there a simpler way to correct them?
Stephen23
Stephen23 on 26 Nov 2018
Edited: Stephen23 on 26 Nov 2018
"Do you know why these lines are not working?"
You can read the reasons here:
and by reading the anonymous function help, which states "Use only explicit variables when constructing anonymous functions. If an anonymous function accesses any variable or nested function that is not explicitly referenced in the argument list or body, MATLAB throws an error when you invoke the function. Implicit variables and function calls are often encountered in the functions such as eval, evalin, assignin, and load. Avoid using these functions in the body of anonymous functions."
"Is there a simpler way to correct them?"
Yes: write better code. This is ugly hack code that is wasting your time. Because that it what badly written code does. Which is why I recommended that you should get rid of the badly written code and write using more reliable code practices: well written code will waste less of your time (and be neater, more efficient, easier to debug, easier to understand, etc.). Read this to know why:
OK Stephen, I got the point :)
Can you help me write alternatives?
For example, instead of: cellfun(@(x) eval(['handles.' x ' =cell(size(Size_Parameter));']), handles.Names);
I can write:
for ii=1:numel(handles.Names)
eval(['handles.',handles.Names{ii} = cell(size(Size_Parameter));']);
end
But it still using "eval" function. any idea of how to creat these variables? (not fields)
for ii=1:numel(handles.Names)
handles.(handles.Names{ii}) = cell(size(Size_Parameter));
end
In the case where the handles struct starts out empty, then there is another way to do it in vectorized form involving cell2struct(), or a different way involving struct() and structfun(). There are probably other ways as well for that situation. They do not, however, apply for the case where handles already has content.
Thank you, this is great!

Sign in to comment.

 Accepted Answer

cellfun(@(x) logical(exist(x,'var')), handles.Names)
The exist() is going to be executed in the context of a function. It will test the existence of the given name as a variable in the workspace of the function, then as a parameter to the function (second), then as a shared variable in a nested function, then as a global variable that has been declared as global in the function. But the function context that the exist() is being executed in is the anonymous function, which has no saved variables and has one parameter named 'x' and is not a nested function and has no global declared in it. The only variable name that exists will therefore be 'x'. If there happened to be a 'x' in handles.Names then that one will succeed and all others will fail.
In order for this anonymous function to do anything more useful it would need to use evalin('caller')
If you do not need to know about parameters or shared variables, then you could instead
ismember(handles.Names, who())

1 Comment

ori yungrise
ori yungrise on 27 Nov 2018
Edited: ori yungrise on 27 Nov 2018
Hi Walter,
I wil use: "ismember(handles.Names, who())" and then "logical".
Any ideas about the other two comman lines?
Thank you!

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Release

R2018a

Community Treasure Hunt

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

Start Hunting!