问题
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
回答1:
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.
来源:https://stackoverflow.com/questions/52680489/analog-of-maple-unapply-or-mathematica-function-in-maxima