ReadyBASIC
BASIC Language Reference Manual > Command and Function Reference >

PROCEDURE Command

Summary

Defines a procedure.

Syntax

  • PROCEDURE ProcedureName
        code block
    END PROCEDURE
    

  • PROCEDURE ProcedureName()
        code block
    END PROCEDURE
    

  • PROCEDURE ProcedureName(ParameterName1)
        code block
    END PROCEDURE
    

  • PROCEDURE ProcedureName(ParameterName1, ..., ParameterNameN)
        code block
    END PROCEDURE
    

Remarks and Examples

A procedure is a block of code that performs some task. When you define a procedure, you must give it a name. Optionally, a procedure definition can specify one or more parameters (explained below).

Once a procedure is defined, you can then call or invoke the procedure (using the CALL command) as many times as you like throughout the rest of your program. Each time you call a procedure, the program flow jumps to the the procedure definition and the commands in the procedure definition are executed. When the end of procedure is reached, the control passes back to the place where the procedure was called. Program execution resumes with the instruction immediately after the procedure call.

Example program listing illustrating a simple procedure:

Main:
    PRINT "Hello!"
    CALL CountToFive
    CALL CountToFive
    PRINT "One more time..."
    CALL CountToFive
    END
    
PROCEDURE CountToFive
    FOR X% = 1 TO 5
        PRINT X%; " ";
    NEXT X%
    PRINT
END PROCEDURE

When this program is run, the results are as follows:

Hello!
1 2 3 4 5
1 2 3 4 5
One more time....
1 2 3 4 5

Procedures can thus be used to package up sets of instructions that you would otherwise end up repeating throughout your program. They are also a structured programming technique that helps you organize your program more clearly.

Parameters

When defining a procedure, you can specify one or more parameters by providing a comma-separated list of variable names surrounded by parentheses.

If a variable name is given without any suffix (e.g., "AccountBalance"), the variable is considered to be of the floating-point numeric type. If the variable name is given the % suffix, (e.g., "Age%"), it signifies an integer numeric type. If the variable name is given the $ suffix, (e.g., "Message$"), it is considered to be a string.

Example of a simple procedure with a single integer parameter:

Main:
    PRINT "Hello!"
    CALL CountToNumber(3)
    CALL CountToNumber(10)
    CALL CountToNumber(7)
    END
    
PROCEDURE CountToNumber (Limit%)
    FOR X% = 1 TO Limit%
        PRINT X%; " ";
    NEXT X%
    PRINT
END PROCEDURE

When this program is run, the results are as follows:

Hello!
1 2 3
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7

Example of a program with a procedure taking four parameters, and an example of a procedure calling another procedure:

Main:
    CALL DisplayInfo("Bob", "Smith", 555222, 9305.677)
    END

PROCEDURE DisplayInfo (FirstName$, LastName$, AccountNumber%, AccountBalance)
    PRINT "Customer: "; FirstName$; " "; LastName$
    PRINT "Account number: "; AccountNumber%
    PRINT "Account balance: $";
    CALL PrintNumberWithTwoDecimalPlaces(AccountBalance)
END PROCEDURE

PROCEDURE PrintNumberWithTwoDecimalPlaces (Value)
    PRINT ROUND(Value * 100) / 100
END PROCEDURE

Output:

Customer: Bob Smith
Account number: 555222
Account balance: $9305.68

If you attempt to call a procedure without specifying any values for the parameters, or if you specify more values than parameters, or if the values do not match type parameter types (for instance, the procedure expects an integer value, but you provide a string), the program will be terminated with an error message.

Returning values to the caller by means of parameters

Procedures in ReadyBASIC follow a principle called pass-by-reference parameter passing.

This means that the variables in the procedure definition are linked with any corresponding variables that were used in the call to the procedure. If a parameter variable's value is modified in a procedure, and if the procedure call used a variable to supply the value for that parameter, the new value will be reflected in the original variable after the procedure call.

As this description is very abstract, an example will illustrate this property more clearly:

