Writing function for symbolic and numeric input - matlab

I am writing a (rather big) pure function, which shall accept numeric and symbolic input. The problem I am facing is (mostly) with conversion symbolic expressions to logical expression. E.g., When I have a expression like syms x; assume( x, 'positive' ); and a test if( x>0 ); ..., then Matlab throws an error; Either:
Conversion to logical from sym is not possible.
or
Unable to prove 'x > 0' literally. Use 'isAlways' to test the statement mathematically.
depending on the context.
Up to now I solved this problem by rewriting all my ifs to if( isAlways(x>0) ); ... and adding a function isAlways in a folder #double, so that Matlab uses this function when it encounters a double.
The downside of this approach is, that I would have to write a isAlways function for each other type too (single, int8, ... ) (and also functions simplify,...).
Another approach of mine was, to write a function isAlways in the global namespace, and call the builtin isAlways when I encounter a sym. But, isAlways does not seem to be a built in, since Matlab reports
>> builtin('isAlways',sym(1));
Error using builtin
Cannot find builtin function 'isAlways'
Do you have any ideas how to solve this problem in a more elegant way, or at least another way?
Edit: I don't want to change the code of my function much, in particular don't want to add checks like switch class(x); case sym; ... case double;...`, but add "functionality" to Matlab such that it works out of the box for most functions.

In Matlab version approx R2018 I ended up defined a function isAlways in a folder #double etc.
Unfortunately, the behaviour changed around Matlab R2020. Now it is not possible anymore in a reliable way to add functions to classes. Thus, I now define a function isAlways in the global namespace, which gets called for each type which does not have an overload.
This is not the perfect solution, but it works at least.

Related

When is the eval function necessary?

I just read the following article from MathWorks which describes why it is important to avoid the eval function and lists alternatives to many of eval's common uses.
After reading the article, I have the impression that the eval function is neither useful nor necessary. So, my question is this: When is the eval function necessary?
I have found only one useful case for eval, and then the evalc variety: when calling a function with built-in command line call back (e.g. lines without ; or with disp calls), which you cannot modify. For instance when you got some obfuscated function that dumps heaps of stuff to your command window. In that case it's best to try and obtain the source code to modify that to your needs, as using evalc will mess up your performance. Otherwise, I have not found a case where eval is the best solution.
I wrote an extensive answer detailing why you should try to avoid eval as much as possible here: How to put these images together?
I have already used eval when trying to create multiple arrays with different names. This is not really recommended, but it worked for my specific application. For example, if I wanted to have N matrices with the specific names "matrix1" "matrix2" .. "matrixN" , one solution would be to manually type these in as "matrix1 = something" ... "matrixN = somethingelse". If N is really large, this is not ideal. Using eval , you could set up a for loop that would change the name of the matrix on every loop, and calculate some value based on that same N value.
Of course, ideally saving them in to a cell would be better, but I needed the arrays in the format I described.

Set function workspace to base in MATLAB

I have a rather bulky program that I've been running as a script from the MATLAB command line. I decided to clean it up a bit with some nested functions (I need to keep everything in one file), but in order for that to work it required me to also make the program itself a function. As a result, the program no longer runs in the base workspace like it did when it was a script. This means I no longer have access to the dozens of useful variables that used to remain after the program runs, which are important for extra calculations and information about the run.
The suggested workarounds I can find are to use assignin, evalin, define the variables as global, or set the output in the definition of the now function-ized program. None of these solutions appeal to me, however, and I would really like to find a way to force the workspace itself to base. Does any such workaround exist? Or is there any other way to do this that doesn't require me to manually define or label each specific variable I want to get out of the function?
Functions should define clearly input and output variables. Organizing the code differently will be much more difficult to understand and to modify later on. In the end, it will most likely cost you more time to work with an unorthodox style than investing in some restructuring.
If you have a huge number of output variables, I would suggest organizing them in structure arrays, which might be easy to handle as output variables.
The only untidy workaround I can imagine would use whos, assignin and eval:
function your_function()
x = 'hello' ;
y = 'world' ;
variables = whos ;
for k=1:length(variables)
assignin('base',variables(k).name,eval(variables(k).name))
end
end
But I doubt that this will help with the aim to clean up your program. As mentioned above I suggest ordering things manually in structures:
function out = your_function()
x = 'hello' ;
y = 'world' ;
out.x = x ;
out.y = y ;
end
If the function you would like to define are simple and have a single output, one option is to use anonymous functions.
Another option is to store all the variable you would like to use afterwards in a struct and have your big function return this struct as an output.
function AllVariables = GlobalFunction(varargin);
% bunch of stuff
AllVariables= struct('Variable1', Variable1, 'Variable2', Variable2, …);
end

How does scoping in Matlab work?

I just discovered (to my surprise) that calling the following function
function foo()
if false
fprintf = 1;
else
% do nothing
end
fprintf('test')
gives and error Undefined function or variable "fprintf". My conclusion is that the scope of variables is determined before runtime (in my limited understanding how interpretation of computer languages and specifically Matlab works). Can anyone give me some background information on this?
Edit
Another interesting thing I forgot to mention above is that
function foo()
if false
fprintf = 1;
else
% do nothing
end
clear('fprintf')
fprintf('test')
produces Reference to a cleared variable fprintf.
MATLAB parses the function before it's ever run. It looks for variable names, for instance, regardless of the branching that activates (or doesn't activate) those variables. That is, scope is not determined at runtime.
ADDENDUM: I wouldn't recommend doing this, but I've seen a lot of people doing things with MATLAB that I wouldn't recommend. But... consider what would happen if someone were to define their own function called "false". The pre-runtime parser couldn't know what would happen if that function were called.
It seems that the first time the MATLAB JIT compiler parses the m-file, it identifies all variables declared in the function. It doesn't seem to care whether said variable is being declared in unreachable code. So your local fprintf variable immediately hides the builtin function fprintf. This means that, as far as this function is concerned, there is no builtin function named fprintf.
Of course, once that happens, every reference within the function to fprintf refers to the local variable, and since the variable never actually gets created, attempting to access it results in errors.
Clearing the variable simply clears the local variable, if it exists, it does not bring the builtin function back into scope.
To call a builtin function explicitly, you can use the builtin function.
builtin( 'fprintf', 'test' );
The line above will always print the text at the MATLAB command line, irrespective of local variables that may shadow the fprintf function.
Interesting situation. I doubt if there is detailed information available about how the MATLAB interpreter works in regard to this strange case, but there are a couple of things to note in the documentation...
The function precedence order used by MATLAB places variables first:
Before assuming that a name matches a function, MATLAB checks for a variable with that name in the current workspace.
Of course, in your example the variable fprintf doesn't actually exist in the workspace, since that branch of the conditional statement is never entered. However, the documentation on variable naming says this:
Avoid creating variables with the same name as a function (such as i, j, mode, char, size, and path). In general, variable names take precedence over function names. If you create a variable that uses the name of a function, you sometimes get unexpected results.
This must be one of those "unexpected results", especially when the variable isn't actually created. The conclusion is that there must be some mechanism in MATLAB that parses a file at runtime to determine what possible variables could exist within a given scope, the net result of which is functions can still get shadowed by variables that appear in the m-file even if they don't ultimately appear in the workspace.
EDIT: Even more baffling is that functions like exist and which aren't even aware of the fact that the function appears to be shadowed. Adding these lines before the call to fprintf:
exist('fprintf')
which('fprintf')
Gives this output before the error occurs:
ans =
5
built-in (C:\Program Files\MATLAB\R2012a\toolbox\matlab\iofun\fprintf)
Indicating that they still see the built-in fprintf.
These may provide insight:
https://www.mathworks.com/help/matlab/matlab_prog/base-and-function-workspaces.html
https://www.mathworks.com/help/matlab/matlab_prog/share-data-between-workspaces.html
This can give you some info about what is shadowed:
which -all
(Below was confirmed as a bug)
One gotcha is that Workspace structs, and classes on the path, have particular scoping and type precedence that (if you are me) may catch you out.
E.g. in 2017b:
% In C.m, saved in the current directory
classdef C
properties (Constant)
x = 100;
end
end
% In Command window
C.x = 1;
C.x % 100
C.x % 1 (Note the space)
C.x*C.x % 1
disp(C.x) % 1

Can operators be stored in variables?

This is a thought example of what I am thinking of:
test = 'x > 0';
while str2func(test)
Do your thing
x=x-1;
end
Is it possible to store whole logical operations in a variable like this?
Of course the str2func will break here. If it is possible this function will likely be something else. And I have only added apostrophes to the test variable content, because I cannot think of what else would be the storing method.
I can see it usefull when sending arguments to functions and alike. But mostly I'm just wondering, because I have never seen it done in any programming language before.
You can store the textual representation of a function in a variable and evaluate it, for example
test = 'x > 0';
eval(test)
should result in 1 or 0 depending on x's value.
But you shouldn't use eval for reasons too-often covered here on SO for me to bother repeating. You should instead become familiar with functions and function handles. For example
test = #(x)x>0
makes test a handle to a function which tests whether its argument is greater than 0 or not.
Many languages which are interpreted at run-time, as opposed to compiled languages, have similar capabilities.

Use and implications of eval('expression') in MATLAB code?

I was encountered with usage of function eval(expression) in somebody else's code in matlab:
for example:
for n = 1 : 4
sn = int2str( n) ;
eval( [ 'saveas( fig' sn ', [ sName' sn ' ], ''fig'' ) ' ] );
end
MathWorks stuff in Matlab Help pointed out that:
Many common uses of the eval function are less efficient and are more difficult to read and debug than other MATLAB functions and language constructs.
After this, I find usage of this function in many other program languages, so as Python, JavaScript, PHP.
So I have a few questions:
Will usage of this function be enfluenced on the performance of my code?
If it will slow down execution, why does it occur?
If it slow down execution every time when called, what reason for use this function in principle?
The eval function is dangerous and there are very few examples where you actually need it. For example, the code you gave can easily be rewritten if you store the figure handles in an array fig(1), fig(2) etc and write
for n = 1:4
filename = sprintf('sName%d', n);
saveas(fig(n), filename, 'fig');
end
which is clearer, uses fewer characters, can be analysed by the Matlab editor's linter, is more easily modifiable if (when) you need to extend the code, and is less prone to weird bugs.
As a rule of thumb, you should never use eval in any language unless you really know what you are doing (i.e. you are writing a complicated Lisp macro or something else equivalent to manipulating the AST of the language - if you don't know what that means, you probably don't need to use eval).
There are almost always clearer, more efficient and less dangerous ways to achieve the same result. Often, a call to eval can be replaced with some form of recursion, a higher-order function or a loop.
Using eval here will certainly be slower than a non-eval version, but most likely it won't be a bottleneck in you code. However, the performance is only one issue, maintenance (incl. debugging), as well as readability are other ones.
The slowdown occurs because Matlab uses a JIT compiler, and eval lines cannot be optimized.
Eval use is in most cases due to lack of knowledge about the Matlab functionality that would be appropriate instead. In this particular case, the issue is that the figure handles are stored in variable names called fig1 through fig4. If they had been stored in an array called fig, i.e. fig(1) etc, eval would have been unnecessary.
EDIT Here are two excellent articles by Loren Shure about why eval should be avoided in Matlab. Evading eval, and More on eval.
For the most part, the slowdown occurs because the string has to be parsed into actual code. This isn't such a major issue if used sparingly, but if you ever find yourself using it in code that loops (either an explicit loop or things like JavaScript's setInterval()) then you're in for a major performance drop.
Common uses I've seen for eval that could be done better are:
Accessing property names in the ignorance of [] notation
Calling functions based on an argument name, which could instead be done with a switch (safer, prevents risk of code injection)
Accessing variables named like var1, var2, var3 when they should be arrays instead
To be honest, I don't think I've ever encountered a single situation where eval is the only way to solve a problem. I guess you could liken it to goto in that it's a substitute for program structure, or useful as a temporary solution to test a program before spending the time making it work optimally.
Here is another implication:
When you compile a program that uses eval, you must put pragmas that tell the compiler that some functions are needed. For example:
This code will compile and run well:
foo()
But this one needs a pragma added:
%#function foo
eval('foo()')
Otherwise you will encounter a runtime problem.