Unlike functions, there's no need to forward declare a procedure. It can be placed anywhere in your code, before or after you call it using RUN
.
RUN proc.
//Procedure starts here
PROCEDURE proc:
//Procedure ends here
END PROCEDURE.
The procedure name is folowed by a colon sign telling us that this is the start of a block. The block ends with END PROCEDURE.
(but this can be replaced with simply END.
).
A procedure can have parameters of different kinds: input, output, input-output (bidirectional) and also some special types like temp-tables and datasets).
In the run statement it's optional to declare INPUT
(it's considered default) - all other directions must be specifically declared.
A procedure taking two integers as input and outputting a decimal.
PROCEDURE divideAbyB:
DEFINE INPUT PARAMETER piA AS INTEGER NO-UNDO.
DEFINE INPUT PARAMETER piB AS INTEGER NO-UNDO.
DEFINE OUTPUT PARAMETER pdeResult AS DECIMAL NO-UNDO.
pdeResult = piA / piB.
END PROCEDURE.
DEFINE VARIABLE de AS DECIMAL NO-UNDO.
RUN divideAbyB(10, 2, OUTPUT de).
DISPLAY de. //5.00
Parameters are totally optional. You can mix and match any way you want. The order of the parameters are up to you but it's handy to start with input and end with output - you have to put them in the right order in the run statement and mixing directions can be annoying.
Recursion is easy - RUN
the procedure itself from inside the procedure. However if you recurse too far the stack will run out of space.
A procedure calculation the factorial.
PROCEDURE factorial:
DEFINE INPUT PARAMETER piNum AS INTEGER NO-UNDO.
DEFINE OUTPUT PARAMETER piFac AS INTEGER NO-UNDO.
DEFINE VARIABLE iFac AS INTEGER NO-UNDO.
IF piNum = 1 THEN DO:
pifac = 1.
END.
ELSE DO:
RUN factorial(piNum - 1, OUTPUT iFac).
piFac = piNum * iFac.
END.
END PROCEDURE.
DEFINE VARIABLE f AS INTEGER NO-UNDO.
RUN factorial(7, OUTPUT f).
DISPLAY f.
The procedure has it's own scope. The outside scope will "bleed" into the procedure but not the other way arround.
DEFINE VARIABLE i AS INTEGER NO-UNDO INIT 1.
DEFINE VARIABLE j AS INTEGER NO-UNDO.
PROCEDURE p:
MESSAGE i VIEW-AS ALERT-BOX. // 1
MESSAGE j VIEW-AS ALERT-BOX. // 0
j = 2.
END PROCEDURE.
RUN p.
MESSAGE i VIEW-AS ALERT-BOX. // 1
MESSAGE j VIEW-AS ALERT-BOX. // 2
Declaring a variable inside a procedure that has the same name as a parameter on the outside will only create a local variable.
DEFINE VARIABLE i AS INTEGER NO-UNDO INIT 1.
DEFINE VARIABLE j AS INTEGER NO-UNDO.
PROCEDURE p:
DEFINE VARIABLE i AS INTEGER NO-UNDO INIT 5.
MESSAGE i VIEW-AS ALERT-BOX. // 5
MESSAGE j VIEW-AS ALERT-BOX. // 0
j = 2.
END PROCEDURE.
RUN p.
MESSAGE i VIEW-AS ALERT-BOX. // 1
MESSAGE j VIEW-AS ALERT-BOX. // 2
Any variable created on the inside of a procedure is accessible to that procedure only.
This will generate a compiler error:
PROCEDURE p:
DEFINE VARIABLE i AS INTEGER NO-UNDO INIT 5.
END PROCEDURE.
RUN p.
MESSAGE i VIEW-AS ALERT-BOX. // Unknown Field or Variable name i - error 201
RUN procedurename. //Runs a procedure called procedurename.
RUN proc1(INPUT "HELLO"). //Inputs the string HELLO to proc1
RUN proc2(INPUT var1, output var2). //Inputs var1 and outputs var2 to/from proc2
RUN proc3(input "name = 'joe'", OUTPUT TABLE ttResult). //Inputs name=joe and outputs records in a table
PROCEDURE proc: // Declares a procedure named proc
END PROCEDURE. // Ends the current procedure