Loren on the Art of MATLAB

December 28th, 2005

Evading eval

If you are a regular reader of the MATLAB Usenet newsgroup, comp.soft-sys.matlab, found on the MathWorks User Community page, you are probably familiar with repeated advice to not use the MATLAB function eval . Today I plan to tell you more about why this is generally good advice.

Code Clarity / Readability

Statements containing a call to eval have a way of obscuring the underlying intent of the code though this is rarely a goal of the author. What do I mean by this? Well, in under 3 seconds, can you discern what the following code means?

a = who ;
a = a(~cellfun('isempty',regexp(a,'2$'))) ;
str = sprintf('%s,',a{:}) ;
str = sprintf('B = cat(1,%s) ;',str(1:end-1)) ;
eval(str) ;

Unless you are one of the proponents of this code pattern (see this newsgroup post, for example), you likely couldn't tell that the code is saying

Concatenate all variables that have '_2' in their name, i.e. a_2, b_2, c_2

Efficiency

When a function M-file is run in MATLAB for the first time in a session, MATLAB reads in the file, translates it into an internal representation, analyzes the contents, and executes the code. The next time you use this function in the same MATLAB session, assuming the file hasn't changed, MATLAB doesn't need to reread and translate the file.

However, if the M-file contains any calls to the function eval, at least those lines of code will need to be reinterpreted each time the function is run. Why? Because there is no guarantee, and it is generally not true, that the expression that was executed in the first instance is the same as subsequent ones. The expression may require different MATLAB functions or variables. In any case, to be sure MATLAB gets the right answer, at least the lines of code containing eval statements need to be re-analyzed with each invocation.

Analyzability

In an M-file, if the functions being called are coded into strings so they can be placed into eval statements, it is very difficult to build up a complete understanding of the functions and files that your M-file depends upon, especially in a static way. It might be possible, though probably difficult and perhaps error-prone, to scan through an M-file to see where strings are used in eval statements and to try to pull out the possible function and file names from these.

Techniques to evade eval

One Response to “Evading eval”

  1. George replied on :

    Thanks for a great article Loren,
    I came across it cause I have been experiencing problems with how terrebly slow the eval function is.
    I have a large code, and thought I could speed it up by avoiding some calculations and using the eval, but the running time exploded!
    Lesson:avoid eval by all means :)

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.