1.7. Functions that return a function (optional)
It is possible to do some unusual things with definitions of Maple functions. For example, we can define a function whose return value is another function. Here is a simple example.
The Maple function
f
takes in a number and returns a
function
that multiplies its input by the number.
So
f(3)
is a function that multiplies its input by 3. Here is how we apply
f(3)
to the input 4.
Here is another call to
f
.
Here is a call to the function that was returned by
f
.
In some sense you can think of
f
as a function of two variables.
But this can be misleading. Consider the next two function calls.
Exercise
: Consider the output of
f(y)
.
Now explain why the following function call does not return 9.
Exercise
: Each of the following functions that returns a function somehow involves a constant function. Explain where the constant functions are, and explain the reason for the way Maple simplifies each command.
Here is an example of how we might use the idea of a function that returns a function. Start with a function of two variables.
> |
f := (x,y) -> 3*x^2+5*y^2;
|
Now we shall define "slicing" functions for
f
. If we hold one input to
f
fixed, then we get a new function of a single variable that is sometimes called a "slice" (or a "section") of
f
. If we just plug a constant into
f
for say
y
, then we get back an expression in
x
.
We can turn that into a Maple function like this.
Now
fx3
is the slice of
f
with
y
fixed at
3
.
We can use a function that returns a function to automate these steps for generating slicing functions.
> |
slice_f_with_y_fixed := c -> ( x->f(x,c) );
|
The input to
slice_f_with_y_fixed
is the number we want the slice function at and the output is the slice function.
> |
fx3 := slice_f_with_y_fixed(3);
|
Now do the same for slices in the other direction.
> |
slice_f_with_x_fixed := c -> ( y->f(c,y) );
|
> |
f3y := slice_f_with_x_fixed(3);
|
One nice feature of our slicing functions is that they still work if we redefine
f
. We do not need to redefine the slicing functions.
> |
f := (u,v) -> sin(5*u-v);
|
> |
fu3 := slice_f_with_y_fixed(3);
|
Did you notice something a bit funny about the redefinition of
f
and the call to
slice_f_with_y_fixed
?
Exercise
: Come up with better names for
slice_f_with_y_fixed
and
slice_f_with_x_fixed
.
Exercise
: Define a Maple function
slicer1
with two inputs, one input a Maple function
h
of two variables and the other input a number
c
, that returns a Maple function that is the slice of the input function with its second input held fixed at
c
. Also define
slicer2
in an analogous way. Test the functions
slicer1
and
slicer2
.
Exercise
: Write Maple functions
shift_vertically
and
shift_horizontally
(you can abbreviate these names if you wish) that each take in two inputs, one input is a function of a single variable and the other input is a number, and that each return a function. The procedure
shift_vertically
produces an output function that is its input function shifted vertically by the amount of the input number, and
shift_horizontally
produces an output function that is its input function shifted horizontally by the amount of the input number. Apply your procedures to some test functions and show that they work by graphing the test functions and their shifted versions in the same graph.
Exercise
: Suppose you wanted to write a version of
slicer1
that worked on expressions instead of Maple functions. That is, suppose you wanted to write a procedure
slicer1
that takes as its input an expression of two variables and a number, and produces as its output an expression in one variable that represents the slice function of the function represented by the input expression with one of the inputs held fixed at the input number. What kind of problem are you going to have with trying to write this version of
slicer1
? (The problem you will have is in fact one of the major weaknesses of working with expressions.)
The idea of a function that returns a function is very common in mathematics. Sometimes these kinds of functions are given the special name
functionals
. One important branch of mathematics is called
functional analysis
. It is the study of the properties of functionals. In particular, functional analysis tries to generalize classical analysis, that is calculus with real and vector valued functions, to function valued functions.
Functions that return functions are also important in computer science. They lead to an important family of programming languages called
functional programming languages
. Some common functional programming languages are Lisp, Scheme, ML, and Haskell. These languages are very different from more traditional programming languages like C, C++, C#, Java, Fortran and Basic. As might be expected, functional programming languages have a much more mathematical feel to them then the more traditional programming languages. Functional programming languages have played an important role in the development of the field of artificial intelligence and in the theoretical developement of programming languages in general.
When we get to the chapter about Maple procedures, we will generalize the idea of a function that returns a function to the idea of a procedure that returns a procedure.