MATLAB爱好者论坛-LabFans.com

MATLAB爱好者论坛-LabFans.com (https://www.labfans.com/bbs/index.php)
-   MATLAB技术文章 (https://www.labfans.com/bbs/forumdisplay.php?f=25)
-   -   Time for an Argument (https://www.labfans.com/bbs/showthread.php?t=22056)

poster 2019-11-24 15:00

Time for an Argument
 
<div class="content"><!--introduction--><p>For those Monty Python fans reading this post, check out the <a href="https://www.youtube.com/watch?v=DkQhK8O9Jik">Argument Clinic</a>. Recently both <a href="https://blogs.mathworks.com/pick/2019/10/04/leaf-pile/">Sean</a> and <a href="https://blogs.mathworks.com/pick/2019/09/27/new-with-r2019b-function-argument-validation/">Jiro</a>, <a href="https://blogs.mathworks.com/pick/2019/10/18/spider-plots-and-more-argument-validation/">twice!</a> posted about the new <a href="https://www.mathworks.com/help/matlab/matlab_prog/function-argument-validation-1.html"><tt>arguments</tt></a> capability available for input argument checking. I wanted to show you some more about this great feature! I've also discussed argument checking over the years, including <a href="https://blogs.mathworks.com/loren/2009/05/05/nice-way-to-set-function-defaults/">this post</a>.</p><!--/introduction--><h3>Contents</h3><div><ul><li><a href="#fb32d2e7-3f93-4f75-9055-6b61f5029df5">What Makes a Program Good, or Useful?</a></li><li><a href="#7280bf11-d561-4667-b47f-7aade7aabd70">Original error checking, circa 2007</a></li><li><a href="#08aaf7b6-a3df-4a5c-afea-e14db7efbcb6">Another solution, similar time frame</a></li><li><a href="#d8b467fc-318e-43ec-898b-60984729d933">And the modern way, circa 2019</a></li><li><a href="#7f42f890-ce80-4d41-a9e7-092bbc43da8e">Do you have arguments?</a></li></ul></div><h4>What Makes a Program Good, or Useful?<a name="fb32d2e7-3f93-4f75-9055-6b61f5029df5"></a></h4><p>Of course, this in the eye of the user frequently, but certainly it helps if you get informative messages when you misuse the program. These messages should help guide you so you can properly use the program without a major headache. To do so generally requires some amount of error checking on the part of the programmer, thinking about what can go wrong, and making sure to give good information if/when it does.</p><p>I'm going to show you some code snippets from a routine. The function in question is modeling the dynamics of a virus, given parameters such as the infection rate.</p><h4>Original error checking, circa 2007<a name="7280bf11-d561-4667-b47f-7aade7aabd70"></a></h4><p>In this first code, I will show you how we did some important error checking about 12 years ago. In 35 lines, we check to see if the user called the function this code is embedded in with 0, 1, or 5 inputs. And we check the types of the inputs. If not all the inputs are supplied by the user, we set the unsupplied variables with default values.</p><pre>% Allowing for variable number of arguments in
switch(nargin)
case 5
Tpoints = varargin{1}; % time to evaluate at
beta = varargin{2}; % infection rate
c = varargin{3}; % clearance rate of virus
delta = varargin{4}; % death rate of infected cells
p = varargin{5}; % viral production rate of infectious cells
case 1
Tpoints = varargin{1}; % time to evaluate at
beta = 3.4e-5; % infection rate
c = 3.3; % clearance rate of virus
delta = 3.4; % death rate of infected cells
p = 7.9e-3; % viral production rate of infectious cells
case 0
% Use all default values
Tpoints = 0:0.1:10; % time to evaluate at
beta = 3.4e-5; % infection rate
c = 3.3; % clearance rate of virus
delta = 3.4; % death rate of infected cells
p = 7.9e-3; % viral production rate of infectious cells
otherwise
error('virusSolve:Input:InvalidNumberOfInputs', ...
'This function expects 0, 1, or 5 inputs.');
end
% Error checking - make sure all inputs are valid
validateattributes(Tpoints, {'numeric'}, {'vector', 'nonnegative'},mfilename,'Tpoints',1);
validateattributes(beta , {'numeric'}, {'scalar', 'real'});
validateattributes(c , {'numeric'}, {'scalar', 'real'});
validateattributes(delta , {'numeric'}, {'scalar', 'real'});
validateattributes(p , {'numeric'}, {'scalar', 'real'});</pre><p>You can see heavy use of <tt><a href="https://www.mathworks.com/help/matlab/ref/validateattributes.html">validateattributes</a></tt> as well as the use of <a href="https://www.mathworks.com/help/matlab/ref/nargin.html"><tt>nargin</tt></a>, and <a href="https://www.mathworks.com/help/matlab/ref/switch.html"><tt>switch, case, otherwise</tt></a>.</p><h4>Another solution, similar time frame<a name="08aaf7b6-a3df-4a5c-afea-e14db7efbcb6"></a></h4><p>There was another solution availabe in about the same time frame using a function called <a href="https://www.mathworks.com/help/matlab/ref/inputparser.html"><tt>inputParser</tt></a>. Here's what that error checking code looks like.</p><pre>% Create input parser
ps = inputParser();
% Define optional arguments with default values and error checking
ps.addOptional('Tpoints', 0:0.1:10, ...
@(x) validateattributes(x, {'numeric'}, {'vector', 'nonnegative'}));
ps.addOptional('beta', 3.4e-5, ...
@(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
ps.addOptional('c', 3.3, ...
@(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
ps.addOptional('delta', 3.4, ...
@(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
ps.addOptional('p', 7.9e-3, ...
@(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
% Parse
parse(ps, varargin{:});
% Extract parameters
Tpoints = ps.Results.Tpoints;
beta = ps.Results.beta;
c = ps.Results.c;
delta = ps.Results.delta;
p = ps.Results.p;</pre><p>A bit better if you count lines, we're down to 25, from 35. In this case, you see that the limitation of number of input arguments is relaxed. It can go from 0 to 5 now.</p><h4>And the modern way, circa 2019<a name="d8b467fc-318e-43ec-898b-60984729d933"></a></h4><p>In MATLAB release 2019b, we introduced a new way to perform input argument validation, using the <a href="https://www.mathworks.com/help/matlab/ref/arguments.html"><tt>arguments</tt></a> block at the beginning of the function code. Here's how to do what we've previously accomplished in 35, then 25 lines of code.</p><pre> arguments % R2019b or newer
Tpoints(1, :) double {mustBeNumeric, mustBeNonnegative} = 0:0.1:10
beta(1, 1) double {mustBeReal} = 3.4e-5
c(1, 1) double {mustBeReal} = 3.3
delta(1, 1) double {mustBeReal} = 3.4
p(1, 1) double {mustBeReal} = 7.9e-3
end</pre><p>In 7 lines of code, you can see that we specify the conditions we want for each input, and supply a default value if the input is missing.</p><p>This is just a simple example. There is a lot more fodder you can bring to <tt>arguments</tt>. Check out the <a href="https://www.mathworks.com/help/matlab/ref/arguments.html"><tt>documentation</tt></a> to see the possibilities.</p><h4>Do you have arguments?<a name="7f42f890-ce80-4d41-a9e7-092bbc43da8e"></a></h4><p>How do you resolve your arguments? Let me know <a href="https://blogs.mathworks.com/loren/?p=3482#respond">here</a>.</p><script language="JavaScript"> <!--
function grabCode_f205eeffb948427383f9fbd267be49d3() {
// Remember the title so we can use it in the new page
title = document.title;

// Break up these strings so that their presence
// in the Javascript doesn't mess up the search for
// the MATLAB code.
t1='f205eeffb948427383f9fbd267be49d3 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
t2='##### ' + 'SOURCE END' + ' #####' + ' f205eeffb948427383f9fbd267be49d3';

b=document.getElementsByTagName('body')[0];
i1=b.innerHTML.indexOf(t1)+t1.length;
i2=b.innerHTML.indexOf(t2);

code_string = b.innerHTML.substring(i1, i2);
code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

// Use /x3C/g instead of the less-than character to avoid errors
// in the XML parser.
// Use '\x26#60;' instead of '<' so that the XML parser
// doesn't go ahead and substitute the less-than character.
code_string = code_string.replace(/\x3C/g, '\x26#60;');

copyright = 'Copyright 2019 The MathWorks, Inc.';

w = window.open();
d = w.document;
d.write('<pre>\n');
d.write(code_string);

// Add copyright line at the bottom if specified.
if (copyright.length > 0) {
d.writeln('');
d.writeln('%%');
if (copyright.length > 0) {
d.writeln('% _' + copyright + '_');
}
}

d.write('</pre>\n');

d.title = title + ' (MATLAB code)';
d.close();
}
--> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter; font-style: italic; color: gray"><br><a href="javascript:grabCode_f205eeffb948427383f9fbd267be49d3()"><span style="font-size: x-small; font-style: italic;">Get
the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br><br>
Published with MATLAB&reg; R2019b<br></p></div><!--
f205eeffb948427383f9fbd267be49d3 ##### SOURCE BEGIN #####
%% Time for an Argument
% For those Monty Python fans reading this post, check out the
% <[url]https://www.youtube.com/watch?v=DkQhK8O9Jik[/url] Argument Clinic>. Recently
% both <[url]https://blogs.mathworks.com/pick/2019/10/04/leaf-pile/[/url] Sean> and
% <[url]https://blogs.mathworks.com/pick/2019/09/27/new-with-r2019b-function-argument-validation/[/url]
% Jiro>,
% <[url]https://blogs.mathworks.com/pick/2019/10/18/spider-plots-and-more-argument-validation/[/url]
% twice!> posted about the new
% <[url]https://www.mathworks.com/help/matlab/matlab_prog/function-argument-validation-1.html[/url]
% |arguments|> capability available for input argument checking. I wanted
% to show you some more about this great feature! I've also discussed
% argument checking over the years, including
% <[url]https://blogs.mathworks.com/loren/2009/05/05/nice-way-to-set-function-defaults/[/url]
% this post>.
%% What Makes a Program Good, or Useful?
% Of course, this in the eye of the user frequently, but certainly it helps
% if you get informative messages when you misuse the program. These
% messages should help guide you so you can properly use the program
% without a major headache. To do so generally requires some amount of
% error checking on the part of the programmer, thinking about what can go
% wrong, and making sure to give good information if/when it does.
%
% I'm going to show you some code snippets from a routine. The function in
% question is modeling the dynamics of a virus, given parameters such as
% the infection rate.
%% Original error checking, circa 2007
% In this first code, I will show you how we did some important error
% checking about 12 years ago. In 35 lines, we check to see if the user
% called the function this code is embedded in with 0, 1, or 5 inputs. And
% we check the types of the inputs. If not all the inputs are supplied by
% the user, we set the unsupplied variables with default values.
%
% % Allowing for variable number of arguments in
% switch(nargin)
% case 5
% Tpoints = varargin{1}; % time to evaluate at
% beta = varargin{2}; % infection rate
% c = varargin{3}; % clearance rate of virus
% delta = varargin{4}; % death rate of infected cells
% p = varargin{5}; % viral production rate of infectious cells
%
% case 1
% Tpoints = varargin{1}; % time to evaluate at
% beta = 3.4e-5; % infection rate
% c = 3.3; % clearance rate of virus
% delta = 3.4; % death rate of infected cells
% p = 7.9e-3; % viral production rate of infectious cells
%
% case 0
% % Use all default values
% Tpoints = 0:0.1:10; % time to evaluate at
% beta = 3.4e-5; % infection rate
% c = 3.3; % clearance rate of virus
% delta = 3.4; % death rate of infected cells
% p = 7.9e-3; % viral production rate of infectious cells
%
% otherwise
% error('virusSolve:Input:InvalidNumberOfInputs', ...
% 'This function expects 0, 1, or 5 inputs.');
% end
%
% % Error checking - make sure all inputs are valid
% validateattributes(Tpoints, {'numeric'}, {'vector', 'nonnegative'},mfilename,'Tpoints',1);
% validateattributes(beta , {'numeric'}, {'scalar', 'real'});
% validateattributes(c , {'numeric'}, {'scalar', 'real'});
% validateattributes(delta , {'numeric'}, {'scalar', 'real'});
% validateattributes(p , {'numeric'}, {'scalar', 'real'});
%
% You can see heavy use of
% |<[url]https://www.mathworks.com/help/matlab/ref/validateattributes.html[/url]
% validateattributes>| as well as the use of
% <[url]https://www.mathworks.com/help/matlab/ref/nargin.html[/url] |nargin|>,
% and <[url]https://www.mathworks.com/help/matlab/ref/switch.html[/url] |switch, case,
% otherwise|>.
%% Another solution, similar time frame
% There was another solution availabe in about the same time frame using a
% function called
% <[url]https://www.mathworks.com/help/matlab/ref/inputparser.html[/url]
% |inputParser|>. Here's what that error checking code looks like.
%
% % Create input parser
% ps = inputParser();
%
% % Define optional arguments with default values and error checking
% ps.addOptional('Tpoints', 0:0.1:10, ...
% @(x) validateattributes(x, {'numeric'}, {'vector', 'nonnegative'}));
% ps.addOptional('beta', 3.4e-5, ...
% @(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
% ps.addOptional('c', 3.3, ...
% @(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
% ps.addOptional('delta', 3.4, ...
% @(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
% ps.addOptional('p', 7.9e-3, ...
% @(x) validateattributes(x, {'numeric'}, {'scalar', 'real'}));
%
% % Parse
% parse(ps, varargin{:});
%
% % Extract parameters
% Tpoints = ps.Results.Tpoints;
% beta = ps.Results.beta;
% c = ps.Results.c;
% delta = ps.Results.delta;
% p = ps.Results.p;
%
% A bit better if you count lines, we're down to 25, from 35. In this
% case, you see that the limitation of number of input arguments is
% relaxed. It can go from 0 to 5 now.
%
%% And the modern way, circa 2019
% In MATLAB release 2019b, we introduced a new way to perform input
% argument validation, using the
% <[url]https://www.mathworks.com/help/matlab/ref/arguments.html[/url] |arguments|>
% block at the beginning of the function code. Here's how to do what we've
% previously accomplished in 35, then 25 lines of code.
%
% arguments % R2019b or newer
% Tpoints(1, :) double {mustBeNumeric, mustBeNonnegative} = 0:0.1:10
% beta(1, 1) double {mustBeReal} = 3.4e-5
% c(1, 1) double {mustBeReal} = 3.3
% delta(1, 1) double {mustBeReal} = 3.4
% p(1, 1) double {mustBeReal} = 7.9e-3
% end
%
% In 7 lines of code, you can see that we specify the conditions we want
% for each input, and supply a default value if the input is missing.
%
% This is just a simple example. There is a lot more fodder you can bring
% to |arguments|. Check out the
% <[url]https://www.mathworks.com/help/matlab/ref/arguments.html[/url]
% |documentation|> to see the possibilities.
%
%% Do you have arguments?
% How do you resolve your arguments? Let me know
% <[url]https://blogs.mathworks.com/loren/?p=3482#respond[/url] here>.

##### SOURCE END ##### f205eeffb948427383f9fbd267be49d3
--><img src="http://feeds.feedburner.com/~r/mathworks/loren/~4/POnfaRq_KuU" height="1" width="1" alt=""/>

[url=http://feedproxy.google.com/~r/mathworks/loren/~3/POnfaRq_KuU/]more...[/url]


所有时间均为北京时间。现在的时间是 23:25

Powered by vBulletin
版权所有 ©2000 - 2025,Jelsoft Enterprises Ltd.