[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
41.1 Introduction to Program Flow | ||
41.2 Definitions for Program Flow |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Maxima provides a do
loop for iteration, as well as more primitive
constructs such as go
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Prints the call stack, that is, the list of functions which called the currently active function.
backtrace()
prints the entire call stack.
backtrace (n)
prints the n most recent
functions, including the currently active function.
backtrace
can be called from a script, a function, or the interactive prompt
(not only in a debugging context).
Examples:
backtrace()
prints the entire call stack.
(%i1) h(x) := g(x/7)$ (%i2) g(x) := f(x-11)$ (%i3) f(x) := e(x^2)$ (%i4) e(x) := (backtrace(), 2*x + 13)$ (%i5) h(10); #0: e(x=4489/49) #1: f(x=-67/7) #2: g(x=10/7) #3: h(x=10) 9615 (%o5) ---- 49 |
backtrace (n)
prints the n most recent
functions, including the currently active function.
(%i1) h(x) := (backtrace(1), g(x/7))$ (%i2) g(x) := (backtrace(1), f(x-11))$ (%i3) f(x) := (backtrace(1), e(x^2))$ (%i4) e(x) := (backtrace(1), 2*x + 13)$ (%i5) h(10); #0: h(x=10) #0: g(x=10/7) #0: f(x=-67/7) #0: e(x=4489/49) 9615 (%o5) ---- 49 |
The do
statement is used for performing iteration. Due to its
great generality the do
statement will be described in two parts.
First the usual form will be given which is analogous to that used in
several other programming languages (Fortran, Algol, PL/I, etc.); then
the other features will be mentioned.
There are three variants of this form that differ only in their terminating conditions. They are:
for variable: initial_value step increment
thru limit do body
for variable: initial_value step increment
while condition do body
for variable: initial_value step increment
unless condition do body
(Alternatively, the step
may be given after the termination condition
or limit.)
initial_value, increment, limit, and body can be any
expressions. If the increment is 1 then "step 1
" may be omitted.
The execution of the do
statement proceeds by first assigning the
initial_value to the variable (henceforth called the
control-variable). Then: (1) If the control-variable has exceeded the
limit of a thru
specification, or if the condition of the unless
is
true
, or if the condition of the while
is false
then the do
terminates. (2) The body is evaluated. (3) The increment is added to
the control-variable. The process from (1) to (3) is performed
repeatedly until the termination condition is satisfied. One may also
give several termination conditions in which case the do
terminates
when any of them is satisfied.
In general the thru
test is satisfied when the control-variable is
greater than the limit if the increment was non-negative, or when the
control-variable is less than the limit if the increment was negative.
The increment and limit may be non-numeric expressions as long as this
inequality can be determined. However, unless the increment is
syntactically negative (e.g. is a negative number) at the time the do
statement is input, Maxima assumes it will be positive when the do
is
executed. If it is not positive, then the do
may not terminate
properly.
Note that the limit, increment, and termination condition are
evaluated each time through the loop. Thus if any of these involve
much computation, and yield a result that does not change during all
the executions of the body, then it is more efficient to set a
variable to their value prior to the do
and use this variable in the
do
form.
The value normally returned by a do
statement is the atom done
.
However, the function
return
may be used inside the body to exit the do
prematurely and give
it any desired value.
Note however that a return
within a do
that
occurs in a block
will exit only the do
and not the block
. Note also
that the go
function may not be used to exit from a do
into a
surrounding block
.
The control-variable is always local to the do
and thus any
variable may be used without affecting the value of a variable with
the same name outside of the do
. The control-variable is unbound
after the do
terminates.
(%i1) for a:-3 thru 26 step 7 do display(a)$ a = - 3 a = 4 a = 11 a = 18 a = 25 |
(%i1) s: 0$ (%i2) for i: 1 while i <= 10 do s: s+i; (%o2) done (%i3) s; (%o3) 55 |
Note that the condition while i <= 10
is equivalent to unless i > 10
and also thru 10
.
(%i1) series: 1$ (%i2) term: exp (sin (x))$ (%i3) for p: 1 unless p > 7 do (term: diff (term, x)/p, series: series + subst (x=0, term)*x^p)$ (%i4) series; 7 6 5 4 2 x x x x x (%o4) -- - --- - -- - -- + -- + x + 1 90 240 15 8 2 |
which gives 8 terms of the Taylor series for e^sin(x)
.
(%i1) poly: 0$ (%i2) for i: 1 thru 5 do for j: i step -1 thru 1 do poly: poly + i*x^j$ (%i3) poly; 5 4 3 2 (%o3) 5 x + 9 x + 12 x + 14 x + 15 x (%i4) guess: -3.0$ (%i5) for i: 1 thru 10 do (guess: subst (guess, x, 0.5*(x + 10/x)), if abs (guess^2 - 10) < 0.00005 then return (guess)); (%o5) - 3.162280701754386 |
This example computes the negative square root of 10 using the
Newton- Raphson iteration a maximum of 10 times. Had the convergence
criterion not been met the value returned would have been done
.
Instead of always adding a quantity to the control-variable one
may sometimes wish to change it in some other way for each iteration.
In this case one may use next expression
instead of step increment
.
This will cause the control-variable to be set to the
result of evaluating expression each time through the loop.
(%i6) for count: 2 next 3*count thru 20 do display (count)$ count = 2 count = 6 count = 18 |
As an alternative to for variable: value ...do...
the syntax
for variable from value ...do...
may be used. This permits the
from value
to be placed after the step or next value or after the
termination condition. If from value
is omitted then 1 is used as
the initial value.
Sometimes one may be interested in performing an iteration where the control-variable is never actually used. It is thus permissible to give only the termination conditions omitting the initialization and updating information as in the following example to compute the square-root of 5 using a poor initial guess.
(%i1) x: 1000$ (%i2) thru 20 do x: 0.5*(x + 5.0/x)$ (%i3) x; (%o3) 2.23606797749979 (%i4) sqrt(5), numer; (%o4) 2.23606797749979 |
If it is desired one may even omit the termination conditions
entirely and just give do body
which will continue to evaluate the
body indefinitely. In this case the function return
should be used to
terminate execution of the do
.
(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), do (y: ev(df), x: x - f(x)/y, if abs (f (x)) < 5e-6 then return (x)))$ (%i2) sqr (x) := x^2 - 5.0$ (%i3) newton (sqr, 1000); (%o3) 2.236068027062195 |
(Note that return
, when executed, causes the current value of
x
to be returned as the value of the do
. The block
is exited and
this value of the do
is returned as the value of the block
because the
do
is the last statement in the block.)
One other form of the do
is available in Maxima. The syntax is:
for variable in list end_tests do body |
The elements of list are any expressions which will
successively be assigned to the variable on each iteration of the
body. The optional termination tests end_tests can be used to terminate execution of
the do
; otherwise it will terminate when the list is exhausted or when
a return
is executed in the body. (In fact, list may be any
non-atomic expression, and successive parts are taken.)
(%i1) for f in [log, rho, atan] do ldisp(f(1))$ (%t1) 0 (%t2) rho(1) %pi (%t3) --- 4 (%i4) ev(%t3,numer); (%o4) 0.78539816 |
Evaluates expr_1, ..., expr_n one by one and
returns [expr_n]
(a list) if no error occurs. If an
error occurs in the evaluation of any argument, errcatch
prevents the error from propagating and
returns the empty list []
without evaluating any more arguments.
errcatch
is useful in batch
files where one suspects an error might occur which
would terminate the batch
if the error weren't caught.
Evaluates and prints expr_1, ..., expr_n,
and then causes an error return to top level Maxima
or to the nearest enclosing errcatch
.
The variable error
is set to a list describing the error.
The first element of error
is a format string,
which merges all the strings among the arguments expr_1, ..., expr_n,
and the remaining elements are the values of any non-string arguments.
errormsg()
formats and prints error
.
This is effectively reprinting the most recent error message.
Reprints the most recent error message.
The variable error
holds the message,
and errormsg
formats and prints it.
Used in iterations. See do
for a description of
Maxima's iteration facilities.
is used within a block
to transfer control to the statement
of the block which is tagged with the argument to go
. To tag a
statement, precede it by an atomic argument as another statement in
the block
. For example:
block ([x], x:1, loop, x+1, ..., go(loop), ...) |
The argument to go
must be the name of a tag appearing in the same
block
. One cannot use go
to transfer to tag in a block
other than the
one containing the go
.
The if
statement is used for conditional execution. The syntax
is:
if <condition> then <expr_1> else <expr_2> |
The result of an if
statement is expr_1 if condition is true
and
expr_2 otherwise. expr_1 and expr_2 are any
Maxima expressions (including nested if
statements), and condition is
an expression which evaluates to true
or false
and is composed of
relational and logical operators which are as follows:
Operation Symbol Type less than < relational infix less than <= or equal to relational infix equality (syntactic) = relational infix negation of = # relational infix equality (value) equal relational function negation of equal notequal relational function greater than >= or equal to relational infix greater than > relational infix and and logical infix or or logical infix not not logical prefix |
Returns an expression whose leading operator
is the same as that of the expressions
expr_1, ..., expr_n but whose subparts are the results of
applying f to the corresponding subparts of the expressions. f is either
the name of a function of n arguments
or is a lambda
form of n arguments.
maperror
- if false
will cause all of the mapping functions to
(1) stop when they finish going down the shortest expi if not all of
the expi are of the same length and (2) apply fn to [exp1, exp2,...]
if the expi are not all the same type of object. If maperror
is true
then an error message will be given in the above two instances.
One of the uses of this function is to map
a function (e.g. partfrac
)
onto each term of a very large expression where it ordinarily wouldn't
be possible to use the function on the entire expression due to an
exhaustion of list storage space in the course of the computation.
(%i1) map(f,x+a*y+b*z); (%o1) f(b z) + f(a y) + f(x) (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 1 1 1 (%o2) ----- - ----- + -------- + x x + 2 x + 1 2 (x + 1) (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y); 1 (%o3) y + ----- + 1 x + 1 (%i4) map("=",[a,b],[-0.5,3]); (%o4) [a = - 0.5, b = 3] |
Returns true
if and only if expr is treated by the mapping
routines as an atom. "Mapatoms" are atoms, numbers
(including rational numbers), and subscripted variables.
Default value: true
When maperror
is false
, causes all of the mapping functions, for example
map (f, expr_1, expr_2, ...)) |
to (1) stop when they finish
going down the shortest expi if not all of the expi are of the same
length and (2) apply f
to [expr_1, expr_2, ...]
if the expr_i
are not all
the same type of object.
If maperror
is true
then an error message
is displayed in the above two instances.
Returns a list of the applications of f to the parts of the expressions expr_1, ..., expr_n. f is the name of a function, or a lambda expression.
maplist
differs from map (f, expr_1, ..., expr_n)
which returns an expression with the same main operator as expr_i has
(except for simplifications and the case where map
does an apply
).
Default value: true
When prederror
is true
, an error message is displayed
whenever the predicate of an if
statement or an is
function fails to
evaluate to either true
or false
.
If false
, unknown
is returned
instead in this case. The prederror: false
mode is not supported in
translated code;
however, maybe
is supported in translated code.
See also is
and maybe
.
May be used to exit explicitly from a block, bringing
its argument. See block
for more information.
Recursively applies f to expr, in a top down manner. This is most useful when complete factorization is desired, for example:
(%i1) exp:(a^2+2*a+1)*y + x^2$ (%i2) scanmap(factor,exp); 2 2 (%o2) (a + 1) y + x |
Note the way in which scanmap
applies the given function factor
to the
constituent subexpressions of expr; if another form of expr is presented
to scanmap
then the result may be different. Thus, %o2
is not
recovered when scanmap
is applied to the expanded form of exp:
(%i3) scanmap(factor,expand(exp)); 2 2 (%o3) a y + 2 a y + y + x |
Here is another example of the way in which scanmap
recursively
applies a given function to all subexpressions, including exponents:
(%i4) expr : u*v^(a*x+b) + c$ (%i5) scanmap('f, expr); f(f(f(a) f(x)) + f(b)) (%o5) f(f(f(u) f(f(v) )) + f(c)) |
scanmap (f, expr, bottomup)
applies f to expr in a
bottom-up manner. E.g., for undefined f
,
scanmap(f,a*x+b) -> f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b)) scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b) -> f(f(a)*f(x))+f(b) -> f(f(f(a)*f(x))+f(b)) |
In this case, you get the same answer both ways.
Evaluates expr and throws the value back to the most recent
catch
. throw
is used with catch
as a nonlocal return
mechanism.
Applies the function f to each one of the elements of the outer product a_1 cross a_2 ... cross a_n.
f is be the name of a function of n arguments or a lambda expression of n arguments. The arguments a_1, ..., a_n may be lists or nonlists. List arguments may have different lengths. Arguments other than lists are treated as lists of length 1 for the purpose of constructing the outer product.
The result of applying f to the outer product is organized as a nested list. The depth of nesting is equal to the number of list arguments (arguments other than lists do not contribute a nesting level). A list at nesting depth k has the same length as the k'th list argument.
outermap
evaluates its arguments.
See also map
, maplist
, and apply
.
Examples:
(%i1) f (x, y) := x - y$ (%i2) outermap (f, [2, 3, 5], [a, b, c, d]); (%o2) [[2 - a, 2 - b, 2 - c, 2 - d], [3 - a, 3 - b, 3 - c, 3 - d], [5 - a, 5 - b, 5 - c, 5 - d]] (%i3) outermap (lambda ([x, y], y/x), [55, 99], [Z, W]); Z W Z W (%o3) [[--, --], [--, --]] 55 55 99 99 (%i4) g: lambda ([x, y, z], x + y*z)$ (%i5) outermap (g, [a, b, c], %pi, [11, 17]); (%o5) [[a + 11 %pi, a + 17 %pi], [b + 11 %pi, b + 17 %pi], [c + 11 %pi, c + 17 %pi]] (%i6) flatten (%); (%o6) [a + 11 %pi, a + 17 %pi, b + 11 %pi, b + 17 %pi, c + 11 %pi, c + 17 %pi] |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on March, 19 2006 using texi2html 1.76.