The following script calculates the factorial of a number recursively. PROCEDURE makes recursion possible and easy.
/* Calculate factorial x, that is, 1*2*3* ... *x */ SAY "Enter a number" PARSE PULL num . SAY num "!=" factorial(num) EXIT factorial: /* calculate the factorial of the argument */ PROCEDURE num = ARG(1) IF num < 3 THEN RETURN num ELSE RETURN factorial(num-1) * pFirst of all, the num variable initially passed to factorial is not the same num variable used within factorial due to the PROCEDURE instruction. So, that ARG() assignment isn't altering the original num variable, but rather, creating a new variable named num. Furthermore, that second num variable is then passed to factorial again. (ie, factorial calls itself when it goes to return a value). When factorial is called again, it creates yet another num variable to be used up until that nested call returns.
Exposing variables
If your function needs access to just a few variables used elsewhere in the script, but wants to protect all other variables, then put the EXPOSE keyword after PROCEDURE, followed by any variable names that you don't want hidden away. In this way, your function can alter the values of particular variables used elsewhere in the script, while also protecting other variables. Consider the following:
/* Assign values to variables First and Second */ First = 0 Second = 0 /* Call subroutine alter */ CALL alter SAY "First =" First", Second =" Second EXIT alter: PROCEDURE EXPOSE First /* don't protect the variable First */ First = 1 Second = 1 RETURNThe above prints out "First = 1, Second = 0". Note that the alter function was able to change the value of First used in the SAY command, but not the value of Second. That's because the Second variable that alter changes is an entirely different variable than the Second variable used elsewhere in the script. On the other hand, the First variable used within alter is the very same one used elsewhere.
You can also specify the name of some variable whose value contains the names of which variables you want EXPOSE'ed. You put that variable's name in parentheses after the EXPOSE keyword.
/* Set the variable MyVar to the names of what other * variables we want exposed. */ MyVar = 'SomeVar MyArray. SomeCompound.1' /* Now call alter(). */ CALL alter EXIT alter: PROCEDURE EXPOSE (MyVar) /* Same as PROCEDURE EXPOSE MyVar SomeVar MyArray. SomeCompound.1 */ RETURNNote: The variable whose name is in parentheses is also exposed.