> How do you, for instance, recurse down a list in maxima? ...
> Now, for a moment setting aside a nice recursive definition,
There are four pretty much orthogonal issues here.
1) Recursing down a list;
2) remembering the names of your variables;
3) evaluating predicates;
4) other
>>>>>>>>>>> Recursing down a list <<<<<<<<<<<<<
Recursion is straightforward, just like Lisp (including Scheme) or C or
whatever, though a bit different from Haskell or Prolog.
For your example:
filter(f,l):=
if l=[]
then []
elseif f(first(l))
then cons(first(l),filter(f,rest(l)))
else filter(f,rest(l));
filter(evenp,[1,3,4,6,7,9,10]) => [4, 6, 10]
>>>>>>>>>>> Remembering the names of your variables <<<<<<<<<
Your version is:
filter(cond,list):=
block([result],
result:[],
for l in list do (if p(l) then result:cons(l,result)),
return(result))$
You seem to have forgotten that your filter funtion is called "cond",
not "p". I'm afraid Maxima is not clever enough to Do What You Mean
here (Google: DWIM). :-)
>>>>>>>>>> Evaluating predicates <<<<<<<<<<<<
> a new layer of trouble: I try to define a conditional:
> f(x):=x>0
...
> MACSYMA was unable to evaluate the predicate:
Here there is a real issue. Remember that Maxima is a symbolic system,
so it must have some way of representing equalities such as x^2=4 and
inequalities such as x^2<1. It would not do for x^2=4 to be evaluated
immediately as either True or False. In fact, usually it *cannot* be
evaluated as True or False. Similarly for inequalities.
Moreover, it is perfectly legitimate to write a Maxima function that
constructs equalities (equations) or inequalities, e.g.
QuadraticRootsAreReal(expr,var) :=
coeff(expr,var,1)^2 - 4 * coeff(expr,var,2) * coeff(expr,var,0)
>= 0;
The return value of this function is not True or False, but rather an
equation. For example,
QuadraticRootsAreReal(x^2-a,x) => 4*a >= 0;
Maxima could then in principle (the module has not been written...)
solve/simplify this inequality to a >= 0.
To force an equality or inequality to evaluate to True or False, you
must use the Is function:
Is(QuadraticRootsAreReal(x^2-a,x))
In this case, unless you've asserted things about the value of a, it
will give an error, since it doesn't know. (Isn't there some way to
force IS to ask questions, like ASKSIGN?)
>>>>>>>>>>>>>> other <<<<<<<<<<<<<<<<
> don't understand the evaluation model and need to rtfm
I'm not sure the FM answers these questions -- we may have to WTFM.
> Hopefully I haven't made myself an idiot in front of all the maxima
gurus!
Not at all.
> Ultimately, what I'd like to get working as a first use of
> maxima is a little routine that computes the eigenvector corresponding
> to the maximal real eigenvalue of a matrix. Phew, it seems pretty
> distant at this point!
Have you looked at the built-in eigenvector/eigenvalue functions?
Note that if your matrices are symbolic, eigenV's blow up very quickly.
> Also, I tried browsing some of the maxima source code for some clues.
> Does one generally do programming directly within lisp rather than in
> maxima?
Depends upon one. Usually for strictly mathematical problems where most
of the heavy lifting is being done by built-in routines (including
simplification), or where there are many math expressions, the Maxima
language is best. When efficiency is important, Lisp is better.
Algorithms with fancy data structures should almost always be
implemented in Lisp. Recursions over expression trees can be done in
Maxima (especially if they are small), with the pattern matching
language, or in Lisp. A lot of it is a matter of taste and comfort.
The Maxima language is not a terribly modern or complete programming
language, and I am not terribly fond of it, but for most people it is
easier to learn than Lisp. YMMV.
-s
PS Though the Maxima language doesn't have pattern-matching or
destructor-based function definition, it does have something vaguely
related:
fact[0]:=0;
fact[n]:=n*fact[n-1];
Note the square brackets instead of parentheses.