Next: Macros, Previous: Introduction to Function Definition, Up: Function Definition [Contents][Index]
To define a function in Maxima you use the :=
operator.
E.g.
f(x) := sin(x)
defines a function f
.
Anonymous functions may also be created using lambda
.
For example
lambda ([i, j], ...)
can be used instead of f
where
f(i,j) := block ([], ...); map (lambda ([i], i+1), l)
would return a list with 1 added to each term.
You may also define a function with a variable number of arguments, by having a final argument which is assigned to a list of the extra arguments:
(%i1) f ([u]) := u; (%o1) f([u]) := u (%i2) f (1, 2, 3, 4); (%o2) [1, 2, 3, 4] (%i3) f (a, b, [u]) := [a, b, u]; (%o3) f(a, b, [u]) := [a, b, u] (%i4) f (1, 2, 3, 4, 5, 6); (%o4) [1, 2, [3, 4, 5, 6]]
The right hand side of a function is an expression. Thus if you want a sequence of expressions, you do
f(x) := (expr1, expr2, ...., exprn);
and the value of exprn is what is returned by the function.
If you wish to make a return
from some expression inside the
function then you must use block
and return
.
block ([], expr1, ..., if (a > 10) then return(a), ..., exprn)
is itself an expression, and so could take the place of the right hand side of a function definition. Here it may happen that the return happens earlier than the last expression.
The first []
in the block, may contain a list of variables and
variable assignments, such as [a: 3, b, c: []]
, which would cause the
three variables a
,b
,and c
to not refer to their
global values, but rather have these special values for as long as the
code executes inside the block
, or inside functions called from
inside the block
. This is called dynamic binding, since the
variables last from the start of the block to the time it exits. Once
you return from the block
, or throw out of it, the old values (if
any) of the variables will be restored. It is certainly a good idea
to protect your variables in this way. Note that the assignments
in the block variables, are done in parallel. This means, that if
you had used c: a
in the above, the value of c
would
have been the value of a
at the time you just entered the block,
but before a
was bound. Thus doing something like
block ([a: a], expr1, ... a: a+3, ..., exprn)
will protect the external value of a
from being altered, but
would let you access what that value was. Thus the right hand
side of the assignments, is evaluated in the entering context, before
any binding occurs.
Using just block ([x], ...)
would cause the x
to have itself
as value, just as if it would have if you entered a fresh Maxima
session.
The actual arguments to a function are treated in exactly same way as the variables in a block. Thus in
f(x) := (expr1, ..., exprn);
and
f(1);
we would have a similar context for evaluation of the expressions as if we had done
block ([x: 1], expr1, ..., exprn)
Inside functions, when the right hand side of a definition,
may be computed at runtime, it is useful to use define
and
possibly buildq
.
A memoizing function caches the result the first time it is called with a given argument, and returns the stored value, without recomputing it, when that same argument is given. Memoizing functions are often called array function and are in fact handled like arrays in many ways:
The names of memoizing functions are appended to the global list arrays
(not the global list functions
). arrayinfo
returns the list of
arguments for which there are stored values, and listarray
returns the
stored values. dispfun
and fundef
return the array function
definition.
arraymake
constructs an array function call,
analogous to funmake
for ordinary functions.
arrayapply
applies an array function to its arguments,
analogous to apply
for ordinary functions.
There is nothing exactly analogous to map
for array functions,
although map(lambda([x], a[x]), L)
or
makelist(a[x], x, L)
, where L is a list,
are not too far off the mark.
remarray
removes an array function definition (including any stored
function values), analogous to remfunction
for ordinary functions.
kill(a[x])
removes the value of the array function a
stored for the argument x;
the next time a is called with argument x,
the function value is recomputed.
However, there is no way to remove all of the stored values at once,
except for kill(a)
or remarray(a)
,
which also remove the function definition.
Examples
If evaluating the function needs much time and only a limited number of points is ever evaluated (which means not much time is spent looking up results in a long list of cached results) Memoizing functions can speed up calculations considerably.
(%i1) showtime:true$ Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes.
(%i2) a[x]:=float(sum(sin(x*t),t,1,10000)); Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes. (%o2) a := float(sum(sin(x t), t, 1, 10000)) x
(%i3) a[1]; Evaluation took 5.1250 seconds (5.1260 elapsed) using 775.250 MB. (%o3) 1.633891021792447
(%i4) a[1]; Evaluation took 0.0000 seconds (0.0000 elapsed) using 0 bytes. (%o4) 1.633891021792447
As the memoizing function is only evaluated once for each input value changes in variables the memoizing function uses are not considered for values that are already cached:
(%i1) a[x]:=b*x; (%o1) a := b x x
(%i2) b:1; (%o2) 1
(%i3) a[2]; (%o3) 2
(%i4) b:2; (%o4) 2
(%i5) a[1]; (%o5) 2
(%i6) a[2]; (%o6) 2
Next: Macros, Previous: Introduction to Function Definition, Up: Function Definition [Contents][Index]