当 DownValues 已经存在时可以阻止 OwnValues 吗?

2024-02-01

对于已经分配了与名称“a”关联的 DownValues 的情况,是否有一种可接受的方法来阻止将 OwnValues 分配给相同的名称? (我最初是在尝试某人实现数据字典时遇到这个问题的。)

这就是我要避免的:

Remove[a];
a[1] := somethingDelayed
a[2] = somethingImmediate;
DownValues[a]
a[1]
a[2]

返回...

{HoldPattern[a[1]] :> somethingDelayed, 
 HoldPattern[a[2]] :> somethingImmediate}
somethingDelayed
somethingImmediate

现在如果我们要评估:

a = somethingThatScrewsUpHeads;
(* OwnValues[a] above stored in OwnValues *)
a[1]
a[2]

我们得到...

somethingThatScrewsUpHeads[1]
somethingThatScrewsUpHeads[2]

是否有一种简单/灵活的方法来阻止 DownValues 中任何名称的 OwnValues? (让我猜一下......这是可能的,但是性能会受到影响?)


我不知道这是否是“可接受的”方式,但您可以定义一个规则来防止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}]

...安装规则之前和之后。时间上没有明显的变化。然后我尝试安装Set10,000 个生成符号的相关上值,因此:

Do[
  With[{s=Unique["s"]}
  , s /: HoldPattern[(Set|SetDelayed)[s, _]] :=
      (Message[s::readOnly]; Abort[])
  ]
, {10000}]

同样,即使制定了如此多的增值规则,时机也没有改变。这些结果表明,从性能的角度来看,这种技术是可以接受的,尽管我强烈建议在您的特定应用程序的上下文中执行性能测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当 DownValues 已经存在时可以阻止 OwnValues 吗? 的相关文章

随机推荐