{"id":787,"date":"2017-12-05T01:08:21","date_gmt":"2017-12-05T09:08:21","guid":{"rendered":"http:\/\/wonghoi.humgar.com\/blog\/?p=787"},"modified":"2017-12-05T01:50:39","modified_gmt":"2017-12-05T09:50:39","slug":"matlab-practices-code-and-variable-transparency-eval-is-one-letter-away-from-evil","status":"publish","type":"post","link":"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-practices-code-and-variable-transparency-eval-is-one-letter-away-from-evil\/","title":{"rendered":"MATLAB Practices: Code and variable transparency. eval() is one letter away from evil()"},"content":{"rendered":"<p>The general wisdom about <strong><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval()<\/code><\/strong> is: <strong>do not use it<\/strong>! At least not until you are really out of reasonable options after consulting more than 3 experts on the newsgroups, forums and <a href=\"mailto:support@mathworks.com\">support@mathworks.com<\/a> (if your SMS is current)!<\/p>\n<p>Abusing <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval()<\/code> turns it into <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">evil()<\/code>!<\/p>\n<p>The elves running inside MATLAB needs to be able to track your variables to reason through your code because:<\/p>\n<ul>\n<li>it helps your code run much faster (<code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval()<\/code> cannot be pre-compiled)<\/li>\n<li>able to use parallel computing toolbox (it has to know absolutely for sure about any shared writes)<\/li>\n<li>mlint can warn you about potentially pitfalls through code smell.<\/li>\n<li>it keeps you sane while debugging!<\/li>\n<\/ul>\n<p>This is called &#8216;transparency&#8217;: MATLAB has to see what you are doing every step of the way. According to MATLAB&#8217;s parallel computing toolbox&#8217;s <a href=\"https:\/\/www.mathworks.com\/help\/distcomp\/transparency.html\">documentation<\/a>,<\/p>\n<blockquote><p><em>Transparency means that all reference to variables must be visible in the text of the code<\/em><\/p><\/blockquote>\n<p>which I used as a subtitle of this post.<\/p>\n<hr \/>\n<p>The 3 major built-in functions that breaks transparency are:<\/p>\n<ol>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval(), evalc()<\/code>: arbitrary code execution resulting in read and write access to its caller workspace.<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">assignin()<\/code>: it poofs variables in its caller&#8217;s workspace!<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">evalin()<\/code>: it breaks open the stack and read the variables in its caller&#8217;s workspace!<\/li>\n<\/ol>\n<p>They should have been replaced by skillful use of dynamic field names, advanced uses of left assignment techniques, and freely passing variables as input arguments (remember MATLAB uses copy-on-write: nothing is copied if you just read it).<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<p>There are other frequently used native MATLAB functions (under certain usages) that breaks transparency:<\/p>\n<ol>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">load()<\/code>: poof variables from the file to the workspace. The best practice is to load the file as a struct, like <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">S=load('file.mat');<\/code>\u00a0, which is fully transparent. Organizing variables into structs actually reduces mental clutter (namespace pollution)!<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">save(), who(), whos()<\/code>: basically anything that takes variable names as input and act on the requested variable violates transparency because it&#8217;s has the effect of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">evalin()<\/code>. I guess the <code class=\"EnlighterJSRAW\" style=\"text-indent: -1.5em;\" data-enlighter-language=\"matlab\">save()<\/code><span style=\"text-indent: -1.5em; font-size: 1.0625rem;\"> function chose to use variable names instead of the actual variables as input because copy-on-write wasn&#8217;t available in early days of MATLAB. A example workaround would be:<\/span>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function save_transparent(filename, varargin)\r\n    VN = arrayfun(@inputname, (2:nargin)', 'UniformOutput', false);     \r\n    if( any( cellfun(@isempty, VN) ) )\r\n        error('All variables to save must be named. Cannot be temporaries');\r\n    end\r\n    \r\n    S = cell2struct(varargin(:), VN, 1);\r\n    save(filename, '-struct', 'S');\r\nend\r\n\r\nfunction save_struct_transparent(filename, S)\r\n    save(filename, '-struct', 'S');\r\nend<\/pre>\n<\/li>\n<\/ol>\n<p>The good practices to avoid non-transparent load\/save also reduces namespace pollution. For example, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">inputname()<\/code> peeks into the caller to see what the variable names are, which should not be used lightly. The example above is one of the few uses that I consider justified. I&#8217;ve seen novice abusing <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">inputname()<\/code> because they were not comfortable with cells and structs yet, making it a total mindfuck to reason through.<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_787\" class=\"pvc_stats all  \" data-element-id=\"787\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The general wisdom about eval() is: do not use it! At least not until you are really out of reasonable options after consulting more than 3 experts on the newsgroups, forums and support@mathworks.com (if your SMS is current)! Abusing eval() &hellip; <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-practices-code-and-variable-transparency-eval-is-one-letter-away-from-evil\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_787\" class=\"pvc_stats all  \" data-element-id=\"787\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[10],"tags":[],"class_list":["post-787","post","type-post","status-publish","format-standard","hentry","category-matlab"],"_links":{"self":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/787","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/comments?post=787"}],"version-history":[{"count":6,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/787\/revisions"}],"predecessor-version":[{"id":800,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/787\/revisions\/800"}],"wp:attachment":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/media?parent=787"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/categories?post=787"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/tags?post=787"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}