equivalent of `evalin` that doesn't require an output argument (internally) - matlab

Background -- I was reading up on accessing shadowed functions, and started playing with builtin . I wrote a little function:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
This throws the error:
Error using clear
Too many output arguments.
I think this happens because evalin demands an output from whatever it's being fed, but clear is one of the functions which has no return value.
So two questions: am I interpreting this correctly, and if so, is there an alternative function that allows me to execute a function in the parent environment (that doesn't require an output)?
Note: I'm fully aware of the arguments against trying to access shadowed funcs (or rather, to avoid naming functions in a way that overload base funcs, etc). This is primarily a question to help me learn what can and can't be done in MATLAB.
Note 2
My original goal was to write an overload function that would require an input argument, to avoid the malware-ish behavior of clear, which defaults to deleting everything. In Q&D pseudocode,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end

There's a couple issues with your clear override:
It will always clear in the base workspace regardless of where it's called from.
It doesn't support multiple inputs, which is a common use case for clear.
Instead I'd have it check for whether it was called from the base workspace, and special-case that for your check for whether it's clearing everything. If some function is calling plain clear to clear all its variables, that's bad practice, but it's still how that function's logic works, and you don't want to break that. Otherwise it could error, or worse, return incorrect results.
So, something like this:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
I hope it goes without saying that this is an atrocious hack that I wouldn't recommend in practice. :)

What happens in your code:
evalin('base', builtin('clear','x'));
is that builtin is evaluated in the current context, and because it is used as an argument to evalin, it is expected to produce an output. It is exactly the same as:
ans = builtin('clear','x');
evalin('base',ans);
The error message you see occurs in the first of those two lines of code, not in the second. It is not because of evalin, which does support calling statements that don't produce an output argument.
evalin requires a string to evaluate. You need to build this string:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(In MATLAB, the quote character is escaped by doubling it.)
You function thus would look like this:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(Inserting a string into another string this way is rather awkward, one of the many reasons I don't like eval and friends).
It might be better to use evalin('caller',...) in this case, so that when you call the new clear from within a function, it deletes something in the function's workspace, not the base one. I think 'base' should only be used from within a GUI that is expected to control variables in the user's workspace, not from a function that could be called anywhere and is expected (by its name in this case) to do something local.
There are reasons why this might be genuinely useful, but in general you should try to avoid the use of clear just as much as the use of eval and friends. clear slows down program execution. It is much easier (both on the user and on the MATLAB JIT) to assign an empty array to a variable to remove its contents from memory (as suggested by rahnema1 in a comment. Your base workspace would not be cluttered with variables if you used function more: write functions, not scripts!

Related

MATLAB bug? "Undefined function or variable" error when using same name for function and variable

It is occasionally convenient to use a function as a "constant" variable of sorts in MATLAB. But when I was using this feature recently, I ran into an unexpected error. When I run the MWE below, I get the error Undefined function or variable 'a'. despite the function being clearly available in the same file. When I comment out the if statement, the error goes away. This seems to imply that MATLAB is pre-interpreting a as a variable even though the variable assignment line is never reached, ignoring the fact that there is a function by the same name. Is this a MATLAB bug or is it somehow the desired behavior?
Here is the MWE:
function matlabBugTest( )
if false
a = 'foo';
end
a
end
function b = a()
b = 'bar';
end
Follow-up:
I know it seems weird to intentionally use the same name for a variable and a function, so I'll give an example of where this can be useful. For instance, you may want to use a function to store some constant (like a file path), but also want to be able to use a different value in case the function cannot be found. Such a case might look like:
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
I know that language design decisions are often difficult and complicated, but one of the more unfortunate consequences of MATLAB's choice here to ignore the function by the same name is that it breaks compatibility between functions and scripts/command line. For instance, the following runs without issue in a script:
if false
a = 'foo';
end
a
where the function a (shown above) is saved in its own file.
It has to do with how Matlab performs name-binding at compilation time. Because matlabBugTest has a line that assigns a value to a, a is determined to be a variable, and the later line with a is a reference to that variable and not a call to the local function. More modern versions of Matlab, like my R2015a install, gives a more clear error message:
At compilation, "a" was determined to be a variable and this variable is uninitialized. "a" is also a function name and previous versions of MATLAB would have called the
function. However, MATLAB 7 forbids the use of the same name in the same context as both a function and a variable.
It's not so much a bug, as it is an ambiguity introduced by the naming scheme that was given a default resolution method, which can be annoying if you have never encountered the problem before and m-lint doesn't mark it. Similar behavior occurs when variables are poofed into the workspace without initialization beforehand.
So the solution is to either change the name of the function or the variable to different things, which I would argue is good practice anyways.
In considering your follow-up example, I have noticed some interesting behavior in moving things around in the function. Firstly, if the function is either external or nested, you get the behavior discussed very well by Suever's answer. However, if the function is local, you can get around the limitation (at least you can in my R2014b and R2015a installs) by invoking the function prior to converting it to a variable as long as you initialize it or explicitly convert it to a variable at some point. Going through the cases, the following bodies of matlabBugTest perform thusly:
Fails:
a
if false
a = 'foo';
end
a
Runs:
a
if true
a = 'foo';
end
a
Runs:
a = a;
if false % runs with true as well.
a = 'foo';
end
a
I'm not entirely sure why this behavior is the way it is, but apparently the parser handles things differently depending on the scope of the function and the order of what symbols appear and in what contexts.
So assuming this behavior hasn't and will not change you could try something like:
pathConstant = pathConstant;
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
Though, entirely personal opinion here, I would do something like
pathConstant = getPathConstant();
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
Concerning breaking "compatibility between functions and scripts/command line", I don't really see this as an issue since those are two entirely different contexts when it comes to Matlab. You cannot define a named function on the command line nor in a script file; therefore, there is no burden on the Matlab JIT to properly and unambiguously determine whether a symbol is a function call or a variable since each line executes sequentially and is not compiled (aside from certain blocks of code the JIT is designed to recognize and optimize like loops in scripts). Now as to why the above juggling of declarations works, I'm not entirely sure since it relies on the Matlab JIT which I know nothing about (nor have I taken a compiler class, so I couldn't even form an academic reason if I wanted).
The reason that you get this behavior is likely that Matlab never have implemented scope resolution for any of their statements. Consider the following code,
(a)
if true
a = 'foo';
end
disp(a)
This would actually display "foo". On the other hand would,
(b)
if false
a = 'foo';
end
disp(a)
give you the error Undefined function or variable "a". So let us consider the following example,
(c,1)
enterStatement = false;
if enterStatement
a = 'foo';
end
disp(a)
(c,2)
enterStatement = mod(0,2);
if enterStatement
a = 'foo';
end
disp(a)
TroyHaskin clearly states the following in his answer
It has to do with how Matlab performs name-binding at compilation time. Because matlabBugTest has a line that assigns a value to a, a is determined to be a variable, and the later line with a is a reference to that variable and not a call to the local function
Matlab does not support constant expressions and does only a limited amout of static code analysis. In fact, if the if statement takes argument false, or if enterStatement is false, Matlab provides a warning, This statement (and possibly following ones) cannot be reached. If enterStatement is set to false Matlab also generates another warning, Variable a is used, but might be unset. However if enterStatement = mod(0,2), so to say if enterStatement calls a function, you get no warning at all. This means that if the example in the question was allowed then (c,2) would compile based on how the function were evaluated and that is a contradiction. This would mean that the code would have to compile based on its runtime results.
Note: Sure it could be good if Matlab could generate an error in case the enterStatement was an expression instead of a constant false, but whether or not this is possible it would depend on implementation I guess.

how single and double type variables work in the same copy of code in Matlab like template in C++

I am writing a signal processing program using matlab. I know there are two types of float-pointing variables, single and double. Considering the memory usage, I want my code to work with only single type variable when the system's memory is not large, while it can also be adapted to work with double type variables when necessary, without significant modification (simple and light modification before running is OK, i.e., I don't need runtime-check technique). I know this can be done by macro in C and by template in C++. I don't find practical techniques which can do this in matlab. Do you have any experience with this?
I have a simple idea that I define a global string containing "single" or "double", then I pass this string to any memory allocation method called in my code to indicate what type I need. I think this can work, I just want to know which technique you guys use and is widely accepted.
I cannot see how a template would help here. The type of c++ templates are still determined in compile time (std::vector vec ...). Also note that Matlab defines all variables as double by default unless something else is stated. You basically want runtime checks for your code. I can think of one solution as using a function with a persistent variable. The variable is set once per run. When you generate variables you would then have to generate all variables you want to have as float through this function. This will slow down assignment though, since you have to call a function to assign variables.
This example is somehow an implementation of the singleton pattern (but not exactly). The persistent variable type is set at the first use and cannot change later in the program (assuming that you do not do anything stupid as clearing the variable explicitly). I would recommend to go for hardcoding single in case performance is an issue, instead of having runtime checks or assignment functions or classes or what you can come up with.
function c = assignFloat(a,b)
persistent type;
if (isempty(type) & nargin==2)
type = b;
elseif (isempty(type))
type = 'single';
% elseif(nargin==2), error('Do not set twice!') % Optional code, imo unnecessary.
end
if (strcmp(type,'single'))
c = single(a);
return;
end
c = double(a);
end

How to safely manipulate MATLAB anonymous functions in string form

I have an anonymous function that I would like to manipulate in string form then use with fsolve.
When I do this the references in the anonymous function to constants are lost and fsolve fails.
The problem is easily illustrated.
The following works:
A=3;
myfun=#(x)sin(A*x);
x = fsolve(#(x)myfun(x),[1 4],optimoptions('fsolve','Display','off'))
The following throws an error as explained here:
A=3;
myfun=#(x)sin(A*x);
mystring=func2str(myfun);
%string operations would go here such as strrep(mystring,'A','A^2') or whatever
myfun2=str2func(mystring);
x = fsolve(#(x)myfun2(x),[1 4],optimoptions('fsolve','Display','off'))
Is there some way I CAN safely manipulate an anonymous function while retaining references to constant parameters?
more info
Specifically I'm writing a simple wrapper to allow fsolve to accept imaginary numbers for simple cases. The following illustrates a working example without a constant parameter:
myeqn=#(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
f1=strrep(func2str(myeqn),'#(x)','');
f2=strrep((f1),'x','(x(1)+(x(2))*1i)');
f3=strcat('#(x)[real(',f2,'); imag(',f2,')]');
fc=str2func(f3);
opts=optimoptions('fsolve','Display','off');
result=arrayfun(#(cinput)[1 1i]*(real(fsolve(fc,[real(cinput);imag(cinput)],opts))),cX0)
As in the failed example above if I include a parameter in my wrapper the process fails with the same error as above.
I originally suggested to use the symbolic math toolbox, but reading your question again I realized it's just a simple substitution of input parameters. You can achieve this using function handles without any string processing.
myeqn=#(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
wrapper=#(x,f)([real(f(x(1)+x(2)*i)),imag(f(x(1)+x(2)*i))])
opts=optimoptions('fsolve','Display','off');
result=arrayfun(#(cinput)[1 1i]*(real(fsolve(#(x)wrapper(x,myeqn),[real(cinput);imag(cinput)],opts))),cX0)
As much as I hate to suggest using the eval function, you could do:
myfun2 = eval(mystring);
Using eval is kinda frowned upon because it makes code hard to analyze (since arbitrary nastiness could be going on in that string), but don't let other people's coding style stop you from doing what works :)
In your longer example, this would correspond to changing the line:
fc=str2func(f3);
to:
fc=eval(f3);
Again, the use of eval is strongly discouraged, so you should consider alternatives to this type of string manipulation of function definitions.

Passing multiple inputs into a MATLAB function via loop?

I have multiple variables var_1, var_2, var_3....var_9 (they are named like that) that I want to pass in a function. All of the variables are saved in the workspace. The function takes 2 variables, and spits out an output. I want to compare var_1 with all the variables, including itself, so I prefer to automate it in a loop.
So I want to execute
function(var_1,var_1)--> display answer, function(var_1,var_2)--> display answer...function(var_1,var_9)-->display answer all at once in a loop. I've tried the following, with no luck:
for i=1:7
functionname(var_1,var_'num2str(i)')
end
Where did I go wrong?
You cannot make a dynamic variable name directly. But you can use the eval-function to evaluate an expression as a string. The string can be generated with sprintf and replaces %d with your value.
for i=1:7
eval(sprintf('functionname(var_1,var_%d)', i));
end
But: Whenever you can, you should avoid using the eval function. A much better solution is to use a cell array for this purpose. In the documentation of Matlab there is a whole article about the why and possible alternatives. To make it short, here is the code that uses a cell array:
arr = {val_1, val_2, val_3, val_4, val_5, val_6, val_7, val_8, val_9};
for i = 1:length(arr)
functionname(arr{1},arr{i})
end

Working with different version of Matlab Function

We have a legacy definition of a matlab function nanstd.m which is being called in a whole lot of functions.
The legacy version has definition like:
function y = nanstd(x, dim);
The above definition is stored on our local server drive "H\Util\Functions".
The newer version of matlab has a differetn definition which is:
function y = nanstd(fts, varargin)
The above translates to:
Y = nanstd(X,flag,dim)
The above is stored under "C\Program Files\Matlab".
We need both versions to be available. Is it possible that I can write a code which says something like if there are 2 arguments input use nanstd.m at "H\Util\Functions" and if there are 3 inputs use nanstd.m at "C\Program Files\Matlab".
Thanks
Since your legacy definition should come before the builtin version on your path, you could simply add the following to your custom nanstd so it behaves as follows:
function y = nanstd(x,varargin)
if nargin > 2
wd = cd(fullfile(matlabroot,'toolbox','stats','stats'));
y = nanstd(x,varargin{:});
cd(wd)
return
elseif nargin == 2
flag = varargin{1};
end
%// ... continue custom nanstd function
As per this discussion on MatlabCentral, the only way to run a shadowed function is to change to its directory. Amazingly enough, the path favors the current directory to the current function — something that surprised me — but it's beneficial for this case. This allows you to simply modify your custom legacy nanstd function to kick out to the builtin definition.
Edit: you may want to wrap the call to the stats nanstd with a try/catch so your directory always gets restored, even in case of an error.
Recommended approach
This is probably the way I would do it (if I didn't want to make a complete mess in the future).
Locate all old files, and replace nanstd( by nanstdold(, this can be automated in many ways.
(If you actually have variables named nanstd you will feel the pain of course)
Then, to be safe define your function as follows:
function y = nanstdold(fts, varargin)
if nargin = 2
y = nanstd(fts,[],varargin)
else
y = nanstd(fts,varargin)
end
You may need to tweak the first call to nanstd, but I think this line of thought should get you there.
Make sure to burn the nanstd function that only takes 2 input arguments, so you cannot accidentally refer to it.
Alternate approach
If you feel confident, you could try to design a replacement rule to automatically update all your old files without introducing a new function. Something to start with:
Find all occurences of
nanstd( + something+ comma that is not between {} or ()
And replace them with
nanstd( + something+ comma + flag argument + comma
Especially for this one you will want to back up your files first!