使用嵌套插槽(#)

时间:2011-02-07 10:28:41

标签: wolfram-mathematica

假设我想构建像

这样的东西
Array[#1^#2 == 3 &, {3, 3}] 

现在我想用变量替换“3”。我可以做,例如:

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

问题是:是否有办法使用广告位和&作为功​​能符号?

5 个答案:

答案 0 :(得分:9)

不是原来问题的答案,但我注意到很多人对#0的东西感兴趣,所以here我提出了几个非平凡的例子,希望它们会有用。

关于嵌套函数的声明,应该使用带有命名参数的函数:虽然这通常是正确的,但应始终记住纯函数(通常)的词法作用域是在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]

此行为与规则替换的侵入性有关 - 也就是说,RuleRuleDelayed不关心作用域结构中名称之间可能的名称冲突,这可能是出现在受规则应用程序约束的表达式中,以及规则中模式变量的名称。更糟糕的是,gf在单独处理时完全正常。当它们混合在一起时,就会发生这种纠缠,只是因为我们不幸在x的主体中使用相同的模式变量f,就像在纯函数中一样。这使得这些错误很难捕获,而这种情况有时会在实践中发生,所以我建议不要将带有命名参数的纯函数作为参数传递给通过模式定义的高阶函数。

编辑:

扩展了词法范围的模拟。我的意思是,例如,当我创建一个纯函数(它是一个词法范围构造,将其体内的变量名称绑定到传递参数的值)时,我希望我不能改变这个绑定在我创建了一个函数之后。这意味着,无论我在哪里使用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在this页面上的帖子底部也注意到了这种行为 - 显然他有类似的经历。根据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所指出的那样是漏洞。或者,它可能是“防水的”,但也许是为了减少暴露的代价。这显然是一个设计决定。

答案 1 :(得分:4)

怎么样

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

非常丑陋的元素提取,非常有趣Map[Last, #]&给出了与Last /@不同的结果。这是因为Map具有与&不同的属性吗?

答案 2 :(得分:3)

我想您知道文档中有关nested pure functions的内容。

  

使用显式名称设置嵌套   纯函数(例如):

     

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}]]

答案 3 :(得分:3)

With[{x = #1}, Array[#1^#2 == x &, {x, x}]] &怎么样?

答案 4 :(得分:2)

也许

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

或者

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