Maxima中的“未应用”或“ Mathematica”功能的枫树的类似物

时间:2018-10-06 15:18:39

标签: maxima

在Wolfram Mathematica中,我们可以定义作用于函数(即返回函数的函数)的运算符,例如在下面的示例中,关于第一个自变量作用于两个自变量的函数的乘法运算符

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

然后我们可以将此运算符应用于任何带有两个参数的函数

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

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

枫树有类似的构造

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

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

end;

具有类似的应用模式

> X(g)(z,t);

  z g(z, t)

在千里马我尝试了这个

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

但是当尝试应用它时,我会得到

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

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

因此,当我使用lambda时,好像f无法识别为函数X的参数。

有什么办法可以解决这个问题?

在Maple和Mathematica的情况下,这种类型的算子对使用线性微分算子有很大帮助。

1 个答案:

答案 0 :(得分:1)

最大值lambda不会计算其主体内的任何表达式,因此不会对f进行g的求值。这就是您所看到的行为。我看到的动机是lambda主体可能包含表达式,直到某些变量具有值(例如, lengthfor ...print

您可以通过代替体内来获得预期的行为。这有两种方法。第一个使用了subst函数,我认为它可能是最明显的。

(%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)

第二个方法使用函数buildq,该函数实际上是一个替换函数,该函数引用(不求值)被替换的表达式。

(%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)

最后,如果您有兴趣更频繁地使用评估表达式来创建lambda表达式,则可以为此创建自己的lambda。我在这里叫evlambda

(%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)

这里的关键是evlambda被定义为一个普通函数,因此要对其参数进行求值。因此,在应用lambda时,已经对b进行了评估,使其包含g

请注意,此evlambda不会对lengthfor ...print有用,这是可以预期的。

(%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     

最后一个带有print的对象在定义print时计算baz(因此,输出为x),但是在baz(5)时不返回已被评估-这种行为是可以预期的,因为evlambda会评估其参数。