Application Center - Maplesoft

App Preview:

Maple Programming: 2.8: Evaluating function definitions

You can switch back to the summary page by clicking here.

Learn about Maple
Download Application


 

2.08.mws

Programming in Maple

Roger Kraft
Department of Mathematics, Computer Science, and Statistics
Purdue University Calumet

roger@calumet.purdue.edu

2.8. Evaluating function definitions

In the last section we emphasized how Maple evaluates function calls. Here we look at how Maple evaluates a function's definition. We will see that this also gives us more information about the evaluation of function calls.

Let us give x  a value.

>    x := -2;

x := -2

If we define f  as an expression in x , then full evaluation will evaluate x  right away and so x  will not really be part of the value of f .

>    f := x^2-1;

f := 3

If we now change x , this does not affect f .

>    x := -5;

x := -5

>    f;

3

Now define g  as a Maple function and use x  as the independent variable in the definition of g .

>    g := x -> x^2-1;

g := proc (x) options operator, arrow; x^2-1 end proc

Maple did not use full evaluation here. None of the x 's on the right hand side of the assignment operator were evaluated. If we evaluate a function call using g , then the x  in the definition of g  will get the operand of the function call, not the current value of x .

>    g(6);

35

Notice that the current value of x  (which is -5 ) has nothing to do with the evaluation of g(6) .

>   

Here is another example. Suppose we give the name c  a value and then use it in the definition of g  along with x .

>    c := -2;

c := -2

>    g := x -> c*x^2-1;

g := proc (x) options operator, arrow; c*x^2-1 end proc

Notice that neither c  nor x  was evaluated in the definition of g .

>    eval( g );

proc (x) options operator, arrow; c*x^2-1 end proc

