OpenMusic

Visual Programming | Computer-Assisted Composition

OpenMusic Tutorials

Prev| Chapter 14. Flow Control IV: Recursive Functions| Next


Tutorial 38: Recursive patch I

Topics

Introduces the concept of recursion

Key Modules Used

omif, omloop, om=, om-

The Concept:

As we have seen, OM patches can contain calls to functions, factories, etc., nested to any level we like. It is even possible to put a call to itself within a function! A function which contains itself (created by dragging the patch from the Workspace into the patch window itself) is called a recursive function. Recursion is actually extremely useful and a powerful part of object-oriented programming.

Some computations require recursive functions, while others benefit from the clarity or speed of recursion, though they may be possible other ways. For example, the factorial procedure performed in Tutorial 36 can be performed more elegantly (and more quickly, it turns out) using a recursive function.

The scheme of the recursive function for finding 5! (5 factorial, that is the product 12345) for example, can be summarized:

We can imagine a function that multiplies 5 by a value taken from its last repetition and passes that to itself along with the value to multiply by (minus one). And here we run into a problem- since recursive functions call themselves, they must have a built in ‘brake’ in the form of a termination test. Only if the termination test fails should they call themselves. Without a termination test, the function continues to call itself on into infinity, eventually saturating the available memory and causing an error:

`> Error: Stack overflow on control stack. > To globally increase stack space,

increase minimum-stack-overflow-size > While executing: “Unknown” > Type Command-/ to continue, Command-. to abort. > If continued: Continue with a larger stack See the Restarts menu item for further choices.`

Let’s look at a recursive patch in OM which will calculate the factorial of whatever number we give it:

The Patch:

On the first repetition, _n_ is equal to 5 (in our example.) If _n_ is not equal to zero, which it is not, om* is called to multiply _n_ and the result of the recursion into the patch factorial. The trick is that we subtract 1 from _n_ before passing it to factorial. Before om* can complete, it must evaluate factorial. So factorial is evaluated using 4 for _n_. This recursion continues, going one level deeper each time (like Russian dolls), until finally, _n_ is zero. At this point, omif (the termination test at B) will return 1 instead of evaluating factorial. 1 is passed to the output, which (remember the Russian dolls?) is going to be coming into the om* function in the level of recursion just above. In that level, _n_ was equal to 1. 1 times 1 is 1, which is passed to the output, which is itself the second input to om* on the next level. _n_ is 2 on this level, and 2 times 1 is 2. Two is passed up out of that recursion to the next level where _n_ is 3. The product, 6, is passed, and we continue to work back up, layer by layer, until we reach the top, where the product of 12345, 120, is passed to the output.

To see this patch in action, drag it into any other patch.

Evaluate it with different numbers. Notice how it takes a longer time for big numbers (since more levels of recursion are being created).


Prev| Home| Next
—|—|—
Flow Control IV: Recursive Functions| Up| Tutorial 39: Recursive patch II