Main:
    MyValue% = 5
    PRINT "Before the procedure call, MyValue% = "; MyValue%
    CALL ModifyMyValue(MyValue%)
    PRINT "After the procedure call, MyValue% = "; MyValue%
    END
    
 PROCEDURE ModifyMyValue(X%)
     PRINT "Initial value of X% is "; X%
     X% = 200 : REM Change the value
     PRINT "X% has been changed to be "; X%
 END PROCEDURE

Result:

Before the procedure call, MyValue% is 5
Initial value of X% is 5
X% has been changed to be 200
After the procedure call, MyValue% is 200

The call to ModifyMyValue has connected the MyValue% variable in the main program to the X% parameter variable in the ModifyMyValue procedure. When the procedure modifies X%, the change is reflected in the MyValue% variable in the main program.

This does not mean that all procedure calls must always use variables to supply parameter values. You can also use literal values, such as a number like 333 or a string like "Bob". A statement such as "CALL ModifyMyValue(333)" would thus perfectly legitimate in the above program. (But if your goal is to have the procedure communicate one or more values back to the caller, you'll need to use variables in order to receive those values.)

Please note that functions (see the FUNCTION command) do not use the pass-by-reference parameter passing principle. Functions use pass-by-value parameters, which means that changing the values of parameter variables within a function definition will not affect the values of variables used to supply parameters in a function call.

Control flow

When a procedure is called, the instructions in the procedure definition will be executed until the matching END PROCEDURE statement is reached.

The use of the RETURN statement to prematurely break out of a procedure is not currently supported.

A procedure can call other procedures and functions.

While a procedure can use GOTO and GOSUB statements, these should be limited to referring to labels that are defined within the procedure definition itself.

Where should procedures be defined in a program listing?

If the flow of control encounters a procedure definition, it will be skipped over, and execution will resume with the instruction following the procedure definition. The only way to execute the code inside a procedure definition is to explicitly call that procedure. For example:

PRINT "A"
PROCEDURE SaySomething
    PRINT "C"
END PROCEDURE
PRINT "B"
CALL SaySomething

Results:

A
B
C

However, this intermixing of procedure definitions with "main program" code can be confusing. It is recommended to keep your main program code at the top of the program listing and define your procedures and functions towards the bottom of the listing. An END statement at the end of the main program code is recommended but not necessary if there are no other statements intermixed between the procedure and function definitions.

You may wish to consider writing your program so that your main program code resides inside a procedure. If you do this, the first statement of your program should be a CALL to your "main" procedure, or else the code in your main procedure will never get executed:

CALL MainProcedure

PROCEDURE MainProcedure
    REM Put your main program code here
END PROCEDURE

Recursive procedures

ReadyBASIC supports recursion. Recursion occurs when a procedure includes a procedure call to itself. Caution must be used to avoid an infinite recursion scenario.

TODO: Example

Variable scope

ReadyBASIC allows you to define local variables inside a procedure using the LOCAL statement. Local variables are not visible or accessible by code outside of the procedure. This is a structured programming technique that allows you to simplify and modularize your program by "hiding" information from parts of the program that do not need to know about that information.

TODO: Example

Notes

A procedure definition can call other procedures and functions, but you cannot nest another procedure or function definition inside a procedure definition itself.

Procedures can return values by means of the pass-by-reference mechanism described above. To create a function that returns a single value, you will probably want to use the FUNCTION command instead.

A procedure definition with no parameters does not need the opening and closing parentheses, and CALL statements that call procedures having no parameters also do not need the opening and closing parentheses. However, ReadyBASIC will allow you to use the optional form () to signify an empty parameter list. For example, the following procedure definitions and calls are valid:

PROCEDURE Sample
    ...
END PROCEDURE

PROCEDURE AnotherSample ()
    ...
END PROCEDURE

CALL Sample
CALL Sample()
CALL AnotherSample
CALL AnotherSample ( )

See also: FUNCTION, GOSUB, LOCAL, RETURN




Copyright 2006-2012, Kevin Matz, All Rights Reserved.