在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的情况下,这种类型的算子对使用线性微分算子有很大帮助。
答案 0 :(得分:1)
最大值lambda
不会计算其主体内的任何表达式,因此不会对f
进行g
的求值。这就是您所看到的行为。我看到的动机是lambda
主体可能包含表达式,直到某些变量具有值(例如, length
,for ...
,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
不会对length
,for ...
和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
会评估其参数。