3

In Wolfram Mathematica we can define an operator acting on a function (i.e. function that returns function) e.g. as for the operator of multiplication by the first argument acting on a functions of two arguments in the example below

X[f_] = Function[{x, y}, x*f[x, y]]

Then we can apply this operators to any function with any 2 arguments

In[2]:= X[g][z, t]

Out[2]= z g[z, t]

There is a similar construction in Maple

X:=proc(f) option operator; local x,y;

unapply(x*f(x,y),x,y)

end;

with the similar mode of application

> X(g)(z,t);

  z g(z, t)

In Maxima I tried this

X(f):=lambda([x,y],x*f(x,y));

but when trying to apply it I get

(%i5) X(g)(z,t)

(%o5) z*f(z,t)

so, it looks like f is not recognized as an argument of function X when I used lambda.

Is there any way to solve this problem?

In case of Maple and Mathematica this type of operators helps a lot to manipulate with linear differential operators

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

1 Answers1

3

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.

Robert Dodier
  • 16,905
  • 2
  • 31
  • 48
  • Ok this works! But I have another problem: How to define composition of such operators? In Mathematica we use @* and in Maple we use @. For instance to get commutator of operator of multiplication by x and differentiation by x, in Maple we write X@dX-dX@X. How can we do this in Maxima? – Truffaldino Oct 11 '18 at 14:26
  • @Truffaldino your "another problem" can be asked as a new question. If this solution works as you say, the best thing to do is to click "accept" so that future readers will see that the problem has been solved. The user also gets a small reputation bump and you get +2 as well. Everybody wins! :-) – uhoh Dec 09 '19 at 02:33
  • @Truffaldino I agree that it's best to ask that as a separate new question. – Robert Dodier Dec 09 '19 at 17:57