Def

From BR Wiki
Jump to navigation Jump to search

The Def statement specifies a user-defined function. It defines a string or numeric function that is referenced elsewhere in the program.

Comments and Examples

User-defined functions are used when a single or set of calculations is performed multiple times in a program. These functions return only one string or numeric value and can be either one or many lines. The name of a user-defined function must start with FN and can be a maximum of 30 characters, including the FN characters. A multi-lined function must end with an FNEND statement.

The following pair of functions gives an example of user-defined functions and their usage.

The first function (FNY) takes a date in MMDDYY format and returns it in YYMMDD format; the second function puts the date back into MMDDYY format (note: these operations can also be done with the built-in DATE function)

00010 DEF FNY(X)=(X-INT(X/100)*100)*10000+INT(X/100)
00020 DEF FNM(X)=(X-INT(X/10000)*10000)*100+INT(X/10000)

Multiple line functions allow more flexibility than single line functions. They can change variable values outside the functions passed values, perform file I/O, and call themselves (recursively). Beyond the syntax of the DEF statement, there are two requirements for a multiple-line function: first, to return a value it must include a statement that sets the function name equal to either a "numeric expression" (for numeric functions) or a "string expression" (for string functions), and second, it must end with an FNEND statement.

Variables passed to a function are normally local to the function. This means that changing the value of a passed variable does not change the value of an identically named variable outside of the function. If the following example were run, its output would be 10 and 2:

00010 DEF FNX(X)
00020 X=X*5
00030 FNX=X
00040 FNEND
00050 X=2
00060 PRINT FNX(X)
00070 PRINT X

NOTE that the value of X at line 70 is the same as it was at line 50. Executing the function FNX at line 60 did not change X. Variables passed to a function this way are "passed by value", meaning that the value of the variable is passed, not the variable itself. A temporary variable X is created for the duration that FNX is active. If FNX calls itself, another temporary variable X is created.

Variables may also be "passed by reference" with an (&) symbol. When this happens, a temporary variable is not created, and any assignments made to the variable affect the variable that was passed.

00010 DEF FNP(&X)
00020 X=X*2 : FNP=X
00030 FNEND
00040 A=2 : X=5
00050 PRINT FNP(A)
00060 PRINT A,X

The output of the above program is 4, 4, and 5. The execution of the function FNP does not change the value of X outside the function, but it does change the value of "A" because the DEF statement specified that the variable itself be passed to the function.

In multiple-line functions the return value of the function is assigned by using the function name as a simple variable, as in line 20 in the example above. If the return value is not assigned, the function returns zero or null.

Syntax

DEF <FNname>[$*<length>] [([{MAT|&}] {<numeric variable>|<string variable> <length>}[,...])] [{<numeric expression>|<string expression>}] 

Parameters

The DEF statement allows for either numeric or string functions to be defined. In both cases, the "FNname" parameter must include the letters FN and may consist of up to 28 more letters, numbers and underscores. In addition, string function names must end with a dollar sign ($). Function names must be unique.

The "length" parameter which follows the FNname$ parameter identifies the dimensions of the returned value. The dimensioned length of the string may be longer than the actual length.

If a variable is to be passed -either by value or by reference- the next set of specifications must appear within parentheses.

The "MAT" keyword identifies that an array variable is to be passed by reference (this is the only way in which arrays may be passed). It must be followed by a "string variable" or "numeric-variable" which identifies the name of the array. If a string-variable is named, its dimensioned "length" may also be identified.

The ampersand ("&") must be specified for variables other than array variables which are to be passed by reference. It must be followed by a "string-variable" or "numeric variable" which identifies the name of the variable. The identified variable will take on all the characteristics of the variable passed, including string length and dimensions.

No preceding keyword or symbol is required for variables that are to be passed by value. Simply identify the "num-var" or "string-var" to be passed. The "length" parameter may also be specified when a string is to be passed (18 is the default).

Single-line function definitions must end with an equal symbol (=) and either a "numeric-expression" (for numeric functions) or a "string-expression" (for string functions). If this set of specifications is not included, Business Rules assumes that the function being defined is a multi-lined function. The data type, length and number of parameters in the statement referencing the function must match the DEF statement.

Technical Considerations

1.) Use of a user-defined function name on the left side of an equation implies assignment of the return value of the function; its use on the right side of an equation always calls the function. Within a function, the following statements call FNX recursively (until the flowstack or Workstack overflow):
00030 DEF FNX(X)
00040 FNX=2
00050 IF X>1 THEN FNX=FNX+X
00060 FNEND

Adding 1 to FNX must be done another way.

Replacing line 50 with the following would give the intended result:

