Использование вложенных слотов (#) - PullRequest
12 голосов
/ 07 февраля 2011

Предположим, я хочу построить что-то вроде

Array[#1^#2 == 3 &, {3, 3}] 

И теперь я хочу заменить "3" на переменную.Я могу сделать, например:

f[x_] := Array[#1^#2 == x &, {x, x}]  

Вопрос: есть ли способ использовать только слотов и & в качестве функциональной записи?

Ответы [ 5 ]

9 голосов
/ 07 февраля 2011

Не совсем ответ на первоначальный вопрос, но я заметил, что многие люди заинтересовались #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. В качестве альтернативы, он мог бы быть «водонепроницаемым», но, возможно, за меньшую цену. Это было явно дизайнерское решение.

4 голосов
/ 07 февраля 2011

Как насчет

Map[Last, #] & /@ Array[#1^#2 == #3 &, {#, #, #}] &[3]

Ужасно уродливое извлечение элементов и, что очень интересно, Map[Last, #]& дает мне результат, отличный от Last /@.Это связано с тем, что Map имеет атрибуты, отличные от &?

3 голосов
/ 22 июня 2013

Как насчет With[{x = #1}, Array[#1^#2 == x &, {x, x}]] &?

3 голосов
/ 07 февраля 2011

Полагаю, вы знаете, что в документации говорится о вложенных чистых функциях .

Использование явных имен для настройки вложенных чистых функций (например):

Function[u, Function[v, f[u, v]]][x]

В любом случае, вот лучшее, что я мог бы придумать, не следуя приведенному выше совету:

f[x_] := Array[#1^#2 == x &, {x, x}]
g = Array[With[{x = #}, #1^#2 == x &], {#, #}] &

g функционально идентичен вашему исходному f, но на самом деле не лучше, чем рекомендуется

h = Function[x, Array[#1^#2 == x &, {x, x}]]
2 голосов
/ 16 февраля 2011

Возможно

Array[#1^#2 &, {#, #}] /. i_Integer :> i == # &[3]

Или

Thread /@ Thread[# == Array[#1^#2 &, {#, #}]] &[3]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...