我不知道这是否是“可接受的”方式,但您可以定义一个规则来防止Set
and SetDelayed
从作用于a
:
Remove[a];
a[1] := somethingDelayed
a[2] = somethingImmediate;
a /: HoldPattern[(Set|SetDelayed)[a, _]] := (Message[a::readOnly]; Abort[])
a::readOnly = "The symbol 'a' cannot be assigned a value.";
有了这条规则,任何尝试分配OwnValue
to a
将失败:
In[17]:= a = somethingThatScrewsUpHeads;
During evaluation of In[17]:= a::readOnly:
The symbol 'a' cannot be assigned a value.
Out[17]= $Aborted
In[18]:= a := somethingThatScrewsUpHeads;
During evaluation of In[18]:= a::readOnly:
The symbol 'a' cannot be assigned a value.
Out[18]= $Aborted
然而,该规则仍然允许新的DownValues
for a
:
In[19]:= a[3] = now;
a[4] := later
In[20]:= a[3]
Out[20]= now
In[21]:= a[4]
Out[21]= later
表现
该规则似乎对性能没有产生明显影响Set
and SetDelayed
,大概是因为该规则是作为上值安装的a
。我尝试通过执行来验证这一点...
Timing@Do[x = i, {i, 100000000}]
...安装规则之前和之后。时间上没有明显的变化。然后我尝试安装Set
10,000 个生成符号的相关上值,因此:
Do[
With[{s=Unique["s"]}
, s /: HoldPattern[(Set|SetDelayed)[s, _]] :=
(Message[s::readOnly]; Abort[])
]
, {10000}]
同样,即使制定了如此多的增值规则,时机也没有改变。这些结果表明,从性能的角度来看,这种技术是可以接受的,尽管我强烈建议在您的特定应用程序的上下文中执行性能测试。