Maxima lambda
doesn't evaluate any of the expressions inside the body of it, so f
is not evaluated (to g
). That's the behavior you are seeing. The motivation for it that I can see is that the lambda
body might contain expressions which don't have the expected effect until some variables have values, e.g. length
, for ...
, print
, etc.
You can get the expected behavior by substituting into the body. Here are two ways to do that. The first uses the function subst
which I think is maybe the most obvious.
(%i1) X(f):= subst ('f = f, lambda([x,y],x*f(x,y)));
(%o1) X(f) := subst('f = f, lambda([x, y], x f(x, y)))
(%i2) X(g);
(%o2) lambda([x, y], x g(x, y))
(%i3) X(g)(z, t);
(%o3) z g(z, t)
The second uses the function buildq
which is effectively a substitution function which quotes (does not evaluate) the expression into which something is substituted.
(%i4) X(f) := buildq ([f], lambda ([x, y], x*f(x, y)));
(%o4) X(f) := buildq([f], lambda([x, y], x f(x, y)))
(%i5) X(g);
(%o5) lambda([x, y], x g(x, y))
(%i6) X(g)(z, t);
(%o6) z g(z, t)
Finally, if you are interested in creating lambda
expressions using evaluated expressions more often, you could create your own kind of lambda for that. I'll call it evlambda
here.
(%i11) evlambda (a, b) := apply (lambda, [a, b]);
(%o11) evlambda(a, b) := apply(lambda, [a, b])
(%i12) X(f) := evlambda ([x, y], x*f(x, y));
(%o12) X(f) := evlambda([x, y], x f(x, y))
(%i13) X(g);
(%o13) lambda([x, y], x g(x, y))
(%i14) X(g)(z, t);
(%o14) z g(z, t)
The key here is that evlambda
is defined as an ordinary function, so its arguments are evaluated. So by the time lambda
is applied, b
has been evaluated so it contains g
.
Note that this evlambda
won't do anything useful with length
, for ...
, and print
, which is to be expected.
(%i15) foo : evlambda ([l], 1 + length(l));
length: argument cannot be a symbol; found l
-- an error. To debug this try: debugmode(true);
(%i16) bar : evlambda ([n], for i thru n do print (i));
Unable to evaluate predicate 1 > n
-- an error. To debug this try: debugmode(true);
(%i17) baz : evlambda ([x], print (x));
x
(%o17) lambda([x], x)
(%i18) baz(5);
(%o18) 5
The last one, with print
, evaluates print
when baz
is defined (so x
is the output), but then not again when baz(5)
is evaluated -- this behavior is to be expected since evlambda
evaluates its arguments.