Programming in Maple
Roger Kraft Department of Mathematics, Computer Science, and Statistics Purdue University Calumet
roger@calumet.purdue.edu
4.10. Procedure data structure
We have said that almost everything in Maple is a data structure. So it should not be a surprise that procedures are themselves another kind of data structure and that they have the data type procedure . Here is a simple (and somewhat silly) example.
Let us check the data type of f .
Oops, forgot about last name evaluation.
Since our procedure is a data structure, we should be able to use the op command to examine the operands of this data structure, that is, use op to see what kind of data is stored in a procedure data structure.
The op command, however, works very strangely with procedure data structures, so looking at the data in a procedure is a bit confusing. First, since Maple uses last name evaluation for procedures, the following command gives us the data type of the name f , not the data type of f 's value, the procedure.
The next command gives us the data type of the procedure which is the value of f .
But in the next two commands, op switches to full evaluation and shows us the definition of the procedure named by f .
But the definition of the procedure is not the data stored in the procedure data structure. To get at the data stored in the procedure data structure, we use the following command.
There are actually eight operands in a procedure data structure, as the next command shows.
The next sequence of commands shows what is in each of the eight operands. A couple of these data items are currently empty in the data structure for f .
Notice that the first operand of a procedure data structure is an expression sequence of formal parameters. If a formal parameter has a type declaration, then the type declaration is held in a `::` data structure.
The second operand of a procedure data structure is an expression sequence of local variables. If a local variable has a type assertion, then the type assertion is held in a `::` data structure (we will not make use of type assertions in these worksheets).
Notice that the definition of the procedure is nowhere in the procedure data structure.
To summarize, op(f) returns the definition of the procedure and op(eval(f)) returns the contents of the procedure data structure.
There are eight operands in a procedure data structure and we access them using op(i, eval(f)) with i from 1 to 8. The first operand is the list of formal parameter names. The second operand is the list of local variable names. The third operand is a list of options. The fourth operand is called the remember table (we will discuss this operand in the next section). The fifth operand is a descriptive string. The sixth operand is the list of global variable names. The seventh operand is called the lexical table. Finally, the eighth operand is the (optional) return type.
Exercise : Explain what the following procedure does and how it does it. In particular, explain the reasons for the right-quotes.
Modify the procedure pds so that it displays a more descriptive message on the left hand side of each equal sign.
Of the eight operands in a procedure data structure, we already know what three of them represent. They are the formal parameters, the local variables, and the global variables. Of the remaining five, the remember table is the most important and we will discuss it in the next section. The descriptive string seems pretty self explanatory. The lexical table lists what are called "lexically scoped variables". These are variables that can only occur when one procedure is defined inside the body of another procedure. We will say more about this in a later (optional) section. The options operand we discuss next. And we will not be making any use of the "return type" in these worksheets.
A procedure definition can contain an optional option section. There are eight different properties that can be declared in the option section, arrow , builtin , inline , operator , remember , system , trace and Copyright . Right now we want to describe just three of these, the operator , arrow and trace options. The remember option will be described in the next section. The builtin and Copyright options will be discussed in the worksheet on Maple programming. The other options we will not mention any further.
If a procedure is defined with both the operator and arrow options, then the procedure acts exactly as if it were defined using the arrow notation.
Notice that if we define a function using the arrow notation
and then examine the option operand of the function's procedure data structure
it will have both the operator and arrow options. A procedure can have one of the operator or arrow options without the other, but we will not go into what that means.
Exercise : Try defining a procedure with just the operator option or just the arrow option. Do they act like functions defined using the arrow notation?
Now we shall mention the trace option. This is an option that is used for debugging a procedure. When we write procedures that are a bit complicated, it is very possible that we can make a mistake in the definition of the procedure and the procedure does not do what we expect it to do. Finding mistakes can be difficult, and the trace option is meant to help.
When a procedure has the trace option, Maple will print out quite a bit of information about the procedure whenever it is called. Here is an example with our silly function f , which has the trace option.
{--> enter f, args = 1, 2
<-- exit f (now at top level) = 8}
Let us define another procedure with the trace option that calls the procedure f .
Now let us call g to see what Maple produces for us.
{--> enter g, args = 2, 3
{--> enter f, args = 2, 2
<-- exit f (now in g) = 9}
{--> enter f, args = 3, 3
<-- exit f (now in g) = 11}
<-- exit g (now at top level) = 20}
What Maple is doing is giving us a "trace", or a history, of everything that goes on inside of the procedures g and f . Hopefully this information will be of use when we are trying to find out what we did wrong in the definition of a procedure. Here is another example. The following procedure takes as input a name and a positive integer and it truncates the name to the integer number of letters.
Let us call this procedure.
{--> enter shorten, args = a name that is too long, 6
<-- exit shorten (now at top level) = a name}
Notice how we can see all of the steps that occur inside the procedure as they are executed.
Exercise : What do you think should happen if you call shorten with the number n larger than the length of the name x ? What does happen and why? Notice how the trace lets you see what is going on inside of a procedure so that you can more easily answer questions like these.
Exercise : The following procedure was meant to reverse the letters in a name, so reverse_name(hello) was supposed to output olleh . But there is a bug in the procedure. Give the procedure the trace option and find the bug.
Exercise : Explain the relationship between a procedure data structure and function data structure. The following two help pages might help a bit.