Аналог Maple "unapply" или Mathematica "Function" в максимах - PullRequest
0 голосов
/ 06 октября 2018

В Wolfram Mathematica мы можем определить оператор, действующий на функцию (т.е. функцию, которая возвращает функцию), например, как для оператора умножения на первый аргумент, действующий на функции двух аргументов в примере ниже

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

Тогда мы можем применить эти операторы к любой функции с любыми 2 аргументами

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

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

В Maple есть похожая конструкция

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

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

end;

с аналогичным режимом применения

> X(g)(z,t);

  z g(z, t)

В Maxima я пробовал это

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

, но при попытке применить его я получаю

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

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

, поэтому, похоже, что f не распознается как аргументфункция X, когда я использовал лямбду.

Есть ли способ решить эту проблему?

В случае Maple и Mathematica этот тип операторов очень помогает манипулировать с линейными дифференциальными операторами

1 Ответ

0 голосов
/ 06 октября 2018

Maxima 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 выражений с использованием вычисляемых выражений чаще, вы можете создать свой собственный тип лямбда-выражений для этого.Я назову это 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 оценивает его аргументы.

...