00050 IF X>1 THEN FNX=2+X
2.) String parameters passed by value must be dimensioned in the DEF parameter list if their length is greater than 18. They may have a dimensioned length longer than the data passed.
3.) Parameters specifying pass by reference (&) take on all the attributes of the variable passed, including string length and dimensions. Arrays must be passed by reference. Only variables can be passed by reference; literals, constants and functions are not allowed.
4.) Variables in the DEF parameter list that are passed by value (default) are local to the function and may be assigned without changing the value of a variable with the same name outside of the function.
5.) Variables in the DEF parameter list that are passed by reference (& or MAT variables) are local to the function in the sense that their assignment does not affect a variable of the same name outside of the function. It does change the value of the variable passed.
6.) References to user-defined functions may typically appear wherever constants are allowed. They are not allowed in the variable list of READ, INPUT or FORM statements.
7.) A user-defined function may be defined anywhere in a program except within a programming structure such as a FOR/NEXT loop or a multi-lined IF. The function may be defined either before or after it is referenced.
8.) Transfer of control outside the function is permitted, but strongly discouraged. No special rules apply to error processing within a function. All ON error conditions are in effect.
9.) When a function is active, its passed variables mask out variables with the same name outside the function. If the function is interrupted, values of the masked variables that existed before the function was called are inaccessible.
10.) If control is passed to the DEF statement without reference to the function, control then transfers to the first line after the FNEND statement.
11.) In an I/O statement, all calculations are done before the I/O is started. If an I/O statement calls a function that does I/O, the function's I/O is performed first.
12.) A function definition must be unique; it may be defined only once in the program.
13.) A function may be recursive (may call itself).
14.) If a function changes a variable that is also referenced in the statement calling the function, the results may not be as expected.
15.) User-defined functions may not be nested (an FNEND statement must be executed before another DEF statement is allowed).
16.) A FOR/NEXT loop must begin and end within the same function.
17.) A DEF statement must be alone on a line. Other statements may neither precede nor follow a DEF statement on the same line.
18.) A function may pass no parameters. The following program illustrates the valid use of a function:
00010 DEF FNX=Y*2+Z
00020 PRINT FNX
19.) If a program is interrupted while a user-defined function is active, the line calling the function may not be changed.
20.) In support of the Library Facility, DEF now accepts the LIBRARY parameter for specifying a user-defined library function. See the remainder of this DEF discussion for details.
21.) The DEF statement's syntax now allows the use of a semi-colon to indicate that all parameters specified to the right of the semi-colon are optional. See the remainder of this DEF discussion for details.
22.) When a function is expecting an array or matrix, but a function call passes a scalar (simple variable), the function now treats the passed variable as an array of one element.

Alternately, if a DEF parameter is defined as a scalar to be passed by reference (&), and an array is passed, the first element of the array will be used as the scalar.

In the following example, a value of 1 is placed into X, as scalar Y is interpreted as a single element array:

00010 X=FNA(Y)
00020 DEF FNA(MAT A)
00030 FNA=UDIM(A)
00040 FNEND

Defaults

  1. User-defined function is not a library function.
  2. Maximum string variable length of 18 characters.
  3. Pass by value, not by reference. (Arrays always pass by reference, and can not be passed by value)
  4. Do not pass any required variables.
  5. Do not pass any optional variables.
  6. Do not pass any variables.
  7. Multi-line function.

Library Parameter

The DEF statement's "LIBRARY" keyword makes a user-defined function into a library function. A library function may be defined either within the main program or within a separate program and also used in either. In either case, the function must be named on a LIBRARY statement that is processed before the first call to the function. The first example defines a library function:

52400 DEF LIBRARY FNSAMPLELIB
52500 PRINT "This is a library function"
52600 FNEND

and this accesses the library function from any program:

01000 LIBRARY "SAMPLEPROGRAM": FNSAMPLELIB
01100 LET FNSAMPLELIB

For complete information about the Business Rules Library Facility, see the Library Facility section, the CLEAR, LOAD and STATUS Commands, and the OPTION Statement.

In another example:

00170     def library Fntotalsales(Sales,Comrate,Taxrate;&Tax,&Commission)
...

The DEF statement's ";" parameter is designates passed parameters. It indicates that all variables to the right of the semi-colon (;) are optional. If the program does not pass a parameter to the function which is listed as optional in the function definition, a temporary variable is created with a value of zero or null.

Optional parameters may be passed by reference. In that case, arrays not passed default to a dimension of 1 and strings default to a length of 18.

Business Rules! accepts function definitions that pass only optional values (i.e., DEF FN(;A,B)). However, a calling statement cannot pass more variables than are defined for the function, and variable types (numeric or string) must match for passed variables.

Examples

The user-defined function in the following example might be used to print an employee list that also names the members of the employee's family. It utilizes DEF's ";" parameter to specify that two optional parameters (SPOUSE$ and MAT CHILD$) may be passed. Since this function also uses the LIBRARY keyword, it will be handled according to the rules and requirements for library functions.

01000 DEF FNEMPFAM$(&EMP$;&SPOUSE$,MAT CHILD$)
01100  PRINT "Employee name: ";TAB(20);EMP$
01200  IF SPOUSE$<>"" THEN PRINT TAB(8);"Spouse: ";TAB(20);SPOUSE$
01300  IF CHILD$(1)<>"" THEN
01400   PRINT TAB(6);"Children: ";TAB(20);CHILD$(1)
01500   FOR X=2 TO UDIM(CHILD$)
01600    PRINT TAB(20);CHILD$(X)
01700   NEXT X
01800  END IF
01900 FNEND