//example of recursion

//This program illustrates a few things about using
//user-defined keywords. See comments below.

TO factorial :a :b [
    if :b = 0
        [:b = :a]       //first time

    if :a > 1
        [factorial :a-1 :b*:a] //recursive call with :a-1
        [say "Factorial "is :b //if :a=1, print result
        :b = 0]                //and reset :b
]

:input = 1
say "Enter "a "number "to "find "factorial "of
say "Or "zero "to "quit
say "

while :input > 0 [              //Enter zero to quit
    ask "Find "factorial "of :input
    if :input > 0 [factorial :input]
]

//keyword FACTORIAL takes two parameters:
//a number and current result
//(a keyword variable can only be used inside the keyword,
//there are no means to pass values out to the main program)

//Note that in the main program, the keyword is used
//with only one parameter.
//This is perfectly legal, but it means that the second
//variable on the list (:b) - or any unspecified variable -
//will have the last value when called again.
//Therefore the second variable is set to zero before
//exiting the routine.

//(The good thing about it is that it lets you code keywords
//with default parameters. Test if a parameter is zero, and
//if it is, assign it any "default" value you like. Otherwise
//the passed value is used.)

//The definition also uses mathematical statements in
//the recursive call.

//This illustrates a peculiarity of the language.
//When factorial :a-1 :b*:a is called the mathematical
//operations are not performed first and then results
//handed to the factorial code block (as one could expect).

//Instead, these operations are done as the first thing
//in the called block. First :a = :a-1 is done. Then
// :b = :a*:b
//However, as 1 has already been substracted from :a before
//multiplication, the first time factorial is called, :b is
//assigned :a not 1 (or it is assigned 1 and multiplied
//by :a).
