{"id":786,"date":"2017-12-05T01:35:29","date_gmt":"2017-12-05T09:35:29","guid":{"rendered":"http:\/\/wonghoi.humgar.com\/blog\/?p=786"},"modified":"2017-12-15T22:48:21","modified_gmt":"2017-12-16T06:48:21","slug":"matlab-techniques-variadic-variable-input-and-output-arguments","status":"publish","type":"post","link":"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-techniques-variadic-variable-input-and-output-arguments\/","title":{"rendered":"MATLAB Techniques: variadic (variable input and output) arguments"},"content":{"rendered":"<p>I&#8217;ve seen a lot of ugly implementations from people trying to deal with variable number of input and output arguments. The most horrendous one I&#8217;ve seen so far came from MIT&#8217;s Physionet&#8217;s WFDB MATLAB Toolbox. Here&#8217;s a snippet showing how <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">wfdbdesc.m<\/code> handles variable input and output arguments:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function varargout=wfdbdesc(varargin)\r\n% [siginfo,Fs,sigClass]=wfdbdesc(recordName)\r\n...\r\n%Set default pararamter values\r\ninputs={'recordName'};\r\noutputs={'siginfo','Fs','sigClass'};\r\n\r\nfor n=1:nargin\r\n    if(~isempty(varargin{n}))\r\n        eval([inputs{n} '=varargin{n};'])\r\n    end\r\nend\r\n...\r\nif(nargout&gt;2)\r\n    %Get signal class\r\n    sigClass=getSignalClass(siginfo,config);\r\nend\r\nfor n=1:nargout\r\n    eval(['varargout{n}=' outputs{n} ';'])\r\nend\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The code itself reeks a very &#8216;smart&#8217; beginner who didn&#8217;t RTFM. The code is so smart (shows some serious thoughts):<\/p>\n<ul>\n<li>Knows to use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">nargout<\/code> to control <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code> to avoid the side effects when no output is requested<\/li>\n<li>[Cargo cult practice]: (unnecessarily) track your variable names<\/li>\n<li>[Cargo cult practice]: using <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code> so it can be symmetric to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code> (also handled similarly). <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code> might have a benefit mentioned above, but there is absolutely no benefit to use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code> over direct variable names when you are not forwarding or use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">inputParser()<\/code>.<\/li>\n<li>[Cargo cult practice]: tries to be efficient to skip processing empty inputs. Judicially non-symmetric this time (not done to output variables)!<\/li>\n<\/ul>\n<p>but yet so dumb (hell of unwise, absolutely no good reason for almost every &#8216;thoughtful&#8217; act put in) at the same time.\u00a0Definitely MIT: Make it Tough!<\/p>\n<p>This code pattern is so wrong in many levels:<\/p>\n<ul>\n<li>Unnecessarily obscuring the names by using <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code>\/<code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code><\/li>\n<li>Managing a list of variable names manually.<\/li>\n<li>Loop through each item of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code> cells unnecessarily<\/li>\n<li>Use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval()<\/code>\u00a0just to do simple cell assignments! Makes me <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-practices-code-and-variable-transparency-eval-is-one-letter-away-from-evil\/\">cringe<\/a>!<\/li>\n<\/ul>\n<p>Actually, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">eval()<\/code> is not even needed to achieve all the remaining evils above. Could have used <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">S_in = cell2struct(varargin)<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout=struct2cell(S_out)<\/code> instead if one really wants to control the list of variable names manually!<\/p>\n<hr \/>\n<p>The hurtful sins above came from not knowing a few common cell packing\/unpacking idioms when dealing with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargout<\/code>, which are cells by definition. Here are the few common use cases:<\/p>\n<ol>\n<li>Passing variable arguments to another function (called perfect forwarding in C++): remember <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">C{:}<\/code> unpacks to comma separated lists!\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">function caller(varargin)\r\n   callee(varargin{:});<\/pre>\n<\/li>\n<li>Limiting the number of outputs to what is actually requested: remember <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">[C{:}]<\/code> on left hand side (assignment) means the outputs are distributed as components of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">C<\/code> that would have been unpacked as comma separated lists, i.e. <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">[C{:}] = f();<\/code> means <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">[C{1}, C{2}, C{3}, ...] = f();<\/code>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function varargout = f()\r\n\/\/ This will output no arguments when not requested,\r\n\/\/ avoiding echoing in command prompt when the call is not terminated by a semicolon\r\n    [varargout{1:nargout}] = eig(rand(3));<\/pre>\n<\/li>\n<li>You can directly modify varargin and varargout by cells without de-referencing them with braces!\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function varargout = f(varargin)\r\n\/\/ This one is effectively deal()\r\n    varargout = varargin(1:nargout);\r\nend\r\n\r\nfunction varargout = f(C)\r\n\/\/ This one unpacks each cell's content to each output arguments\r\n    varargout = C(1:nargout);\r\nend<\/pre>\n<\/li>\n<\/ol>\n<p>One good example combining all of the above is to achieve the <a href=\"https:\/\/blogs.mathworks.com\/loren\/2009\/04\/14\/convenient-nargout-behavior\/\">no-output argument<\/a> example in #2 yet neatly return the variables in the workspace directly by name.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function [a, b] = f()\r\n\/\/ Original way to code: will return a = 4 when \"f()\" is called without a semicolon\r\n    a = 4;\r\n    b = 2;\r\nend\r\n\r\nfunction varargout = f()\r\n\/\/ New way: will not return anything even when \"f()\" is called without a semicolon\r\n    a = 4;\r\n    b = 2;\r\n    varargout = manage_return_arguments(nargout, a, b);\r\nend\r\n\r\nfunction C = manage_return_arguments(nargs, varargin)\r\n    C = varargin(1:nargs);\r\nend<\/pre>\n<p>I could have skipped <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">nargs<\/code> in <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">manage_return_arguments()<\/code> and use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">evalin()<\/code>, but this will make the code nastily <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-practices-code-and-variable-transparency-eval-is-one-letter-away-from-evil\/\">non-transparent<\/a>. As a bonus, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">nargs<\/code> can be fed with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">min(nargout, 3)<\/code> instead of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">nargout<\/code> for extra flexibility.<\/p>\n<hr \/>\n<p>With the technique above, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">wfdbdesc.m<\/code> can be simply rewritten as:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">function varargout = wfdbdesc(recordName)\r\n% varargout: siginfo, Fs, sigClass\r\n...\r\nvarargout = manage_return_arguments(nargout, siginfo, Fs, sigClass);<\/pre>\n<p>Unless you are forwarding variable arguments (with technique#1 mentioned above), input arguments can be (and should be) named explicitly. Using <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">varargin<\/code> would not help you avoid padding the unused input arguments anyway, so there is absolutely no good reason to manage input variables with a flexible list. MATLAB already knows to skip unused arguments at the end as long as the code doesn&#8217;t need it. Use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"matlab\">exist('someVariable', 'var')<\/code>\u00a0instead.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_786\" class=\"pvc_stats all  \" data-element-id=\"786\" 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>I&#8217;ve seen a lot of ugly implementations from people trying to deal with variable number of input and output arguments. The most horrendous one I&#8217;ve seen so far came from MIT&#8217;s Physionet&#8217;s WFDB MATLAB Toolbox. Here&#8217;s a snippet showing how &hellip; <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2017\/12\/05\/matlab-techniques-variadic-variable-input-and-output-arguments\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_786\" class=\"pvc_stats all  \" data-element-id=\"786\" 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,6],"tags":[],"class_list":["post-786","post","type-post","status-publish","format-standard","hentry","category-matlab","category-note-to-self"],"_links":{"self":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/786","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=786"}],"version-history":[{"count":15,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/786\/revisions"}],"predecessor-version":[{"id":818,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/786\/revisions\/818"}],"wp:attachment":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/media?parent=786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/categories?post=786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/tags?post=786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}