1@menu 2* Lisp and Maxima:: 3* Garbage Collection:: 4* Introduction to Program Flow:: 5* Functions and Variables for Program Flow:: 6@end menu 7 8@c ----------------------------------------------------------------------------- 9@node Lisp and Maxima, Garbage Collection, Program Flow, Program Flow 10@section Lisp and Maxima 11@c ----------------------------------------------------------------------------- 12 13Maxima is a fairly complete programming language. But since it is written in 14Lisp, it additionally can provide easy access to Lisp functions and variables 15from Maxima and vice versa. Lisp and Maxima symbols are distinguished by a 16naming convention. A Lisp symbol which begins with a dollar sign @code{$} 17corresponds to a Maxima symbol without the dollar sign. 18 19@c NEED TO MENTION THIS OR IS IT JUST CLUTTERING ?? 20@c This includes special Maxima variables such as @code{%} and input and output 21@c labels, which appear as @code{$%}, @code{$%i1}, @code{$%o1}, etc., in Lisp. 22 23A Maxima symbol which begins with a question mark @code{?} corresponds to a Lisp 24symbol without the question mark. For example, the Maxima symbol @code{foo} 25corresponds to the Lisp symbol @code{$FOO}, while the Maxima symbol @code{?foo} 26corresponds to the Lisp symbol @code{FOO}. Note that @code{?foo} is written 27without a space between @code{?} and @code{foo}; otherwise it might be mistaken 28for @code{describe ("foo")}. 29 30Hyphen @code{-}, asterisk @code{*}, or other special characters in Lisp symbols 31must be escaped by backslash @code{\} where they appear in Maxima code. For 32example, the Lisp identifier @code{*foo-bar*} is written @code{?\*foo\-bar\*} 33in Maxima. 34 35Lisp code may be executed from within a Maxima session. A single line of Lisp 36(containing one or more forms) may be executed by the special command 37@code{:lisp}. For example, 38 39@example 40(%i1) :lisp (foo $x $y) 41@end example 42 43@noindent 44calls the Lisp function @code{foo} with Maxima variables @code{x} and @code{y} 45as arguments. The @code{:lisp} construct can appear at the interactive prompt 46or in a file processed by @mref{batch} or @mrefcomma{demo} but not in a file 47processed by @mrefcomma{load} @mrefcomma{batchload}@w{} 48@mrefcomma{translate_file} or @mrefdot{compile_file} 49 50The function @mref{to_lisp} opens an interactive Lisp session. 51Entering @code{(to-maxima)} closes the Lisp session and returns to Maxima. 52@c I DON'T EVEN WANT TO MENTION USING CTRL-C TO OPEN A LISP SESSION. 53@c (1) IT TAKES EXTRA SET UP TO GET STARTED NAMELY :lisp (setq *debugger-hook* nil) 54@c (2) IT GETS SCREWED UP EASILY -- TYPE SOMETHING WRONG AND YOU CAN'T GET BACK TO MAXIMA 55@c (3) IT DOESN'T OFFER FUNCTIONALITY NOT PRESENT IN THE to_lisp() SESSION 56 57Lisp functions and variables which are to be visible in Maxima as functions and 58variables with ordinary names (no special punctuation) must have Lisp names 59beginning with the dollar sign @code{$}. 60 61Maxima is case-sensitive, distinguishing between lowercase and uppercase letters 62in identifiers. There are some rules governing the translation of names between 63Lisp and Maxima. 64 65@enumerate 66@item 67A Lisp identifier not enclosed in vertical bars corresponds to a Maxima 68identifier in lowercase. Whether the Lisp identifier is uppercase, lowercase, 69or mixed case, is ignored. E.g., Lisp @code{$foo}, @code{$FOO}, and @code{$Foo} 70all correspond to Maxima @code{foo}. But this is because @code{$foo}, 71@code{$FOO} and @code{$Foo} are converted by the Lisp reader by default to the 72Lisp symbol @code{$FOO}. 73@item 74A Lisp identifier which is all uppercase or all lowercase and enclosed in 75vertical bars corresponds to a Maxima identifier with case reversed. That is, 76uppercase is changed to lowercase and lowercase to uppercase. E.g., Lisp 77@code{|$FOO|} and @code{|$foo|} correspond to Maxima @code{foo} and @code{FOO}, 78respectively. 79@item 80A Lisp identifier which is mixed uppercase and lowercase and enclosed in 81vertical bars corresponds to a Maxima identifier with the same case. E.g., 82Lisp @code{|$Foo|} corresponds to Maxima @code{Foo}. 83@end enumerate 84 85The @code{#$} Lisp macro allows the use of Maxima expressions in Lisp code. 86@code{#$@var{expr}$} expands to a Lisp expression equivalent to the Maxima 87expression @var{expr}. 88 89@example 90(msetq $foo #$[x, y]$) 91@end example 92 93@noindent 94This has the same effect as entering 95 96@example 97(%i1) foo: [x, y]; 98@end example 99 100@noindent 101The Lisp function @code{displa} prints an expression in Maxima format. 102 103@example 104(%i1) :lisp #$[x, y, z]$ 105((MLIST SIMP) $X $Y $Z) 106(%i1) :lisp (displa '((MLIST SIMP) $X $Y $Z)) 107[x, y, z] 108NIL 109@end example 110 111Functions defined in Maxima are not ordinary Lisp functions. The Lisp function 112@code{mfuncall} calls a Maxima function. For example: 113 114@example 115(%i1) foo(x,y) := x*y$ 116(%i2) :lisp (mfuncall '$foo 'a 'b) 117((MTIMES SIMP) A B) 118@end example 119 120Some Lisp functions are shadowed in the Maxima package, namely the following. 121 122@verbatim 123 complement continue // 124 float functionp array 125 exp listen signum 126 atan asin acos 127 asinh acosh atanh 128 tanh cosh sinh 129 tan break gcd 130@end verbatim 131 132@opencatbox 133@category{Programming} 134@closecatbox 135 136@c ----------------------------------------------------------------------------- 137@node Garbage Collection, Introduction to Program Flow, Lisp and Maxima, Program Flow 138@section Garbage Collection 139@c ----------------------------------------------------------------------------- 140 141One of the advantages of using lisp is that it uses ``Garbage Collection''. In other 142words it automatically takes care of freeing memory occupied for example of 143intermediate results that were used during symbolic computation. 144 145Garbage Collection avoids many errors frequently found in C programs (memory 146being freed too early, multiple times or not at all). 147 148@c ----------------------------------------------------------------------------- 149 150@anchor{garbage_collect} 151@deffn {Function} garbage_collect () 152 153Tries to manually trigger the lisp's garbage collection. This rarely is necessary 154as the lisp will employ an excellent algorithm for determining when to start 155garbage collection. 156 157If maxima knows how to do manually trigger the garbage collection for the 158current lisp @code{garbage_collect} returns @code{true}, else @code{false}. 159 160@opencatbox 161@category{Programming} 162@closecatbox 163@end deffn 164 165@c ----------------------------------------------------------------------------- 166@node Introduction to Program Flow, Functions and Variables for Program Flow, Garbage Collection, Program Flow 167@section Introduction to Program Flow 168@c ----------------------------------------------------------------------------- 169 170Maxima provides a @code{do} loop for iteration, as well as more primitive 171constructs such as @code{go}. 172 173@c end concepts Program Flow 174 175@c ----------------------------------------------------------------------------- 176@node Functions and Variables for Program Flow, , Introduction to Program Flow, Program Flow 177@section Functions and Variables for Program Flow 178@c ----------------------------------------------------------------------------- 179 180@c ----------------------------------------------------------------------------- 181@anchor{backtrace} 182@deffn {Function} backtrace @ 183@fname{backtrace} () @ 184@fname{backtrace} (@var{n}) 185 186Prints the call stack, that is, the list of functions which 187called the currently active function. 188 189@code{backtrace ()} prints the entire call stack. 190 191@code{backtrace (@var{n})} prints the @var{n} most recent 192functions, including the currently active function. 193 194@c IS THIS STATEMENT REALLY NEEDED ?? 195@c (WHY WOULD ANYONE BELIEVE backtrace CANNOT BE CALLED OUTSIDE A DEBUGGING CONTEXT??) 196@code{backtrace} can be called from a script, a function, or the interactive 197prompt (not only in a debugging context). 198 199Examples: 200 201@itemize @bullet 202@item 203@code{backtrace ()} prints the entire call stack. 204 205@example 206(%i1) h(x) := g(x/7)$ 207(%i2) g(x) := f(x-11)$ 208(%i3) f(x) := e(x^2)$ 209(%i4) e(x) := (backtrace(), 2*x + 13)$ 210(%i5) h(10); 211#0: e(x=4489/49) 212#1: f(x=-67/7) 213#2: g(x=10/7) 214#3: h(x=10) 215 9615 216(%o5) ---- 217 49 218@end example 219@end itemize 220 221@itemize @bullet 222@item 223@code{backtrace (@var{n})} prints the @var{n} most recent 224functions, including the currently active function. 225 226@example 227(%i1) h(x) := (backtrace(1), g(x/7))$ 228(%i2) g(x) := (backtrace(1), f(x-11))$ 229(%i3) f(x) := (backtrace(1), e(x^2))$ 230(%i4) e(x) := (backtrace(1), 2*x + 13)$ 231(%i5) h(10); 232#0: h(x=10) 233#0: g(x=10/7) 234#0: f(x=-67/7) 235#0: e(x=4489/49) 236 9615 237(%o5) ---- 238 49 239@end example 240@end itemize 241 242@opencatbox 243@category{Debugging} 244@closecatbox 245@end deffn 246 247@c ----------------------------------------------------------------------------- 248@anchor{do} 249@anchor{while} 250@anchor{unless} 251@anchor{for} 252@anchor{from} 253@anchor{thru} 254@anchor{step} 255@anchor{next} 256@anchor{in} 257@deffn {Special operator} do 258@deffnx {Special operator} while 259@deffnx {Special operator} unless 260@deffnx {Special operator} for 261@deffnx {Special operator} from 262@deffnx {Special operator} thru 263@deffnx {Special operator} step 264@deffnx {Special operator} next 265@deffnx {Special operator} in 266 267The @code{do} statement is used for performing iteration. The general 268form of the @code{do} statements maxima supports is: 269 270@itemize @bullet 271@item 272@code{for @var{variable}: @var{initial_value} step @var{increment} 273 thru @var{limit} do @var{body}} 274@item 275@code{for @var{variable}: @var{initial_value} step @var{increment} 276 while @var{condition} do @var{body}} 277@item 278@code{for @var{variable}: @var{initial_value} step @var{increment} 279 unless @var{condition} do @var{body}} 280@item 281@code{for @var{variable} in @var{list} do @var{body}} 282@end itemize 283 284If the loop is expected to generate a list as output the command 285@mref{makelist} may be the appropriate command to use instead, 286@xref{Performance considerations for Lists}. 287 288@var{initial_value}, @var{increment}, @var{limit}, and @var{body} can be any 289expression. @var{list} is a list. If the increment is 1 then "@code{step 1}" 290may be omitted; As always, if @code{body} needs to contain more than one command 291these commands can be specified as a comma-separated list surrounded 292by parenthesis or as a @mrefdot{block} 293Due to its great generality the @code{do} statement will be described in two parts. 294The first form of the @code{do} statement (which is shown in the first three 295items above) is analogous to that used in 296several other programming languages (Fortran, Algol, PL/I, etc.); then 297the other features will be mentioned. 298 299The execution of the @code{do} statement proceeds by first assigning 300the @var{initial_value} to the @var{variable} (henceforth called the 301control-variable). Then: (1) If the control-variable has exceeded the 302limit of a @code{thru} specification, or if the condition of the 303@code{unless} is @code{true}, or if the condition of the @code{while} 304is @code{false} then the @code{do} terminates. (2) The @var{body} is 305evaluated. (3) The increment is added to the control-variable. The 306process from (1) to (3) is performed repeatedly until the termination 307condition is satisfied. One may also give several termination 308conditions in which case the @code{do} terminates when any of them is 309satisfied. 310 311In general the @code{thru} test is satisfied when the control-variable 312is greater than the @var{limit} if the @var{increment} was 313non-negative, or when the control-variable is less than the 314@var{limit} if the @var{increment} was negative. The 315@var{increment} and @var{limit} may be non-numeric expressions as 316long as this inequality can be determined. However, unless the 317@var{increment} is syntactically negative (e.g. is a negative number) 318at the time the @code{do} statement is input, Maxima assumes it will 319be positive when the @code{do} is executed. If it is not positive, 320then the @code{do} may not terminate properly. 321 322Note that the @var{limit}, @var{increment}, and termination condition are 323evaluated each time through the loop. Thus if any of these involve 324much computation, and yield a result that does not change during all 325the executions of the @var{body}, then it is more efficient to set a 326variable to their value prior to the @code{do} and use this variable in the 327@code{do} form. 328 329The value normally returned by a @code{do} statement is the atom 330@code{done}. However, the function @code{return} may be used inside 331the @var{body} to exit the @code{do} prematurely and give it any 332desired value. Note however that a @code{return} within a @code{do} 333that occurs in a @code{block} will exit only the @code{do} and not the 334@code{block}. Note also that the @code{go} function may not be used 335to exit from a @code{do} into a surrounding @code{block}. 336 337The control-variable is always local to the @code{do} and thus any 338variable may be used without affecting the value of a variable with 339the same name outside of the @code{do}. The control-variable is unbound 340after the @code{do} terminates. 341 342@example 343(%i1) for a:-3 thru 26 step 7 do display(a)$ 344 a = - 3 345 346 a = 4 347 348 a = 11 349 350 a = 18 351 352 a = 25 353@end example 354 355@c ===beg=== 356@c s: 0$ 357@c for i: 1 while i <= 10 do s: s+i; 358@c s; 359@c ===end=== 360@example 361(%i1) s: 0$ 362(%i2) for i: 1 while i <= 10 do s: s+i; 363(%o2) done 364(%i3) s; 365(%o3) 55 366@end example 367 368Note that the condition @code{while i <= 10} 369is equivalent to @code{unless i > 10} and also @code{thru 10}. 370 371@c ===beg=== 372@c series: 1$ 373@c term: exp (sin (x))$ 374@c for p: 1 unless p > 7 do 375@c (term: diff (term, x)/p, 376@c series: series + subst (x=0, term)*x^p)$ 377@c series; 378@c ===end=== 379@example 380(%i1) series: 1$ 381(%i2) term: exp (sin (x))$ 382(%i3) for p: 1 unless p > 7 do 383 (term: diff (term, x)/p, 384 series: series + subst (x=0, term)*x^p)$ 385(%i4) series; 386 7 6 5 4 2 387 x x x x x 388(%o4) -- - --- - -- - -- + -- + x + 1 389 90 240 15 8 2 390@end example 391 392which gives 8 terms of the Taylor series for @code{e^sin(x)}. 393 394@c ===beg=== 395@c poly: 0$ 396@c for i: 1 thru 5 do 397@c for j: i step -1 thru 1 do 398@c poly: poly + i*x^j$ 399@c poly; 400@c guess: -3.0$ 401@c for i: 1 thru 10 do 402@c (guess: subst (guess, x, 0.5*(x + 10/x)), 403@c if abs (guess^2 - 10) < 0.00005 then return (guess)); 404@c ===end=== 405@example 406(%i1) poly: 0$ 407(%i2) for i: 1 thru 5 do 408 for j: i step -1 thru 1 do 409 poly: poly + i*x^j$ 410(%i3) poly; 411 5 4 3 2 412(%o3) 5 x + 9 x + 12 x + 14 x + 15 x 413(%i4) guess: -3.0$ 414(%i5) for i: 1 thru 10 do 415 (guess: subst (guess, x, 0.5*(x + 10/x)), 416 if abs (guess^2 - 10) < 0.00005 then return (guess)); 417(%o5) - 3.162280701754386 418@end example 419 420This example computes the negative square root of 10 using the 421Newton- Raphson iteration a maximum of 10 times. Had the convergence 422criterion not been met the value returned would have been @code{done}. 423 424Instead of always adding a quantity to the control-variable one 425may sometimes wish to change it in some other way for each iteration. 426In this case one may use @code{next @var{expression}} instead of 427@code{step @var{increment}}. This will cause the control-variable to be set to 428the result of evaluating @var{expression} each time through the loop. 429 430@example 431(%i6) for count: 2 next 3*count thru 20 do display (count)$ 432 count = 2 433 434 count = 6 435 436 count = 18 437@end example 438 439@c UGH. DO WE REALLY NEED TO MENTION THIS?? 440As an alternative to @code{for @var{variable}: @var{value} ...do...} 441the syntax @code{for @var{variable} from @var{value} ...do...} may be 442used. This permits the @code{from @var{value}} to be placed after the 443@code{step} or @code{next} value or after the termination condition. 444If @code{from @var{value}} is omitted then 1 is used as the initial 445value. 446 447Sometimes one may be interested in performing an iteration where 448the control-variable is never actually used. It is thus permissible 449to give only the termination conditions omitting the initialization 450and updating information as in the following example to compute the 451square-root of 5 using a poor initial guess. 452 453@c ===beg=== 454@c x: 1000$ 455@c thru 20 do x: 0.5*(x + 5.0/x)$ 456@c x; 457@c sqrt(5), numer; 458@c ===end=== 459@example 460(%i1) x: 1000$ 461(%i2) thru 20 do x: 0.5*(x + 5.0/x)$ 462(%i3) x; 463(%o3) 2.23606797749979 464(%i4) sqrt(5), numer; 465(%o4) 2.23606797749979 466@end example 467 468If it is desired one may even omit the termination conditions entirely 469and just give @code{do @var{body}} which will continue to evaluate the 470@var{body} indefinitely. In this case the function @code{return} 471should be used to terminate execution of the @code{do}. 472 473@c ===beg=== 474@c newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), 475@c do (y: ev(df), x: x - f(x)/y, 476@c if abs (f (x)) < 5e-6 then return (x)))$ 477@c sqr (x) := x^2 - 5.0$ 478@c newton (sqr, 1000); 479@c ===end=== 480@example 481(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), 482 do (y: ev(df), x: x - f(x)/y, 483 if abs (f (x)) < 5e-6 then return (x)))$ 484(%i2) sqr (x) := x^2 - 5.0$ 485(%i3) newton (sqr, 1000); 486(%o3) 2.236068027062195 487@end example 488 489@c DUNNO IF WE NEED THIS LEVEL OF DETAIL; THIS ARTICLE IS GETTING PRETTY LONG 490(Note that @code{return}, when executed, causes the current value of @code{x} to 491be returned as the value of the @code{do}. The @code{block} is exited and this 492value of the @code{do} is returned as the value of the @code{block} because the 493@code{do} is the last statement in the block.) 494 495One other form of the @code{do} is available in Maxima. The syntax is: 496 497@example 498for @var{variable} in @var{list} @var{end_tests} do @var{body} 499@end example 500 501The elements of @var{list} are any expressions which will successively 502be assigned to the @code{variable} on each iteration of the 503@var{body}. The optional termination tests @var{end_tests} can be 504used to terminate execution of the @code{do}; otherwise it will 505terminate when the @var{list} is exhausted or when a @code{return} is 506executed in the @var{body}. (In fact, @code{list} may be any 507non-atomic expression, and successive parts are taken.) 508 509@example 510(%i1) for f in [log, rho, atan] do ldisp(f(1))$ 511(%t1) 0 512(%t2) rho(1) 513 %pi 514(%t3) --- 515 4 516(%i4) ev(%t3,numer); 517(%o4) 0.78539816 518@end example 519 520@opencatbox 521@category{Programming} 522@closecatbox 523@end deffn 524 525@c ----------------------------------------------------------------------------- 526@anchor{errcatch} 527@deffn {Function} errcatch (@var{expr_1}, @dots{}, @var{expr_n}) 528 529Evaluates @var{expr_1}, @dots{}, @var{expr_n} one by one and 530returns @code{[@var{expr_n}]} (a list) if no error occurs. If an 531error occurs in the evaluation of any argument, @code{errcatch} 532prevents the error from propagating and 533returns the empty list @code{[]} without evaluating any more arguments. 534 535@code{errcatch} 536is useful in @code{batch} files where one suspects an error might occur which 537would terminate the @code{batch} if the error weren't caught. 538 539See also @mrefdot{errormsg} 540 541@opencatbox 542@category{Programming} 543@closecatbox 544@end deffn 545 546@c ----------------------------------------------------------------------------- 547@anchor{error} 548@deffn {Function} error (@var{expr_1}, @dots{}, @var{expr_n}) 549@deffnx {System variable} error 550 551Evaluates and prints @var{expr_1}, @dots{}, @var{expr_n}, 552and then causes an error return to top level Maxima 553or to the nearest enclosing @code{errcatch}. 554 555The variable @code{error} is set to a list describing the error. 556The first element of @code{error} is a format string, which merges all the 557strings among the arguments @var{expr_1}, @dots{}, @var{expr_n}, 558and the remaining elements are the values of any non-string arguments. 559 560@code{errormsg()} formats and prints @code{error}. 561This is effectively reprinting the most recent error message. 562 563@opencatbox 564@category{Programming} 565@closecatbox 566@end deffn 567 568@c ----------------------------------------------------------------------------- 569@anchor{warning} 570@deffn {Function} warning (@var{expr_1}, @dots{}, @var{expr_n}) 571 572Evaluates and prints @var{expr_1}, @dots{}, @var{expr_n}, 573as a warning message that is formatted in a standard way so a maxima front-end 574may be able to recognize the warning and to format it accordingly. 575 576The function @code{warning} always returns false. 577 578@opencatbox 579@category{Programming} 580@closecatbox 581@end deffn 582 583@c ----------------------------------------------------------------------------- 584@anchor{error_size} 585@defvr {Option variable} error_size 586Default value: 10 587 588@code{error_size} modifies error messages according to the size of expressions 589which appear in them. If the size of an expression (as determined by the Lisp 590function @code{ERROR-SIZE}) is greater than @code{error_size}, the expression is 591replaced in the message by a symbol, and the symbol is assigned the expression. 592The symbols are taken from the list @mref{error_syms}. 593 594Otherwise, the expression is smaller than @code{error_size}, and the expression 595is displayed in the message. 596 597See also @mref{error} and @mrefdot{error_syms} 598 599Example: 600@c OUTPUT GENERATED BY THE FOLLOWING 601@c U: (C^D^E + B + A)/(cos(X-1) + 1)$ 602@c error_size: 20$ 603@c error ("Example expression is", U); 604@c errexp1; 605@c error_size: 30$ 606@c error ("Example expression is", U); 607 608The size of @code{U}, as determined by @code{ERROR-SIZE}, is 24. 609 610@example 611(%i1) U: (C^D^E + B + A)/(cos(X-1) + 1)$ 612 613(%i2) error_size: 20$ 614 615(%i3) error ("Example expression is", U); 616 617Example expression is errexp1 618 -- an error. Quitting. To debug this try debugmode(true); 619(%i4) errexp1; 620 E 621 D 622 C + B + A 623(%o4) -------------- 624 cos(X - 1) + 1 625(%i5) error_size: 30$ 626 627(%i6) error ("Example expression is", U); 628 629 E 630 D 631 C + B + A 632Example expression is -------------- 633 cos(X - 1) + 1 634 -- an error. Quitting. To debug this try debugmode(true); 635@end example 636 637@opencatbox 638@category{Debugging} 639@category{Display flags and variables} 640@closecatbox 641@end defvr 642 643@c ----------------------------------------------------------------------------- 644@anchor{error_syms} 645@defvr {Option variable} error_syms 646Default value: @code{[errexp1, errexp2, errexp3]} 647 648In error messages, expressions larger than @mref{error_size} are replaced by 649symbols, and the symbols are set to the expressions. The symbols are taken from 650the list @code{error_syms}. The first too-large expression is replaced by 651@code{error_syms[1]}, the second by @code{error_syms[2]}, and so on. 652 653If there are more too-large expressions than there are elements of 654@code{error_syms}, symbols are constructed automatically, with the @var{n}-th 655symbol equivalent to @code{concat ('errexp, @var{n})}. 656 657See also @mref{error} and @mrefdot{error_size} 658 659@opencatbox 660@category{Debugging} 661@category{Display flags and variables} 662@closecatbox 663@end defvr 664 665@c ----------------------------------------------------------------------------- 666@anchor{errormsg_fn} 667@deffn {Function} errormsg () 668 669Reprints the most recent error message. 670The variable @code{error} holds the message, 671and @mref{errormsg} formats and prints it. 672 673@opencatbox 674@category{Programming} 675@closecatbox 676@end deffn 677 678@c ----------------------------------------------------------------------------- 679@anchor{errormsg} 680@defvr {Option variable} errormsg 681Default value: @code{true} 682 683When @code{false} the output of error messages is suppressed. 684 685The option variable @code{errormsg} can not be set in a block to a local 686value. The global value of @code{errormsg} is always present. 687 688@c ===beg=== 689@c errormsg; 690@c sin(a,b); 691@c errormsg:false; 692@c sin(a,b); 693@c ===end=== 694@example 695@group 696(%i1) errormsg; 697(%o1) true 698@end group 699@group 700(%i2) sin(a,b); 701sin: wrong number of arguments. 702 -- an error. To debug this try: debugmode(true); 703@end group 704@group 705(%i3) errormsg:false; 706(%o3) false 707@end group 708@group 709(%i4) sin(a,b); 710 -- an error. To debug this try: debugmode(true); 711@end group 712@end example 713 714The option variable @code{errormsg} can not be set in a block to a local value. 715 716@c ===beg=== 717@c f(bool):=block([errormsg:bool], print ("value of errormsg is",errormsg))$ 718@c errormsg:true; 719@c f(false); 720@c errormsg:false; 721@c f(true); 722@c ===end=== 723@example 724(%i1) f(bool):=block([errormsg:bool], print ("value of errormsg is",errormsg))$ 725@group 726(%i2) errormsg:true; 727(%o2) true 728@end group 729@group 730(%i3) f(false); 731value of errormsg is true 732(%o3) true 733@end group 734@group 735(%i4) errormsg:false; 736(%o4) false 737@end group 738@group 739(%i5) f(true); 740value of errormsg is false 741(%o5) false 742@end group 743@end example 744 745@opencatbox 746@category{Programming} 747@closecatbox 748@end defvr 749 750@c ----------------------------------------------------------------------------- 751@anchor{go} 752@deffn {Function} go (@var{tag}) 753 754is used within a @mref{block} to transfer control to the statement 755of the block which is tagged with the argument to @code{go}. To tag a 756statement, precede it by an atomic argument as another statement in 757the @code{block}. For example: 758 759@example 760block ([x], x:1, loop, x+1, ..., go(loop), ...) 761@end example 762 763The argument to @code{go} must be the name of a tag appearing in the same 764@code{block}. One cannot use @code{go} to transfer to tag in a @code{block} 765other than the one containing the @code{go}. 766 767@opencatbox 768@category{Programming} 769@closecatbox 770@end deffn 771 772@c NEEDS CLARIFICATION, EXPANSION, EXAMPLES 773@c THIS ITEM IS IMPORTANT 774 775@c ----------------------------------------------------------------------------- 776@anchor{if} 777@deffn {Special operator} if 778 779Represents conditional evaluation. Various forms of @code{if} expressions are 780recognized. 781 782@code{if @var{cond_1} then @var{expr_1} else @var{expr_0}} 783eva@-lu@-ates to @var{expr_1} if @var{cond_1} evaluates to @code{true}, 784otherwise the expression evaluates to @var{expr_0}. 785 786The command @code{if @var{cond_1} then @var{expr_1} elseif @var{cond_2} then 787@var{expr_2} elseif ... else @var{expr_0}} evaluates to @var{expr_k} if 788@var{cond_k} is @code{true} and all preceding conditions are @code{false}. If 789none of the conditions are @code{true}, the expression evaluates to 790@code{expr_0}. 791 792A trailing @code{else false} is assumed if @code{else} is missing. That is, 793the command @code{if @var{cond_1} then @var{expr_1}} is equivalent to 794@code{if @var{cond_1} then @var{expr_1} else false}, and the command 795@code{if @var{cond_1} then @var{expr_1} elseif ... elseif @var{cond_n} then 796@var{expr_n}} is equivalent to @code{if @var{cond_1} then @var{expr_1} elseif 797... elseif @var{cond_n} then @var{expr_n} else false}. 798 799The alternatives @var{expr_0}, @dots{}, @var{expr_n} may be any Maxima 800expressions, including nested @code{if} expressions. The alternatives are 801neither simplified nor evaluated unless the corresponding condition is 802@code{true}. 803 804The conditions @var{cond_1}, @dots{}, @var{cond_n} are expressions which 805potentially or actually evaluate to @code{true} or @code{false}. 806When a condition does not actually evaluate to @code{true} or @code{false}, 807the behavior of @code{if} is governed by the global flag @code{prederror}. 808When @code{prederror} is @code{true}, it is an error if any evaluated condition 809does not evaluate to @code{true} or @code{false}. Otherwise, conditions which 810do not evaluate to @code{true} or @code{false} are accepted, and the result is 811a conditional expression. 812 813Among other elements, conditions may comprise relational and logical operators 814as follows. 815 816@c - SEEMS LIKE THIS TABLE WANTS TO BE IN A DISCUSSION OF PREDICATE FUNCTIONS; PRESENT LOCATION IS OK I GUESS 817@c - REFORMAT THIS TABLE USING TEXINFO MARKUP (MAYBE) 818@example 819Operation Symbol Type 820 821less than < relational infix 822less than <= 823 or equal to relational infix 824equality (syntactic) = relational infix 825negation of = # relational infix 826equality (value) equal relational function 827negation of equal notequal relational function 828greater than >= 829 or equal to relational infix 830greater than > relational infix 831and and logical infix 832or or logical infix 833not not logical prefix 834@end example 835 836@opencatbox 837@category{Programming} 838@category{Predicate functions} 839@closecatbox 840@end deffn 841 842@c NEEDS CLARIFICATION 843@c THIS ITEM IS IMPORTANT 844 845@c ----------------------------------------------------------------------------- 846@anchor{map} 847@deffn {Function} map (@var{f}, @var{expr_1}, @dots{}, @var{expr_n}) 848 849Returns an expression whose leading operator is the same as that of the 850expressions @var{expr_1}, @dots{}, @var{expr_n} but whose subparts are the 851results of applying @var{f} to the corresponding subparts of the expressions. 852@var{f} is either the name of a function of @math{n} arguments or is a 853@code{lambda} form of @math{n} arguments. 854 855@mref{maperror} - if @code{false} will cause all of the mapping 856functions to (1) stop when they finish going down the shortest 857@var{expr_i} if not all of the @var{expr_i} are of the same length and 858(2) apply @var{f} to [@var{expr_1}, @var{expr_2}, @dots{}] if the 859@var{expr_i} are not all the same type of object. If @code{maperror} 860is @code{true} then an error message will be given in the above two 861instances. 862 863One of the uses of this function is to @code{map} a function (e.g. 864@mref{partfrac}) onto each term of a very large expression where it ordinarily 865wouldn't be possible to use the function on the entire expression due to an 866exhaustion of list storage space in the course of the computation. 867 868See also @mrefcomma{scanmap} @mrefcomma{maplist} @mrefcomma{outermap} @mref{matrixmap} and @mrefdot{apply} 869 870@c IN THESE EXAMPLES, SPELL OUT WHAT IS THE MAIN OPERATOR 871@c AND SHOW HOW THE RESULT FOLLOWS FROM THE DESCRIPTION STATED IN THE FIRST PARAGRAPH 872 873@c ===beg=== 874@c map(f,x+a*y+b*z); 875@c map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 876@c map(ratsimp, x/(x^2+x)+(y^2+y)/y); 877@c map("=",[a,b],[-0.5,3]); 878@c ===end=== 879@example 880(%i1) map(f,x+a*y+b*z); 881(%o1) f(b z) + f(a y) + f(x) 882(%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 883 1 1 1 884(%o2) ----- - ----- + -------- + x 885 x + 2 x + 1 2 886 (x + 1) 887(%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y); 888 1 889(%o3) y + ----- + 1 890 x + 1 891(%i4) map("=",[a,b],[-0.5,3]); 892(%o4) [a = - 0.5, b = 3] 893 894 895@end example 896 897@opencatbox 898@category{Function application} 899@closecatbox 900@end deffn 901 902@c ----------------------------------------------------------------------------- 903@anchor{mapatom} 904@deffn {Function} mapatom (@var{expr}) 905 906Returns @code{true} if and only if @var{expr} is treated by the mapping 907routines as an atom. "Mapatoms" are atoms, numbers 908(including rational numbers), and subscripted variables. 909@c WHAT ARE "THE MAPPING ROUTINES", AND WHY DO THEY HAVE A SPECIALIZED NOTION OF ATOMS ?? 910 911@opencatbox 912@category{Predicate functions} 913@closecatbox 914@end deffn 915 916@c NEEDS CLARIFICATION 917 918@c ----------------------------------------------------------------------------- 919@anchor{maperror} 920@defvr {Option variable} maperror 921Default value: @code{true} 922 923When @code{maperror} is @code{false}, causes all of the mapping functions, 924for example 925 926@example 927map (@var{f}, @var{expr_1}, @var{expr_2}, ...) 928@end example 929 930to (1) stop when they finish going down the shortest @var{expr_i} if 931not all of the @var{expr_i} are of the same length and (2) apply 932@var{f} to [@var{expr_1}, @var{expr_2}, @dots{}] if the @var{expr_i} are 933not all the same type of object. 934 935If @code{maperror} is @code{true} then an error message 936is displayed in the above two instances. 937 938@opencatbox 939@category{Function application} 940@closecatbox 941@end defvr 942 943@c ----------------------------------------------------------------------------- 944@anchor{mapprint} 945@defvr {Option variable} mapprint 946Default value: @code{true} 947 948When @code{mapprint} is @code{true}, various information messages from 949@mref{map}, @mref{maplist}, and @mref{fullmap} are produced in certain 950situations. These include situations where @code{map} would use 951@mref{apply}, or @code{map} is truncating on the shortest list. 952 953If @mref{mapprint} is @code{false}, these messages are suppressed. 954 955@opencatbox 956@category{Function application} 957@closecatbox 958@end defvr 959 960@c NEEDS CLARIFICATION 961 962@c ----------------------------------------------------------------------------- 963@anchor{maplist} 964@deffn {Function} maplist (@var{f}, @var{expr_1}, @dots{}, @var{expr_n}) 965 966Returns a list of the applications of @var{f} to the parts of the expressions 967@var{expr_1}, @dots{}, @var{expr_n}. @var{f} is the name of a function, or a 968lambda expression. 969 970@code{maplist} differs from @code{map(@var{f}, @var{expr_1}, ..., @var{expr_n})} 971which returns an expression with the same main operator as @var{expr_i} has 972(except for simplifications and the case where @mref{map} does an @mref{apply}). 973 974@opencatbox 975@category{Function application} 976@closecatbox 977@end deffn 978 979@c NEEDS CLARIFICATION 980 981@c ----------------------------------------------------------------------------- 982@anchor{prederror} 983@defvr {Option variable} prederror 984Default value: @code{false} 985 986When @code{prederror} is @code{true}, an error message is displayed whenever the 987predicate of an @code{if} statement or an @mref{is} function fails to evaluate 988to either @code{true} or @code{false}. 989 990If @code{false}, @code{unknown} is returned 991instead in this case. The @code{prederror: false} mode is not supported in 992translated code; 993however, @code{maybe} is supported in translated code. 994 995See also @mref{is} and @mrefdot{maybe} 996 997@opencatbox 998@category{Programming} 999@category{Predicate functions} 1000@closecatbox 1001 1002@end defvr 1003 1004@anchor{return} 1005@deffn {Function} return (@var{value}) 1006May be used to exit explicitly from the current @mrefcomma{block} @mrefcomma{while} 1007@mref{for} or @mref{do} loop bringing its argument. It therefore can be compared 1008with the @code{return} statement found in other programming languages but it yields 1009one difference: In maxima only returns from the current block, not from the entire 1010function it was called in. In this aspect it more closely resembles the @code{break} 1011statement from C. 1012 1013@c ===beg=== 1014@c for i:1 thru 10 do o:i; 1015@c for i:1 thru 10 do if i=3 then return(i); 1016@c for i:1 thru 10 do 1017@c ( 1018@c block([i], 1019@c i:3, 1020@c return(i) 1021@c ), 1022@c return(8) 1023@c ); 1024@c block([i], 1025@c i:4, 1026@c block([o], 1027@c o:5, 1028@c return(o) 1029@c ), 1030@c return(i), 1031@c return(10) 1032@c ); 1033@c ===end=== 1034@example 1035@group 1036(%i1) for i:1 thru 10 do o:i; 1037(%o1) done 1038@end group 1039@group 1040(%i2) for i:1 thru 10 do if i=3 then return(i); 1041(%o2) 3 1042@end group 1043@group 1044(%i3) for i:1 thru 10 do 1045 ( 1046 block([i], 1047 i:3, 1048 return(i) 1049 ), 1050 return(8) 1051 ); 1052(%o3) 8 1053@end group 1054(%i4) block([i], 1055 i:4, 1056 block([o], 1057 o:5, 1058 return(o) 1059 ), 1060 return(i), 1061 return(10) 1062 ); 1063(%o4) 4 1064@end example 1065 1066 1067See also @mrefcomma{for} @mrefcomma{while} @mref{do} and @mref{block}. 1068 1069@opencatbox 1070@category{Programming} 1071@closecatbox 1072@end deffn 1073 1074@c NEEDS CLARIFICATION 1075@anchor{scanmap} 1076@deffn {Function} scanmap @ 1077@fname{scanmap} (@var{f}, @var{expr}) @ 1078@fname{scanmap} (@var{f}, @var{expr}, bottomup) 1079 1080Recursively applies @var{f} to @var{expr}, in a top 1081down manner. This is most useful when complete factorization is 1082desired, for example: 1083 1084@example 1085(%i1) exp:(a^2+2*a+1)*y + x^2$ 1086(%i2) scanmap(factor,exp); 1087 2 2 1088(%o2) (a + 1) y + x 1089@end example 1090 1091Note the way in which @code{scanmap} applies the given function 1092@code{factor} to the constituent subexpressions of @var{expr}; if 1093another form of @var{expr} is presented to @code{scanmap} then the 1094result may be different. Thus, @code{%o2} is not recovered when 1095@code{scanmap} is applied to the expanded form of @code{exp}: 1096 1097@example 1098(%i3) scanmap(factor,expand(exp)); 1099 2 2 1100(%o3) a y + 2 a y + y + x 1101@end example 1102 1103Here is another example of the way in which @code{scanmap} recursively 1104applies a given function to all subexpressions, including exponents: 1105 1106@example 1107(%i4) expr : u*v^(a*x+b) + c$ 1108(%i5) scanmap('f, expr); 1109 f(f(f(a) f(x)) + f(b)) 1110(%o5) f(f(f(u) f(f(v) )) + f(c)) 1111@end example 1112 1113@code{scanmap (@var{f}, @var{expr}, bottomup)} applies @var{f} to @var{expr} in a 1114bottom-up manner. E.g., for undefined @code{f}, 1115 1116@example 1117scanmap(f,a*x+b) -> 1118 f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b)) 1119scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b) 1120 -> f(f(a)*f(x))+f(b) -> 1121 f(f(f(a)*f(x))+f(b)) 1122@end example 1123 1124In this case, you get the same answer both 1125ways. 1126 1127@opencatbox 1128@category{Function application} 1129@closecatbox 1130@end deffn 1131 1132@c ----------------------------------------------------------------------------- 1133@anchor{throw} 1134@deffn {Function} throw (@var{expr}) 1135 1136Evaluates @var{expr} and throws the value back to the most recent 1137@mref{catch}. @code{throw} is used with @code{catch} as a nonlocal return 1138mechanism. 1139 1140@opencatbox 1141@category{Programming} 1142@closecatbox 1143@end deffn 1144 1145@c ----------------------------------------------------------------------------- 1146@anchor{outermap} 1147@deffn {Function} outermap (@var{f}, @var{a_1}, @dots{}, @var{a_n}) 1148 1149Applies the function @var{f} to each one of the elements of the outer product 1150@var{a_1} cross @var{a_2} @dots{} cross @var{a_n}. 1151 1152@var{f} is the name of a function of @math{n} arguments or a lambda expression 1153of @math{n} arguments. Each argument @var{a_k} may be a list or nested list, 1154or a matrix, or any other kind of expression. 1155 1156The @code{outermap} return value is a nested structure. Let @var{x} be the 1157return value. Then @var{x} has the same structure as the first list, nested 1158list, or matrix argument, @code{@var{x}[i_1]...[i_m]} has the same structure as 1159the second list, nested list, or matrix argument, 1160@code{@var{x}[i_1]...[i_m][j_1]...[j_n]} has the same structure as the third 1161list, nested list, or matrix argument, and so on, where @var{m}, @var{n}, 1162@dots{} are the numbers of indices required to access the elements of each 1163argument (one for a list, two for a matrix, one or more for a nested list). 1164Arguments which are not lists or matrices have no effect on the structure of 1165the return value. 1166 1167Note that the effect of @code{outermap} is different from that of applying 1168@var{f} to each one of the elements of the outer product returned by 1169@mref{cartesian_product}. @code{outermap} preserves the structure of the 1170arguments in the return value, while @code{cartesian_product} does not. 1171 1172@code{outermap} evaluates its arguments. 1173 1174See also @mrefcomma{map} @mrefcomma{maplist} and @mrefdot{apply} 1175@c CROSS REF OTHER FUNCTIONS HERE ?? 1176 1177Examples: 1178 1179Elementary examples of @code{outermap}. 1180To show the argument combinations more clearly, @code{F} is left undefined. 1181 1182@c ===beg=== 1183@c outermap (F, [a, b, c], [1, 2, 3]); 1184@c outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4])); 1185@c outermap (F, [a, b], x, matrix ([1, 2], [3, 4])); 1186@c outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y])); 1187@c outermap ("+", [a, b, c], [1, 2, 3]); 1188@c ===end=== 1189@example 1190@group 1191(%i1) outermap (F, [a, b, c], [1, 2, 3]); 1192(%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], 1193 [F(c, 1), F(c, 2), F(c, 3)]] 1194@end group 1195@group 1196(%i2) outermap (F, matrix ([a, b], [c, d]), matrix ([1, 2], [3, 4])); 1197 [ [ F(a, 1) F(a, 2) ] [ F(b, 1) F(b, 2) ] ] 1198 [ [ ] [ ] ] 1199 [ [ F(a, 3) F(a, 4) ] [ F(b, 3) F(b, 4) ] ] 1200(%o2) [ ] 1201 [ [ F(c, 1) F(c, 2) ] [ F(d, 1) F(d, 2) ] ] 1202 [ [ ] [ ] ] 1203 [ [ F(c, 3) F(c, 4) ] [ F(d, 3) F(d, 4) ] ] 1204@end group 1205@group 1206(%i3) outermap (F, [a, b], x, matrix ([1, 2], [3, 4])); 1207 [ F(a, x, 1) F(a, x, 2) ] [ F(b, x, 1) F(b, x, 2) ] 1208(%o3) [[ ], [ ]] 1209 [ F(a, x, 3) F(a, x, 4) ] [ F(b, x, 3) F(b, x, 4) ] 1210@end group 1211@group 1212(%i4) outermap (F, [a, b], matrix ([1, 2]), matrix ([x], [y])); 1213 [ [ F(a, 1, x) ] [ F(a, 2, x) ] ] 1214(%o4) [[ [ ] [ ] ], 1215 [ [ F(a, 1, y) ] [ F(a, 2, y) ] ] 1216 [ [ F(b, 1, x) ] [ F(b, 2, x) ] ] 1217 [ [ ] [ ] ]] 1218 [ [ F(b, 1, y) ] [ F(b, 2, y) ] ] 1219@end group 1220@group 1221(%i5) outermap ("+", [a, b, c], [1, 2, 3]); 1222(%o5) [[a + 1, a + 2, a + 3], [b + 1, b + 2, b + 3], 1223 [c + 1, c + 2, c + 3]] 1224@end group 1225@end example 1226 1227A closer examination of the @code{outermap} return value. The first, second, 1228and third arguments are a matrix, a list, and a matrix, respectively. 1229The return value is a matrix. 1230Each element of that matrix is a list, 1231and each element of each list is a matrix. 1232 1233@c ===beg=== 1234@c arg_1 : matrix ([a, b], [c, d]); 1235@c arg_2 : [11, 22]; 1236@c arg_3 : matrix ([xx, yy]); 1237@c xx_0 : outermap (lambda ([x, y, z], x / y + z), arg_1, 1238@c arg_2, arg_3); 1239@c xx_1 : xx_0 [1][1]; 1240@c xx_2 : xx_0 [1][1] [1]; 1241@c xx_3 : xx_0 [1][1] [1] [1][1]; 1242@c [op (arg_1), op (arg_2), op (arg_3)]; 1243@c [op (xx_0), op (xx_1), op (xx_2)]; 1244@c ===end=== 1245@example 1246@group 1247(%i1) arg_1 : matrix ([a, b], [c, d]); 1248 [ a b ] 1249(%o1) [ ] 1250 [ c d ] 1251@end group 1252@group 1253(%i2) arg_2 : [11, 22]; 1254(%o2) [11, 22] 1255@end group 1256@group 1257(%i3) arg_3 : matrix ([xx, yy]); 1258(%o3) [ xx yy ] 1259@end group 1260(%i4) xx_0 : outermap (lambda ([x, y, z], x / y + z), arg_1, 1261 arg_2, arg_3); 1262 [ [ a a ] [ a a ] ] 1263 [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] 1264 [ [ 11 11 ] [ 22 22 ] ] 1265(%o4) Col 1 = [ ] 1266 [ [ c c ] [ c c ] ] 1267 [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] 1268 [ [ 11 11 ] [ 22 22 ] ] 1269 [ [ b b ] [ b b ] ] 1270 [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] 1271 [ [ 11 11 ] [ 22 22 ] ] 1272 Col 2 = [ ] 1273 [ [ d d ] [ d d ] ] 1274 [ [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] ] 1275 [ [ 11 11 ] [ 22 22 ] ] 1276@group 1277(%i5) xx_1 : xx_0 [1][1]; 1278 [ a a ] [ a a ] 1279(%o5) [[ xx + -- yy + -- ], [ xx + -- yy + -- ]] 1280 [ 11 11 ] [ 22 22 ] 1281@end group 1282@group 1283(%i6) xx_2 : xx_0 [1][1] [1]; 1284 [ a a ] 1285(%o6) [ xx + -- yy + -- ] 1286 [ 11 11 ] 1287@end group 1288@group 1289(%i7) xx_3 : xx_0 [1][1] [1] [1][1]; 1290 a 1291(%o7) xx + -- 1292 11 1293@end group 1294@group 1295(%i8) [op (arg_1), op (arg_2), op (arg_3)]; 1296(%o8) [matrix, [, matrix] 1297@end group 1298@group 1299(%i9) [op (xx_0), op (xx_1), op (xx_2)]; 1300(%o9) [matrix, [, matrix] 1301@end group 1302@end example 1303 1304@code{outermap} preserves the structure of the arguments in the return value, 1305while @code{cartesian_product} does not. 1306 1307@c ===beg=== 1308@c outermap (F, [a, b, c], [1, 2, 3]); 1309@c setify (flatten (%)); 1310@c map (lambda ([L], apply (F, L)), 1311@c cartesian_product ({a, b, c}, {1, 2, 3})); 1312@c is (equal (%, %th (2))); 1313@c ===end=== 1314@example 1315@group 1316(%i1) outermap (F, [a, b, c], [1, 2, 3]); 1317(%o1) [[F(a, 1), F(a, 2), F(a, 3)], [F(b, 1), F(b, 2), F(b, 3)], 1318 [F(c, 1), F(c, 2), F(c, 3)]] 1319@end group 1320@group 1321(%i2) setify (flatten (%)); 1322(%o2) @{F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), 1323 F(c, 1), F(c, 2), F(c, 3)@} 1324@end group 1325@group 1326(%i3) map (lambda ([L], apply (F, L)), 1327 cartesian_product (@{a, b, c@}, @{1, 2, 3@})); 1328(%o3) @{F(a, 1), F(a, 2), F(a, 3), F(b, 1), F(b, 2), F(b, 3), 1329 F(c, 1), F(c, 2), F(c, 3)@} 1330@end group 1331@group 1332(%i4) is (equal (%, %th (2))); 1333(%o4) true 1334@end group 1335@end example 1336 1337@opencatbox 1338@category{Function application} 1339@closecatbox 1340@end deffn 1341 1342