I need to repeat this code many times. It is part of system-tester.
testFvB=#(fBE,fMCS,CI)
{
d='FV';
dF=strcat('testing/systemTestFiles/D_', fBE, '_', fMCS, '_', d, '.txt');
bepo(fBE,CI,fMCS,d,dF,oF);
d='B';
oF=strcat('testing/systemTestFiles/O_', fBE, '_', fMCS, '_', d, '.txt');
bepo(fBE,CI,fMCS,d,dF,oF);
};
but
Error: File: systemTester.m Line: 3 Column: 6
The expression to the left of the equals sign is not a valid target for an
assignment.
I don't know but it looks like Matlab does not accept anonymous functions of this large size. So how to use anonymous functions to encapsulate larger codes not just things like doIt=#(x) x+1? Is the only way for the encapsulation here to create a new file?
[Update] not working, possible to make this into an execution?
test=#(fBE,fMCS)for d=1:2
for CI=0:0.25:1
if d==1
d='FV';
else
d='B';
end
oF=strcat('testing/systemTestFiles/O_', fBE, '_', fMCS, '_', d, '.txt');
bepo(fBE,CI,fMCS,d,dF,oF);
end
end;
fBE='TestCase1 BE Evendist v2.txt';
fMCS='TestCase1 MCS.txt';
test(fBE,fMCS)
Anonymous functions can only contain a single executable statement.
So in your case, just create a regular M-file function.
If you are interested, there is a series of articles on Loren Shure's blog introducing functional programming style, using anonymous functions to do non-simple tasks.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I already showed that the performance of str2func is better, but I got a lot of comments stating that there are more fundamental reasons to not use eval. Which fundamental reasons do apply to eval and do not apply to str2func in the following situation:
f='a^x+exp(b)+sin(c*x)+d'
eval:
y = eval(f)
or (suggested by rahnema1)
fHandle = eval(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
str2func:
fHandle = str2func(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
Why is the first option worse than the second one except for performance reasons?
Remarks
Note that I'm aware that it is good practice to avoid both methods if possible.
Note that I assign the output of eval to a variable, which avoids a lot of tricky code from being executed.
Stop trying to downplay the security risk that is eval. Running arbitrary code can be harmful if you don't fully control the input. If you fully control the input, there is almost always a better way that doesn't involve dynamic code generation.
You insist on a specific example:
>> ls TMPFILE
Error using ls (line 35)
ls: cannot access 'TMPFILE': No such file or directory
>> y = eval('system(''touch TMPFILE'')');
>> y
y =
0
>> ls TMPFILE
TMPFILE
touch is a very friendly unix command; it creates an empty file. Imagine rm -rf ~ in the same context.
Let's try it with str2func:
>> y = str2func('system(''touch TMPFILE2'')');
Warning: The input to STR2FUNC "system('touch TMPFILE2')" is not a valid function name. This will generate an error in a future release.
>> ls TMPFILE2
Error using ls (line 35)
ls: cannot access 'TMPFILE2': No such file or directory
>> y
y =
function_handle with value:
#system('touch TMPFILE2')
>> y()
Undefined function or variable 'system('touch TMPFILE2')'.
Side note: while the risk of eval is real and not just due to superstition, not using eval doesn't necessarily mean you're safe. My favourite example, the sneaky devil of str2num:
>> x = str2num('[system(''touch TMPFILE3'')]')
x =
0
>> ls TMPFILE3
TMPFILE3
So even if you're not explicitly using eval, it might happen that a convenience function you're using instead does. You should always make sure that this doesn't happen: use the safe str2double instead of str2num, and use str2func instead of eval (since we saw above that str2func won't execute arbitrary code).
First, performance (especially x100 slower) should be enough reason to not use something.
However, you are missing the point. You are now asking "why not use eval in the specific example of evaluating a function in a string?". Well, the answer of that is because you have a function called str2func to specifically do this job faster and more safely. The reason you should not use eval is because in the cases you want to use eval, the logic of your code is flawed.
The only reason to eval is to evaluate an arbitrary input that is not just a function on a string (why would you do that, you already showed that there is an specific function for it). If you know what you are evaluating, then you don't need eval, you can write code for what you expect. Thus, eval is only of use when you accept generic inputs. But generic inputs include rm -rf to delete your whole OS. Or in a less catastrophic case, the code may rewrite over a variable that is important for the rest of the algorithm. It is obvious why you dont want to let your code run arbitrary inputs.
What about dynamic variables? A terrible idea that can be generated using eval. And you may accidentally make this by accepting arbitrary inputs.
But there are more things. eval does make your code unreadable. You have no idea what the code does, until runtime.
I have seen code that does this within its core functions
model.solve_algorithm=eval(['default(',[ class(input3) ],')']);
result=eval(model.solve_algorithm);
What does the code do? What are the options? There is no way to know, unless you run it, and see where it goes. This makes the code obfuscated and hard to read, and certainly hard to maintain. Being explicit in code is something that does benefit a lot in maintainability of code.
TLDR: In any case that you may want to use eval, one of the two is happening:
There is a better, more specific function for what you want to do
You really should not be doing what you are trying to do, code/logic needs restructuring.
I'll put aside the arguments against both methods for a moment, although they are all very valid and a conscientious reader should try to understand them.
I can see two clear differences. For these examples we have to assume you've constructed the input string to the functions in your script, using some variable data, and assume it could be anything (by mistake or otherwise). So we prepare and account for the worst case.
str2func includes some extra checks to make sure what you've passed is a valid function, which might avoid unwanted behaviour. Let's not take the stance of "yeah but you could do it this way to avoid that" and look at an example...
% Not assigning an output variable
% STR2FUNC: You've harmlessly assigned ans to some junk function
str2func('delete test.txt')
% EVAL: You've just deleted your super important document
eval('delete test.txt')
% Assigning an output variable
% STR2FUNC: You get a clear warning that this is not a valid function
f = str2func('delete test.txt')
% EVAL: You can a non-descript error "Unexpected MATLAB expression"
f = eval('delete test.txt')
Another difference is the subject of about half the str2func documentation. It concerns variable scopes, and is found under the heading "Examine Differences Between str2func and eval".
[Intro to the function]
If you use a character vector representation of an anonymous function, the resulting function handle does not have access to private or local functions.
[Examine Differences Between str2func and eval]
When str2func is used with a character vector representing an anonymous function, it does not have access to the local function [...]. The eval function does have access to the local function.
So to conclude, you might have use cases where each function is preferable depending on your desired error handling and variable scoping should never use eval or str2func wherever possible, as stated in the other answers.
TL;DR - eval has access to locally defined functions while str2func does not. The "right" function to use among these two depends on the structure of your code.
Without getting into the whole "why eval is bad" discussion, I shall try to focus on the relevant piece of MATLAB documentation that discusses it in the context of your question:
Consider a file with two functions:
function out = q46213509
f='a^x+exp(b)+sin(c*x)+d';
fHandle = {eval(['#(x, a, b, c, d) ' f]), str2func(['#(x, a, b, c, d) ' f])};
out = [fHandle{1}(1,2,3,4,5) fHandle{2}(1,2,3,4,5)];
end
function e = exp(x)
e = x.^0./factorial(0) - x.^1./factorial(1) + x.^2./factorial(2); % Error is deliberate
end
When you run the above, it results in :
ans =
8.7432 26.3287
If you're working with classes and you define your own operators this might get out of hand... Let's say somebody decided to add a file to your MATLAB path, and conveniently give it the name of some function you use, or that of an overloadable operator (i.e. mpower.m):
function out = mpower(varargin)
% This function disregards all inputs and prints info about the calling workspace.
disp(struct2cell(evalin('caller','whos')));
end
While in some cases, MATLAB protects from redefinition of builtin functions, I bet the scenario above might confuse str2func quite a lot...
I am exporting symbolic expression from Matlab to Fortran. Consider the following example,
>> syms a b c d real;
>> expr=(a+b+c)+(a+b+c)^2+(a+b+c)^3+(a+b+c)^4+(a+b+c)^5+(a+b+c)^6+(a+b+c)^7+(a+b+c)^8+(a+b+c)^9+(a+b+c)^10+(a+b+c)^11+(a+b+c)^12;
>> fortran(expr)
the output from Matlab is:
t0 = a+b+c+(a+b+c)**2+(a+b+c)**3+(a+b+c)**4+(a+b+c)**5+(a+b+c)**6+
&(a+b+c)**7+(a+b+c)**8+(a+b+c)**9+(a+b+c)**10+(a+b+c)**11+(a+b+c)**
&12
This is normal for the so-called "fixed form" of Fortran, where an ampersand appears at the beginning of each line. However, the "free form" or free-format of Fortran, requires ampersands at the end of each line as well, i.e.,
t0 = a+b+c+(a+b+c)**2+(a+b+c)**3+(a+b+c)**4+(a+b+c)**5+(a+b+c)**6+&
&(a+b+c)**7+(a+b+c)**8+(a+b+c)**9+(a+b+c)**10+(a+b+c)**11+(a+b+c)**&
&12
This is obviously annoying when using really big expressions, since one would have either to put manually every ampersand at the end of each line or make a shell script to do it. Is there any output of Matlab that exports the expressions in the latest format that I showed?
the ampersand on the continued line is not needed in freeform. You can fix this with a simple string replacement:
ee=(a+b+c)+(a+b+c)^2+(a+b+c)^3+(a+b+c)^4+(a+b+c)^5+(a+b+c)^6+(a+b+c)^7+(a+b+c)^8+(a+b+c)^9+(a+b+c)^10+(a+b+c)^11+(a+b+c)^12;
fstring=fortran(ee)
t0 = a+b+c+(a+b+c)**2+(a+b+c)**3+(a+b+c)**4+(a+b+c)**5+(a+b+c)**6+
+(a+b+c)**7+(a+b+c)**8+(a+b+c)**9+(a+b+c)**10+(a+b+c)**11+(a+b+c)**
+12
strrep(fstring,[char(10) ' +'],[' &' char(10)])
t0 = a+b+c+(a+b+c)**2+(a+b+c)**3+(a+b+c)**4+(a+b+c)**5+(a+b+c)**6+ &
(a+b+c)**7+(a+b+c)**8+(a+b+c)**9+(a+b+c)**10+(a+b+c)**11+(a+b+c)** &
12
notice my matlab used a '+' for the fixed-form continuation marker. You must use an ampersand at the end for free form.
You could also just get rid of the continuation:
strrep(fstring,[char(10) ' +'],'')
t0 = a+b+c+(a+b+c)**2+(a+b+c)**3+(a+b+c)**4+(a+b+c)**5+(a+b+c)**6+(a+b+c)**7+(a+b+c)**8+(a+b+c)**9+(a+b+c)**10+(a+b+c)**11+(a+b+c)**12
for a reasonable amount of code I'd do that and then manually insert line breaks as needed. (standard free form has a 130 char/line limit )
In SAS/IML is it possible to change a variable if only a macro with its name is available? Using symget on left side produces mistake:
proc iml;
variable = 0;
call symput ('macVar', 'variable');
/* &macVar = 1;*/
symget('macVar') = 1;
print variable;
quit;
ERROR 180-322: Statement is not valid or it is used out of proper order.
The &-sign works, but the code is in a do-loop and symget must be used.
The problem stems from task to write a function that accepts variable number of arguments and processes them in several do-loops. It is connected with the following questions:
SAS IML use of Mattrib with Macro (symget) in a loop
SAS IML pass reference to variable defined in macro
Loop over names in SAS-IML?
In other languages (R, C++, Java, Matlab, etc..) the task is solved with help of abstraction.
Ideas?
SOLVED
Thanks a lot.
Useful article.
Use the VALSET subroutine:
call valset(symget('macVar'), 1);
You find the article "Read hundreds of data sets into matrices." helpful, since so many of your questions are about similar.
I have three lists of macros that have been created by a program, and I'm looking for an easy way to eliminate any dupes from the lists without looping back through the process that created them.
%let a=(1, 2, 3, 4);
%let b=(2, 8, 12);
%let c=(1, 3, 5, 7);
What I want is three new variables that have any overlap values eliminated, like this:
%let a_mod=(4);
%let b_mod=(8, 12);
%let c_mod=(5, 7);
I know there is probably a fairly straightforward way to do this in SAS. Any thoughts? Thanks.
What #Joe said in his comment is correct. Macro variables shouldn't be used to hold data; that's what datasets are for. Any solution that directly addresses the problem using macro functions and logic is likely to be fragile and error prone. Here is an approach that uses datasets. It's not entirely inelegant, at least in my opinion.
In your comment you mentioned that it's possible for you to store the values as datasets prior to creating the macro lists. That's great! I'll begin by assuming you have three datasets, a, b, and c, containing the values in a common variable called v.
First you want to join all three datasets.
proc sql;
create table abc as
select a.v as a,
b.v as b,
c.v as c
from a
full join b
on a.v = b.v
full join c
on a.v = c.v
quit;
In the resulting dataset, here called abc, you have columns a, b, and c, each containing the values from the dataset of the same name. Since the datasets were full joined, all of the values are present. Then in any given row, if only one of a, b, and c are non-missing, you have a non-duplicate.
Now you can separate the values back out, omitting duplicates, akin to your a_mod, etc. macro lists.
data a_mod(keep=a) b_mod(keep=b) c_mod(keep=c);
set abc;
if n(a, b, c) = 1 then do;
if a ne . then output a_mod;
else if b ne . then output b_mod;
else if c ne . then output c_mod;
end;
run;
The n() function counts the number of non-missing arguments.
Now if you need lists again for whatever the final use may be, you can recreate them using the into: clause in proc sql, for example:
proc sql noprint;
select a
into: a_mod
from a_mod
separated by ', ';
quit;
%let a_mod = (&a_mod); /* To get the surrounding parentheses back */
While this will get you what you want in the case of just a few lists like in your question, it's good to note that a simple approach such as this one gets ugly and/or annoying if you have a ton of lists.
In a matlab program I have an external parameter file that needs to be read in. Like
a = 1/3
b = 'test'
Currently I use textscan to read this file and use str2num to parse the values of a. However, I read that str2num use eval inside, which is undesirable for safety reason: what if someone made a = 'delete something', and then str2num will execute the string as a side effect. str2double does not work for fractional numbers. Is there any better way to parse 1/3 from external file into matlab?
If you are going to parse input that can only be a simple number or a division, the str2double/str2double approach may be sufficient. However if you want to parse input safely in general, I would recommend restricting the input.
For example like so:
rawString= 'dir+3/5'
safeCharacters = ['0':'9' '+-*/\^eEij. '];
if all(ismember(rawString,safeCharacters))
str2num(junkString)
end
Of course this may filter out some potentially good input like: str2num('rand')
Personally, I'd use str2num (which is based on eval if you read the documentation). However, another option is sym. The Symbolic Math toolbox is based on eval as well of course, but it has input validation to avoid the potential dangers you're worried about. It is very robust and simple to use for what you need:
a = '1/3';
a = double(sym(a))
This also handles converting cell arrays of strings to vectors and matrices gracefully:
a={'1/3','1/33','1/333'; ...
'2/3','2/33','2/333'};
a = double(sym(a))
The following unlikely input will return warnings and an error (and not delete a in memory):
b = 'delete a';
a = double(sym(b))
Thus you may want to use a try/catch statement to gracefully handle cases when a user may provide invalid input:
try
Xs = double(sym(X));
catch err
if strcmp(err.id,'MATLAB:UndefinedFunction')
error('YourFunctionName:UnknownInput','Your helpful message here.');
else
rethrow(err);
end
end
You could equally replace the Xs = double(sym(X)); line with a call to str2num.
You can explicitly search for the backslash with strfind.
if ~isempty(strfind(X, '/'))
% then use str2num
else
% use str2double, and if this returns a NaN, then it is a string
end
Or use strtok to split the string using '/' as a token, and use str2double on all resulting elements.