Использование вложенных слотов (#)
Предположим, что я хочу построить что-то вроде
Array[#1^#2 == 3 &, {3, 3}]
И теперь я хочу заменить "3" на переменную. Я могу сделать, например:
f[x_] := Array[#1^#2 == x &, {x, x}]
Вопрос: есть ли способ использовать только слоты и как функциональную нотацию?
Ответы
Ответ 1
Как насчет
Map[Last, #] & /@ Array[#1^#2 == #3 &, {#, #, #}] &[3]
Ужасно уродливое извлечение элементов, и очень интересно Map[Last, #]&
дает мне отличный результат, чем Last /@
. Это связано с тем, что Map
имеет разные атрибуты, чем &
?
Ответ 2
Не совсем ответ на исходный вопрос, но я заметил, что многие люди интересовались вещами #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
не заботятся о возможных столкновениях имен между именами в конструкциях оглавления, которые могут присутствовать в выражениях subject для управления приложениями и имен переменных шаблонов в правилах. Хуже всего то, что 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},[email protected]@{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. В качестве альтернативы он мог бы быть "водонепроницаемым", но, возможно, ценой менее подверженной воздействию. Это было явно конструктивное решение.
Ответ 3
Я думаю, вы знаете, что в документации говорится о вложенных чистых функциях.
Использовать явные имена для настройки вложенных чистые функции (например):
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}]]
Ответ 4
Как насчет With[{x = #1}, Array[#1^#2 == x &, {x, x}]] &
?
Ответ 5
Может
Array[#1^#2 &, {#, #}] /. i_Integer :> i == # &[3]
или
Thread /@ Thread[# == Array[#1^#2 &, {#, #}]] &[3]