Introduction
Optional input arguments can make your statistical computing more efficient and enjoyable. GAUSS version 20 added a new suite of tools to make it easy for you to add optional input arguments to your GAUSS procedures.
In this blog post we will show you how to easily:
- Create procedures that can accept optional inputs.
- Check for and count the number of optional inputs.
- Set default values.
- Pass optional inputs to other procedures and functions.
Basic GAUSS Procedure without Optional Inputs
We’ll start by creating a simple toy GAUSS procedure that does not use optional arguments.
// Run procedure
myProc(1.1, 2.2, 3.3);
// Define procedure
proc (0) = myProc(a, b, c);
print a;
print b;
print c;
endp;
If we run the code above, we will get the following output:
1.1 2.2 3.3
To modify this procedure to accept optional arguments, we need to make the following changes:
- Modify the procedure declaration to specify the required arguments and allow optional arguments to be passed in.
- If desired, check to see if any optional arguments were passed in.
- Access the optional arguments.
Procedure Declaration with Optional Arguments
The procedure declaration is the first line of the procedure. The procedure declaration from our initial procedure was:
// Procedure declaration
proc (0) = myProc(a, b, c);
Now we will modify our original procedure to make a
the only required input. The new procedure declaration will look like this:
// Procedure declaration with optional inputs
proc (0) = myProc(a, ...);
In the procedure declaration, above, a
is a required input as it was before. However, we have replaced b
and c
with ...
. The triple dots represent the optional arguments. The triple dots ...
:
- Allow any number of optional arguments to be passed in.
- Must be the final input in the procedure declaration.
Checking for Optional Inputs in GAUSS Procedures
The GAUSS function dynargsCount
returns the number of optional arguments passed into the procedure. dynargsCount
may only be called inside of a GAUSS procedure and does not take any inputs. For example:
a = 9;
b = 3.14;
c = 2.54;
print "call 1";
myProc(a);
print "call 2";
myProc(a, b);
print "call 3";
myProc(a, b, c);
// Procedure declaration with optional inputs
proc (0) = myProc(a, ...);
local n_dynargs;
// Notice that you do not pass ‘...’
// into ‘dynargsCount’
n_dynargs = dynargsCount();
print "Number of optional inputs = " n_dynargs;
print "---------";
endp;
Will print the following output:
call 1 Number of optional inputs = 0.0 --------- call 2 Number of optional inputs = 1.0 --------- call 3 Number of optional inputs = 2.0 ---------
This allows you to add logic which depends on the number of optional arguments that were passed into your procedure.
dynargs
.Accessing Optional Arguments in GAUSS Procedures
You can access optional arguments in GAUSS procedures by:
- Using the
dynargsGet
function. - Passing the triple dots,
...
, to another function.
Retrieving Optional Input Arguments with dynargsGet
The dynargsGet
procedure returns specified optional arguments. It requires one input that specifies the index, or index range of optional arguments to return. For example:
a = 9;
b = 3.14;
c = 2.54;
print "call 1";
myProc(a);
print "call 2";
myProc(a, b);
print "call 3";
myProc(a, b, c);
// Procedure declaration with optional inputs
proc (0) = myProc(a, ...);
// Since ‘b’ and ‘c’ are not declared as inputs
// in the procedure declaration, they must be
// declared as local variables
local b, c, idx;
// The range of optional inputs we want to return
idx = { 1, 2 };
{ b, c } = dynargsGet(idx);
print "a = " a;
print "b = " b;
print "c = " c;
print "---------";
endp;
This time, the code will print out:
call 1 a = 9.00 b = {} c = {} --------- call 2 a = 9.00 b = 3.14 c = {} --------- call 3 a = 9.00 b = 3.14 c = 2.54 ---------
As we see above, a
is passed through as we would expect each time. In "call 1", neither b
or c
were passed into myProc
. We can see that GAUSS printed their contents as empty curly braces, {}
. This indicates that they were empty matrices.
If an optional input argument requested by dynargsGet
is not supplied, by default an empty matrix will be returned in its place. We can check for empty matrices with the GAUSS function, isempty
. For example:
// Create an empty matrix
z = {};
// Check to see if `z` is an empty matrix
if isempty(z);
print "z is an empty matrix";
else;
print "z is not an empty matrix";
endif;
As you may have guessed, the above code will print:
z is an empty matrix
Setting Default Values with dynargsGet
While we can use isempty
and if
statements to handle the optional inputs, it is often simpler to set default values.
Fortunately, dynargsGet
allows us to specify default values for the optional arguments which are not supplied. To specify default values with dynargsGet
, simply add them as a comma-separated list of inputs after the required index input.
There are a few things to remember when specifying default values:
- If default values are specified for any requested inputs, they must be specified for all optional inputs.
- The default values may be any GAUSS type, including structures, arrays, strings, string arrays as well as sparse and dense matrices.
We can set default values for our toy example, like this:
a = 9;
b = 3.14;
c = 2.54;
print "call 1";
myProc(a);
print "call 2";
myProc(a, b);
print "call 3";
myProc(a, b, c);
// Procedure declaration with optional inputs
proc (0) = myProc(a, ...);
// Since ‘b’ and ‘c’ are not declared as inputs
// in the procedure declaration, they must be
// declared as local variables
local b, c, idx;
// The range of optional inputs we want to return
idx = { 1, 2 };
// If ‘b’ or ‘c’ are not passed in, return
// 29 or 33 respectively
{ b, c } = dynargsGet(idx, 29, 33);
print "a = " a;
print "b = " b;
print "c = " c;
print "---------";
endp;
This time our code will return:
call 1 a = 9.00 b = 29.00 c = 33.00 --------- call 2 a = 9.00 b = 3.14 c = 33.00 --------- call 3 a = 9.00 b = 3.14 c = 2.54 ---------
Passing Optional Inputs to other GAUSS Procedures
While any input arguments accessed by dynargsGet
can be passed to other procedures, it is important to know that the triple dots, ...
, can also be passed directly into other procedures.
Passing triple dots, ...
, to another procedure is just as if you passed a comma-separated list of the arguments in ...
.
...
, do not have to be the final input when passed to other procedures.For example:
X_1 = initMat1(3.14, 5, 2);
X_2 = initMat2(3.14, 5, 2);
// Procedure declaration with only optional inputs
proc (1) = initMat1(val, ...);
local X;
X = val + zeros(...);
retp(X);
endp;
// Procedure declaration with only required inputs
proc (1) = initMat2(val, r, c);
local X;
X = val + zeros(r, c);
retp(X);
endp;
The calls to initMat1
and initMat2
will behave the same.
Practical Example with Optional Arguments
Now that we’ve seen the basics of using optional inputs to GAUSS procedures, let’s work through a more practical example. We’ll create two procedures that will work together to simulate a linear model.
Our first procedure will create a random normal matrix, with the option to specify the mean and standard deviation of the variables.
/*
** Inputs: r - Required input. Number of rows.
** c - Required input. Number of columns.
** mu - Optional input. Mean of the simulated columns.
** Default = 0.
** sd - Optional input. Standard deviation of the
** simulated columns. Default = 1.
*/
proc (1) = rndNormal(r, c, ...);
local X, mean, sd;
// If a 3rd input is passed in, assign it
// to ‘mean’. Otherwise set ‘mean’ equal to 0.
// If a 4th input is passed in, assign it
// to `sd`. Otherwise set ‘sd’ equal to 1.
{ mean, sd } = dynargsGet(1|2, 0, 1);
// Compute a random matrix with the
// specified mean and sd.
X = (rndn(r, c) .* sd) + mean;
retp(X);
endp;
Here are a few examples of how we could call this procedure:
// Create a 100x4 random normal matrix
// with mean=0 and sd=1
X_1 = rndNormal(100, 4);
// Create a 130x2 random normal matrix
// with mean=3.7 and sd=1
X_2 = rndNormal(130, 2, 3.7);
// Create a 74x5 random normal matrix
// with mean=-2 and sd=3
X_3 = rndNormal(74, 5, -2, 3);
Next, we’ll create a procedure that will use our rndNormal
procedure to simulate linear models.
/*
** Inputs: b_true - Required input. True parameter values of
** the simulated linear model.
** nobs - Required input. The number of observations
** to simulate.
** alpha_true - Optional input. True intercept of the
** simulated linear model. Default = 0.
** err_sd - Optional input. Standard deviation of the
** error term. Default = 1.
*/
proc (1) = simulateLM(b_true, nobs, ...);
local X, err, nvars, alpha_plus_err, y;
// Find number of desired variables
nvars = rows(b_true);
// Simulate variables with
// mean = 0, sd = 1
X = rndNormal(nobs, nvars);
// Simulate error term and add intercept
// if it was passed in.
alpha_plus_err = rndNormal(nobs, 1, ...);
y = X * b_true + alpha_plus_err;
retp(y);
endp;
Here are a few examples of how our simulateLM
procedure can be used:
b = { 0.8, -1.1, 0.2 };
n = 10;
/*
** Simulate linear model:
** - Without intercept
** - With error term sd equal to 1
*/
y_1 = simulateLM(b, n);
/*
** Simulate linear model:
** - With intercept
** - With error term sd equal to 1
*/
alpha = 2.3;
y_2 = simulateLM(b, n, alpha);
/*
** Simulate linear model:
** - With intercept
** - With error term sd equal to 3
*/
alpha = 2.3;
err_sd = 3;
y_3 = simulateLM(b, n, alpha, err_sd);
Conclusion
Congratulations! You should now be able to start creating GAUSS procedures with optional input arguments. You have learned how to:
- Allow optional inputs, by adding triple dots,
...
, to the procedure declaration. - Find out how many optional arguments were passed in by using
dynargsCount
. - Access the optional arguments and set default values with
dynargsGet
. - Pass optional arguments to other GAUSS procedures.