Top  Previous  Next


The SUBROUTINE statement introduces a subroutine. The abbreviation SUB may be used.





SUBROUTINE name{(arg1 {, arg2...}) {VAR.ARGS}}




nameis the name of the subroutine.


arg1, etcare the names of the arguments to the subroutine.



QMBasic programs should commence with a PROGRAM, SUBROUTINE, FUNCTION or CLASS statement. If none of these is present, the compiler behaves as though a PROGRAM statement had been used with name as the name of the source record.


The SUBROUTINE statement must appear before any executable statements. A SUBROUTINE with no arguments is equivalent to a PROGRAM. The brackets are optional if there are no arguments. The SUBROUTINE statement may be split over multiple lines by breaking after a comma.


The name used in a SUBROUTINE statement need not be related to the name of the source record though it is recommended that they are the same as this eases program maintenance. The name must comply with the QMBasic name format rules


A subroutine module is entered by referencing it a CALL statement. A subroutine that has no arguments can also be entered by use of the RUN command or by executing a command name that corresponds to the name of the program in the system catalogue.



Variable Length Argument Lists and Default Values


The number of arguments in calls to the subroutine must be the same as in the SUBROUTINE statement unless the subroutine is declared with the VAR.ARGS option. When VAR.ARGS is used, any arguments not passed by the caller will be unassigned. The ARG.COUNT() function can be used to determine the actual number of arguments passed. The ARG.PRESENT() function can be used to test for the presence of an optional argument by name. If the values of argument variables are changed by the subroutine, these changes are reflected in the variables used in the CALL statement that entered the subroutine.


In this example, if the calling program supplies only one argument, the CLASS and CODE variables will be unassigned. If the calling program provides two arguments, the CODE variable will  be unassigned.


When using VAR.ARGS, default values may be provided for any arguments by following the argument name with an = sign and the required numeric or string value or the @FALSE or @TRUE constants. For example,


In this example, if the calling program supplies only one argument, the CLASS variable will default to 1 and the CODE variable will default to "Standard". It the calling program provides two arguments, the default value for CLASS is ignored and the CODE variable defaults to "Standard".


Default argument values can also be provided when the DEFAULT.UNASS.ARGS option of the $MODE compiler directive is enabled. In this case, the default value will be applied if the argument variable passed from the calling program is unassigned.



Pass By Reference


Subroutine arguments are normally passed by reference such that changes made to the argument variable inside a subroutine will be visible in the caller's variable referenced by that argument. The CALL statement allows arguments to be passed by value by enclosing them in brackets. The SUBROUTINE statement also supports this dereferencing syntax. For example


If dereferencing is used with the default argument syntax described above, the default value is placed inside the parenthesis. For example,




Matrix Arguments


An argument may refer to a whole matrix. In this case the argument variable name must be preceded by the keyword MAT and there must be a DIM statement following the subroutine declaration to indicate whether this is a one or two dimensional matrix. Alternatively, the dimensions may be given after the variable name in the SUBROUTINE statement. In either case, the actual dimension values are counted by the compiler to establish whether the matrix has one or two dimensions but are otherwise ignored. Developers frequently use of a dimension value of one to emphasise to readers of the program that the value is meaningless. A default style (not Pick style) matrix passed as an argument can be re-dimensioned in the subroutine by use of the REDIMENSION (or REDIM) statement. Used in any other context, this statement is identical to use of DIM.


For example


  DIM A(1)

  MAX = A(1)

  N = INMAT(A)

  FOR I = 2 TO N

     IF A(I) > MAX THEN MAX = A(I)





This subroutine scans a one dimensional matrix and passes back the value of the largest element via the MAX argument. The first two lines could alternatively be written as