### 2.10 User-deﬁned functions

BayES supports user-deﬁned functions. These functions are deﬁned in BayES script ﬁles and can take multiple arguments and return multiple values. User-deﬁned functions are called from script ﬁles or other functions and can be used to perform a particular task that may require many lines of code, helping to keep the code in the main script tidy. Also, in cases where a task needs to be performed repeatedly, it is easier to describe the task in a user-deﬁned function and to call this function at the appropriate places in the script ﬁle.

Each user-deﬁned function must be declared and implemented in its own BayES script ﬁle. These special ﬁles have a speciﬁc form. For example, suppose that we want to deﬁne a function named myFunction that takes a list of arguments, ar1, ar2, ..., uses these argument to do some calculations and deﬁnes a list of return values, rv1, rv2, ..., which will be available after the function completes its job. The following code should be put in a BayES script ﬁle called myFunction.bsf and this ﬁle saved in the current working directory:

function [rv1, rv2, ... ] = @myFunction(ar1, ar2, ...)
<list of statements>
// these statements will use ar1, ar2, ..., and define
// rv1, rv2, ..., which will be available in the calling
// workspace once the function completes its job
end

Functions are not meant to be executed independently, but to be called from other scripts (or other functions). A statement like:

[y1, y2, ... ] = @myFunction(x1, x2, ...);

placed within a BayES script represents a call to the user-deﬁned function myFunction. When such a calling statement is encountered the following process takes place:

1. the arguments x1, x2, ... passed to myFunction in the calling statement are copied and made available in the function’s workspace as ar1, ar2, ...6

2. program control jumps to the user-deﬁned function myFunction, where the listed statements are executed and the return values, rv1, rv2, ..., are assigned

3. program control jumps back to the calling script and the function’s return values are made available to the workspace that contains the calling statement as y1, y2, ...

The directory "\$BayESHOME/Samples/4$-$Functions" contains samples of simple and not-so-simple functions. Here we will describe how to deﬁne and use a simple function called SimpleFunction, which takes a single argument x and returns 2*x. Suppose the ﬁle SimpleFunction.bsf is located in the current working directory and it contains the following code:

function [y] = @SimpleFunction(x)
// Print a message on the console
print("program control is now in @SimpleFunction");

// Print the value of x on the console
print(x);

// Assign the value 2*x to y
y = 2*x;

// Print a message on the console
print("program control is about to leave @SimpleFunction");
end

The ﬁrst statement in the function simply notiﬁes the user that program control has passed to @SimpleFunction by printing a message on the BayES console. The next statement prints the value of x, as it is deﬁned in the workspace of @SimpleFunction. The third statement assigns the value 2*x to y and the last statement, again, prints information on the BayES console that program control leaves @SimpleFunction.

The code in SimpleFunction.bsf cannot be executed simply by hitting Ctrl+R on the script editor window: the function needs to be called from another script. This is demonstrated in Example 2.10.

Example 2.10
▼ Input

// Define a 1x2 matrix z using draws from an exponential distribution
z = exprnd(2.5, 1, 2);

// Call "@SimpleFunction" and assign its return value to w
w = @SimpleFunction(z);

// Print a message on the console to indicate that @SimpleFunction finished
print("nnControl is back to the calling script");

// Print the value of w from the calling script
print(w);

▼ Output

Program control is now in @SimpleFunction
x =
0.5597008  0.23834727

Program control is about to leave @SimpleFunction

Control is back to the calling script
w =
1.1194016  0.47669454

#### 2.10.1 Rules for deﬁning and calling functions

The following rules apply when deﬁning and calling functions:

1. each function must be deﬁned in its own BayES script ﬁle

2. the keyword function must be the ﬁrst word in the script ﬁle that deﬁnes the function

3. the function name must be the same as the ﬁle name of the BayES script ﬁle that contains its deﬁnition, prepended by ‘@

4. the function deﬁnition ends with the end keyword; everything that follows this keyword in the script ﬁle that deﬁnes the function is ignored

5. when calling a function the BayES script ﬁle that contains its deﬁnition must be in the current working directory

6. functions can have zero, one, or multiple arguments of diﬀerent types (matrices, datasets, strings, etc.)

7. the order in which arguments are passed to a function matters

8. functions can have zero, one, or multiple return values of diﬀerent types (matrices, datasets, strings, etc.); if the function returns only one value then the square brackets in the deﬁnition and calling statements can be omitted

9. the order in which return values are assigned to elements in the workspace of the calling script matters

10. functions have their own workspace and arguments are passed by making copies: functions are aware only of items that have been passed to them as arguments and cannot access items in the workspace of the calling script7

6Each function has its own workspace and it cannot access any elements deﬁned in the workspace of the calling script (see also Section 2.10.1).

7If the workspace of the calling script has an item with id value x and a function is called, which deﬁnes another item with id value x, these two items are distinct: altering the value of x deﬁned inside the function will not aﬀect the value of x in the calling script.