TUTORIAL: Why Variables Should Not Be Named Dynamically (eval)
4,233 views (last 30 days)
Show older comments
Summary:
Dynamically accessing variable names can negatively impact the readability of your code and can cause it to run slower by preventing MATLAB from optimizing it as well as it could if you used alternate techniques. The most common alternative is to use simple and efficient indexing.
Explanation:
Sometimes beginners (and some self-taught professors) think it would be a good idea to dynamically create or access variable names, the variables are often named something like these:
- matrix1, matrix2, matrix3, matrix4, ...
- test_20kmh, test_50kmh, test_80kmh, ...
- nameA, nameB, nameC, nameD,...
Good reasons why dynamic variable names should be avoided (click the links to jump to the "answers" below):
- Slow
- Buggy
- Security Risk
- Difficult to Work With
- Obfuscated Code Intent
- Confuses Data with Code
- Code Helper Tools do not Work
- Magically Making Variables Appear in a Workspace is Risky
There are much better alternatives to accessing dynamic variable names:
- Indexing into Cell Array or ND-Array
- Non-scalar Structures (with Indexing)
- Dynamic Field-Names in a Structure
- load into a Structure, not into the Workspace
- save the Fields of a Scalar Structure
- Use a table or timetable Array
- Use more Efficient Ways to Pass Variables Between Workspaces
Note that avoiding eval (and assignin, etc.) is not some esoteric MATLAB restriction, it also applies to many other programming languages as well:
MATLAB Documentation:
If you are not interested in reading the answers below then at least read MATLAB's own documentation on this topic Alternatives to the eval Function, which states "A frequent use of the eval function is to create sets of variables such as A1, A2, ..., An, but this approach does not use the array processing power of MATLAB and is not recommended. The preferred method is to store related data in a single array." Data in a single array can be accessed very efficiently using indexing.
Note that all of these problems and disadvantages also apply to functions load (without an output variable), assignin, evalin, and evalc, and the MATLAB documentation explicitly recommends to "Avoid functions such as eval, evalc, evalin, and feval(fname)".
The official MATLAB blogs explain why eval should be avoided, the better alternatives to eval, and clearly recommend against magically creating variables. Using eval comes out at position number one on this list of Top 10 MATLAB Code Practices That Make Me Cry. Experienced MATLAB users recommend avoiding using eval for trivial code, and have written extensively on this topic.
9 Comments
DGM
on 8 Dec 2022
I find it surprising that we haven't found more use for the "make me cry" tag. I'll have to keep that in mind. :D
More Answers (19)
Stephen23
on 26 Sep 2016
Edited: Stephen23
on 24 Nov 2022
3 Comments
Steven Lord
on 23 Oct 2019
Running the char command is safe, that will just create a char vector you can read. Remove the eval() around the char command and it won't execute the command stored in the char vector.
Stephen23
on 26 Sep 2016
Edited: Stephen23
on 25 Nov 2022
1 Comment
Tom Hawkins
on 7 Feb 2019
On this topic, it would be great if the Code Analyzer and checkcode would actually flag a warning when eval etc. are used. Perhaps that would cut down the number of questions about them on here?
Stephen23
on 19 Jul 2017
Edited: Stephen23
on 17 Feb 2023
6 Comments
Walter Roberson
on 21 Aug 2019
There is currently some name re-resolution being done whenever the MATLAB path changes, including when you cd() -- which is a reason to avoid cd() in code.
In the past, I put some thought into the kinds of structures you would have to put in place in order to handle that situation efficiency . I did not follow it through, though; just some thought experiments.
Stephen23
on 26 Sep 2016
Edited: Stephen23
on 25 Nov 2022
2 Comments
Walter Roberson
on 26 Jan 2022
MATLAB supports targetting systems with Harvard architecture -- systems where the instructions and the data live in different address spaces, so the instructions are not data on such systems.
Steven Lord
on 30 Apr 2019
Edited: Steven Lord
on 30 Apr 2019
Alternative: Use a table or timetable Array
table (introduced in release R2013b) and timetable (introduced in release R2016b) arrays allow you to store data with row and/or column names with which you can access the data. For example, if you create a table with variables named Age, Gender, Height, Weight, and Smoker and rows named with the last names of the patients:
load patients
patients = table(Age,Gender,Height,Weight,Smoker,...
'RowNames',LastName);
you can ask for all the ages of the first five patients:
patients(1:5, 'Age')
or all the data for the patients with last names Smith or Jones:
patients({'Smith', 'Jones'}, :)
You can also add new variables to the table, either by hard-coding the name of the variable:
% Indicate if patients are greater than five and a half feet tall
patients.veryTall = patients.Height > 66
or using variable names stored in char or string variables. The code sample below creates new variables named over40 and under35 in the patients table using different indexing techniques.
newname1 = 'over40';
patients.(newname1) = patients.Age > 40;
newname2 = 'under35';
patients{:, newname2} = patients.Age < 35;
patients(1:10, :) % Show the first ten rows
The code sample below selects either Height or Weight and shows the selected variable for the fifth through tenth patients using dynamic names.
if rand > 0.5
selectedVariable = 'Height';
else
selectedVariable = 'Weight';
end
patients.(selectedVariable)(5:10)
See this documentation page for more information about techniques you can use to access and manipulate data in a table or timetable array. This documentation page contains information about accessing data in a timetable using the time information associated with the rows.
Econstudent
on 17 Jan 2017
You discuss at length why we shouldn't A, B or C and you also comment on how we could access certain objects.
Now, suppose we need to import a few time series -- but I can only import those series one at a time. The intention behind creating a sequence of variables inside a loop is often to store those time series in distinct object every time. That is, you want to assign the data to a different object every time and do it considerably more than once...
What other choice do you have besides creating objects within your loop?
18 Comments
Samuel Gray
on 20 Feb 2022
Edited: Samuel Gray
on 20 Feb 2022
"But first you need to look at any significant C program intended for multiple operating systems, and look at the sheer amount of #ifdef in the headers. "
I think this is only a problem because we don't know exactly which #defines need to be included in the program, and what values they need to have, and where to get them.
So there's a lack of standardization in C/C++ You could always write programs in a "higher" language like Python, and let the developers of Python deal with those "C-level" problems. I'm sure that MS would help you with them if you'd just adopt VS 2019+ as your IDE, no problem.
I personally agree, C is one of the most frustrating languages to program in for that simple reason. C++ is like trying to program in C after taking acid. Let's make it harder by just throwing the code at a library full of header-files that are platform-specific. But part of that is because of Microsoft being Microsoft and walking into a part of people playing a game and changing the rules and changing all of the pieces and calling it the same game. They are only relevant to OS when they are in control. This is why you have entire segments of the x86 market that refuse to go anywhere near Windows.
But the BSD crowd is just as responsible for this for their simple failure to adhere to their own development guidelines and make makefiles that spell out for even the greenest C noob, exactly how to make and install their programs. And of course even that depends on the exact build environment. The one thing that MS is very good at is glomming onto OS without making OS-style mistakes. They do however often make MS-style mistakes and that is one reason why we still use Matlab. Without Matlab you'd have a bunch of little camps of people programming in different languages with little in common. And the great thing about having Matlab on Linux now is that hopefully you guys will abandon COM. And the Matlab features that rely on COM and likewise on Windows. Much of which could be written in VBA just as easily. COM is just a desperate attempt to duplicate functionality that's been in Unix for decades and now that Canonical has partnered with MS and has Ubuntu bundled with Windows, why would you even need COM in the first place? You can bundle Matlab with Ubuntu and there you go.
You just have to figure-out how to charge for Matlab ;)
(that's what the toolkits are for!)
...ultimately the BSD crowd is elitist and doesn't really care if someone finds it difficult to develop in their personal favorite flavor of Unix. That just means more work and more income for them. You want something easy to develop in, there's always Python, right? Programming in Python is a great idea until you find out that Python also is dependent on library-file versions. And certifying code? LOL
John Dzielski
on 19 Feb 2022
I have a question about a specific use case for the eval command. It is one I use frequently, and I would like to understand if and why it is bad. I data sets from a piece of instrumentation where either the filename or the variable name often includes some identifying string and some sort of numbering. When I write analysis scripts, I will typically assume the data is stored in a variable called something like 'data'. I will use a command like eval(['data=',namedVariable]) to assigne the value to 'data' and then run the script. I will often use the reverse of the argument to copy the processed data back to the same variable and save it to a file. These scripts are often LiveScripts and the plot titles often derive from 'namedVariable', so a function call is not a useful solution here. What is wrong with doing this? (If anything).
14 Comments
Rik
on 20 Feb 2022
There isn't any shame in not knowing a specific syntax that avoids the need for eval. Your mistake is in repeating 'I don't think there is a way to avoid eval here'. As we have now demonstrated several times, there usually is.
Please post the next one as a separate question so others can find the solution as well. (and don't assume the only way is eval)
See Also
Categories
Find more on Structures in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!