Не совсем ответ на первоначальный вопрос, но я заметил, что многие люди заинтересовались #0
вещами, поэтому здесь Я привел пару нетривиальных примеров, надеюсь, они будут полезны.
Что касается утверждения о том, что для вложенных функций следует использовать функции с именованными аргументами: хотя в общем случае это так, следует всегда помнить, что лексическая область видимости для чистых функций (и вообще) эмулируется в Mathematica и может быть нарушена. Пример:
In[71]:=
Clear[f,g];
f[fun_,val_]:=val/.x_:>fun[x];
g[fn_,val_]:=f[Function[{x},fn[#1^#2==x&,{x,x}]],val];
g[Array,3]
During evaluation of In[71]:= Function::flpar: Parameter specification {3} in
Function[{3},Array[#1^#2==3&,{3,3}]] should be a symbol or a list of symbols. >>
During evaluation of In[71]:= Function::flpar: Parameter specification {3} in
Function[{3},Array[#1^#2==3&,{3,3}]] should be a symbol or a list of symbols. >>
Out[74]= Function[{3},Array[#1^#2==3&,{3,3}]][3]
Это поведение связано с навязчивой природой подстановок правил, то есть с тем фактом, что Rule
и RuleDelayed
не заботятся о возможных конфликтах имен между именами в ограничивающих конструкциях, которые могут присутствовать в выражениях субъекта. правила приложений и имена переменных шаблона в правилах. Хуже всего то, что g
и f
работают совершенно нормально, если брать их отдельно. Это когда они смешиваются вместе, это запутывание происходит, и только потому, что нам не повезло использовать ту же переменную шаблона x
в теле f
, что и в чистой функции. Это делает такие ошибки очень трудными для обнаружения, хотя такие ситуации иногда случаются на практике, поэтому я рекомендую не передавать чистые функции с именованными аргументами в качестве параметров в функции более высокого порядка, определенные с помощью шаблонов.
Edit:
Расширение немного по эмуляции лексической области видимости. Я имею в виду, что, например, когда я создаю чистую функцию (которая представляет собой лексическую ограничивающую конструкцию, которая связывает имена переменных в своем теле со значениями передаваемых параметров), я ожидаю, что не смогу изменить эту привязку после того, как я создал функцию. Это означает, что независимо от того, где я использую Function[x,body-that-depends-on-x]
, я должен иметь возможность рассматривать его как черный ящик с входными параметрами и полученными результатами. Но в Mathematica Function[x,x^2]
(например) также является выражением и, как таковое, может быть изменено, как любое другое выражение. Например:
In[75]:=
x = 5;
Function[Evaluate[x],x^2]
During evaluation of In[75]:= Function::flpar: Parameter specification 5 in Function[5,x^2] should
be a symbol or a list of symbols. >>
Out[76]= Function[5,x^2]
или, еще проще (суть моего предыдущего предупреждения):
In[79]:= 1/.x_:>Function[x,x^2]
During evaluation of In[79]:= Function::flpar: Parameter specification 1 in Function[1,1^2] should
be a symbol or a list of symbols. >>
Out[79]= Function[1,1^2]
Это последнее поведение меня укусило несколько раз довольно болезненно. Это поведение было также замечено @WReach в нижней части его поста на этой странице - очевидно, у него были похожие переживания. Существуют и другие способы выхода за рамки, основанные на точном знании того, как Mathematica переименовывает переменные во время конфликтов, но на практике они сравнительно менее вредны. Вообще, я не думаю, что такого рода вещи можно избежать, если кто-то настаивает на уровне прозрачности, представленной выражениями Mathematica. Кажется, что он просто «чрезмерно прозрачен» для чистых функций (и вообще для лексических конструкций объема), но с другой стороны, это также имеет свои применения, например, мы можем создать чистую функцию во время выполнения, например:
In[82]:= Block[{x},Function@@{x,Integrate[HermiteH[10,y],{y,0,x}]}]
Out[82]= Function[x,-30240 x+100800 x^3-80640 x^5+23040 x^7-2560 x^9+(1024 x^11)/11]
Там, где интеграл вычисляется только один раз, во время определения (также может использоваться Evaluate
). Итак, это выглядит как компромисс. Таким образом, функциональная абстракция лучше интегрируется в Mathematica, но имеет утечку, как отмечает @WReach. В качестве альтернативы, он мог бы быть «водонепроницаемым», но, возможно, за меньшую цену. Это было явно дизайнерское решение.