If we evaluate a function call using g , then Maple will use the current value of c  in evaluating the function call but not the current value of x . This is because c  is a parameter in the definition of g  but x  is the independent variable (and independent variables get their values from the function call's operands).

>    g(3);

-19

If we now change the value of c , then the definition of g  is unchanged, but the evaluation of g  in a function call will change.

>    c := 2;

c := 2

>    eval( g );

proc (x) options operator, arrow; c*x^2-1 end proc

>    g(3);

17

We can even leave c  unassigned.

>    c := 'c';

c := 'c'

>    g(3);

9*c-1

>   

So when Maple evaluates a function definition using the arrow operator, it does not evaluate any of the names in the definition, neither the independent variables nor the parameters. When Maple evaluates a function call, then the independent variables get their values from the operands of the function call, and the parameters in the function definition are fully evaluated to whatever values they may currently have at the time of the function call.

>   

So far we have looked at how Maple evaluates a function definition that uses the arrow notation. But we can also define Maple functions using the unapply  command. Let us see how Maple evaluates a function definition that uses the unapply  command.

>    g := unapply( c*x^2-1, x );

Error, (in unapply) variables must be unique and of type name

We got an error message. What happened is that Maple used full evaluation for the unapply  command. So this last command looked to Maple like the following

>    g := unapply( 25*c-1, -5 );

Error, (in unapply) variables must be unique and of type name

because x  has a value (and c  does not).

>    x, c;

-5, c

Here is a way to verify this.

>    'unapply'( c*x^2-1, x );

unapply(25*c-1,-5)

So the unapply  command uses full evaluation. Let us see how that affects the function we are defining. First of all, we must have the independent variable (in this case x ) as an unassigned variable.

>    x := 'x';

x := 'x'

Now we can use unapply .

>    g := unapply( c*x^2-1, x );

g := proc (x) options operator, arrow; c*x^2-1 end proc

Notice that since c  is currently unassigned, c  is a parameter in the definition of g .

>    g(3);

9*c-1

We can give c  different values and get different evaluations of function calls to g .

>    c := -1;

c := -1

>    g(3); g(w);

-10

-w^2-1

>    c := 2;

c := 2

>    g(3); g(w);

17

2*w^2-1

What happens if we now use unapply  again to redefine g  using the same expression?

>    g := unapply( c*x^2-1, x );

g := proc (x) options operator, arrow; 2*x^2-1 end proc

Now, since c  is an assigned variable and Maple uses full evaluation in the unapply  command, we no longer have c  as a parameter in the definition of g . The value 2 is now a permanent part of the definition of g .

>    eval( g );

proc (x) options operator, arrow; 2*x^2-1 end proc

>    c := 5;

c := 5

>    eval( g );

proc (x) options operator, arrow; 2*x^2-1 end proc

What if we want to use unapply  and force c  to be a parameter in the definition of g ? Then we would need to delay the evaluation of c  in the unapply  command.

>    g := unapply( 'c'*x^2-1, x );

g := proc (x) options operator, arrow; c*x^2-1 end proc

>    eval( g );

proc (x) options operator, arrow; c*x^2-1 end proc

>    g(x);

5*x^2-1

Why is there a 5 in the last expression?

>    c := -2;

c := -2

>    g(x);

-2*x^2-1

>   

In summary, the arrow operator and the unassign  command use very different evaluation rules when used to define a Maple function. The arrow operator does not evaluate any of the names used in the definition of the function, and the unapply  command uses full evaluation (except in cases where last name evaluation should be used).

>   

Exercise : Explain each the following three sequences of commands.

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g := x -> c*h(x) -1;

g := proc (x) options operator, arrow; c*h(x)-1 end proc

>    g(3);

-19

>    h := x -> x^3;

h := proc (x) options operator, arrow; x^3 end proc

>    g(3);

-55

>   

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g := unapply( c*h(x)-1, x );

g := proc (x) options operator, arrow; -2*x^2-1 end proc

>    g(3);

-19

>    h := x -> x^3;

h := proc (x) options operator, arrow; x^3 end proc

>    g(3);

-19

>   

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g := unapply( c*'h'(x)-1, x );

g := proc (x) options operator, arrow; -2*h(x)-1 end proc

>    g(3);

-19

>    h := x -> x^3;

h := proc (x) options operator, arrow; x^3 end proc

>    g(3);

-55

>    eval( g );

proc (x) options operator, arrow; -2*h(x)-1 end proc

>   

Exercise : Explain the following sequence of commands.

>    h := x -> x^3;

h := proc (x) options operator, arrow; x^3 end proc

>    g := h -> h(5);

g := proc (h) options operator, arrow; h(5) end proc

>    g(h);

125

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g(h);

25

>    g := unapply( h(5), h );

g := 25

>    g := unapply( 'h'(5), h );

g := proc (h) options operator, arrow; h(5) end proc

Since h  has a value, why was there no error message from the last two commands?

>    eval( h );

proc (x) options operator, arrow; x^2 end proc

For example, here we get an error message

>    x := 5;

>    unapply( h(x), x );

x := 5

Error, (in unapply) variables must be unique and of type name

which we get rid of this way.

>    unapply( h(x), 'x' );

25

>   

Exercise : Explain the following sequence of commands.

>    h := x -> x^3;

h := proc (x) options operator, arrow; x^3 end proc

>    g := h -> h(x);

g := proc (h) options operator, arrow; h(x) end proc

>    g(h);

125

>    x := y;

x := y

>    g(h);

y^3

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g(h);

y^2

>    g := unapply('h'(x), h);

g := proc (h) options operator, arrow; h(y) end proc

>    x := z;

x := z

>    g(h);

y^2

>    g := unapply('h'('x'), h);

g := proc (h) options operator, arrow; h(x) end proc

>    g(h);

z^2

>   

Exercise : Explain with as much detail as you can how Maple evaluates the following commands. What rules of evaluation are used at each step.

>    x := 0;

x := 0

>    h := x -> x^2;

h := proc (x) options operator, arrow; x^2 end proc

>    g := (h, x) -> h(x);

g := proc (h, x) options operator, arrow; h(x) end proc

>    g(h, y);

y^2

>    g := (h, x) -> 'h'(x);

g := proc (h, x) options operator, arrow; ('h')(x) end proc

>    g(h, y);

h(y)

>    g(sin, Pi);

sin(Pi)

>    g(eval(h), y);

proc (x) options operator, arrow; x^2 end proc(y)

>    %;

y^2

>    eval(g(h, y));

y^2

>    g(eval(sin), Pi);

proc (x::algebraic) local n, t, pull_out, keep_in; option `Copyright (c) 1992 by the University of Waterloo. All rights reserved.`; if nargs <> 1 then error

How would we use unapply  to define the exact same function g  that we have right now?

>    eval( g );

proc (h, x) options operator, arrow; ('h')(x) end proc

The following is not correct. Try to fix it.

>    g := unapply( 'h'('x'), h, 'x');

g := proc (h, x) options operator, arrow; h(x) end proc

Explain what happens if you remove any one of the pairs of right-quotes from the unapply  command. And why does the last h  in the unapply  command not even need right-quotes?

>   

>   

>