Procedures

We have already looked at defining simple functions, where the argument is always taken to a specific expression, such as

[> f := (x) -> exp(-x)*sin(x):
[> f( 1.3 );

$0.2626002399$

[> f( x + 1 );

$e^{-x-1} \sin(x + 1)$

[> g := (x, y) -> x^2 - y^2:
[> g( 5, 3 );

$16$

[> g( a + b, a - b );

$(a + b)^2 - (a - b)^2$

On the other hand, you may want to implement a more serious function; for example:

  1. Defining a more complex mathematical function, such as a function that a tent function. In this case, you don't know what to return if the argument is, for example, $x + 1$.
  2. Implementing an algorithm such as Dijstra's algorithm on graph data structure.

These cannot be defined as simply as one or more arguments mapped to a result. For this, we need something more akin to a C or C++ function, which is implemented in Maple as a procedure. We will assume you know the basics of a C function:

[> procedure_name := proc( param_1::typename, param_2::typename, ... )::return_typename
    # List all variable names that are intended to be local variables,
    # and include their types
    local   local_var_1::typename,  local_var_2::typename,  local_var_3::typename, ...;

    # List any variables that are global variables
    #   - This is generally frowned upon...
    global global_var_1, global_var_2, global_var_3, ...;


    # Procedure body: all various sorts of statements include
    # while and for loops and conditional statements.

    # To exit a procedure, use
    #     return expression;
    # or even an expression sequence
    #     return expression, expression, ...;
end proc:

One important difference between C/C++ functions and Maple procedures is that parameters cannot be assigned to. They are protected, so under no conditions can you assign a parameter to, for example, round it to an integer:

double f( double x ) {
    x = std::round( x );

    // Do something with 'x'

    return something;
}

You will notice that a procedure is assigned to a variable name, and so this suggests that this also allows for anonymous procedures.

To be concluded...

This leads to a few issues: how do you recursively call a procedure if you don't necessarily know what it is assigned to? Maple deals with this by allowing you to refer to the procedure itself regardless of the actual name by referring to procname:

what it
[> factorial := proc( n::algebriac )::algebraic
    if n = 0 or n = 1 then
        return 1;
    elif n::posint then
        return n*procname( n - 1 );
    else
        return 'procname'( n );
    end if;
end proc: