如何暂时修改内置函数
在Mathematica里,内置函数一般拥有属性Protected
,这意味着你不能随便内置函数的定义进行修改。当然,对于绝大部分函数(除去那些有Locked
属性的)都可以Unprotect
了之。但是这样做是极为危险的,有时你都忘记了自己对内置函数做了哪些修改,虽然这些修改在重启Kernel之后都会恢复,但还是不建议这样做。
今天介绍一种暂时修改内置函数的方法,这个方法用到了没有文档的内部函数,Internal`InheritedBlock
。此函数的用法和Block
类似,它能将内置函数复制一份并进行任意的修改且不影响源函数。
举个例子来介绍其使用方法。假如我们希望编写一个函数WithOrderedPlus[expr]
,在这个函数里运行的expr
里的Plus
函数将不会带有Orderless
属性。我们实现的方法如下:
SetAttributes[WithOrderedPlus, HoldFirst];
WithOrderedPlus[expr___] := Internal`InheritedBlock[
{Plus}, ClearAttributes[Plus, Orderless]; expr];
代码开始时设置HoldFirst
属性是为了防止表达式在进入Block
之前就被计算。现在来试试效果:
In[1]:= WithOrderedPlus[List @@ (b + a + c)]
Out[1]= {b, a, c}
如果在WithOrderedPlus
外面计算的话,Orderless
属性又回来了:
In[2]:= List@@{b, a, c}
Out[2]= {a, b, c}