不是原来问题的真正答案,但我注意到很多人对#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]
这种行为与规则替换的侵入性有关 - 也就是说,Rule 和 RuleDelayed 不关心可能出现在表达式主题中的范围构造中的名称之间可能的名称冲突规则应用程序,以及规则中模式变量的名称。更糟糕的是,g 和 f 在单独使用时完全可以正常工作。正是当它们混合在一起时,才会发生这种纠缠,只是因为我们不幸在f 的主体中使用了相同的模式变量x,就像在纯函数中一样。这使得此类错误很难被发现,而在实践中有时确实会发生这种情况,因此我建议不要将带有命名参数的纯函数作为参数传递给通过模式定义的高阶函数。
编辑:
对词法作用域的模拟进行了一些扩展。我的意思是,例如,当我创建一个纯函数(这是一个词法范围构造,将其主体中的变量名绑定到传递的参数的值)时,我希望我不能改变这个绑定在我创建了一个函数之后。这意味着,无论我在哪里使用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 所指出的那样存在漏洞。或者,它可能是“防水的”,但可能是以较少暴露为代价的。这显然是一个设计决定。