在mathematica中选择特定的符号定义(不是转换规则)

时间:2011-08-23 17:34:35

标签: wolfram-mathematica

我有以下问题。

f[1]=1;
f[2]=2;
f[_]:=0;

dvs = DownValues[f];

这给出了

dvs = 
   {
      HoldPattern[f[1]] :> 1, 
      HoldPattern[f[2]] :> 2, 
      HoldPattern[f[_]] :> 0
   }

我的问题是我想只提取f [1]和f [2]等的定义,而不是一般定义f [_],我不知道该怎么做。

我试过了,

Cases[dvs, HoldPattern[ f[_Integer] :> _ ]] (*)

但它没有给我任何东西,即空列表。

有趣的是,将HoldPattern更改为临时^脚注

dvs1 = {temporary[1] :> 1, temporary[2] :> 2, temporary[_] :> 0}

并发出

Cases[dvs1, HoldPattern[temporary[_Integer] :> _]] 

给出

{temporary[1] :> 1, temporary[2] :> 2}

它有效。这意味着(*)几乎是一种解决方案。

我不明白为什么它适用于临时而不是HoldPattern?如何使用HoldPattern直接使其工作?

当然,问题是什么得到评估,什么不得等。在Mathematica编码时的以太问题。对于真正的大师来说......

致以最诚挚的问候 卓然

脚注=我手动输入它作为替换“/ .HoldPattern - > temporary”实际执行f [_]:= 0规则并给出一些奇怪的,我当然希望避免这种情况。

3 个答案:

答案 0 :(得分:7)

原因是您必须使用Verbatim转义HoldPattern

In[11]:= Cases[dvs, 
            Verbatim[RuleDelayed][
               Verbatim[HoldPattern][HoldPattern[f[_Integer]]], _]]

Out[11]= {HoldPattern[f[1]] :> 1, HoldPattern[f[2]] :> 2}

只有少数头是必要的,而HoldPattern就是其中之一,正是因为它通常对模式匹配器“不可见”。对于您的temporary或其他负责人,这不是必需的。请注意,模式f[_Integer]包含在HoldPattern中 - 此时HoldPattern用于其直接目的 - 保护模式不受评估。请注意,RuleDelayed也包含在Verbatim中 - 这实际上是Verbatim的另一种常见情况 - 这是必需的,因为Cases具有涉及规则的语法,我们这样做不希望Cases在此处使用此解释。因此,IMO是一个非常好的例子来说明HoldPatternVerbatim。 另请注意,可以使用HoldPattern完全实现目标,如下所示:

In[14]:= Cases[dvs,HoldPattern[HoldPattern[HoldPattern][f[_Integer]]:>_]]

Out[14]= {HoldPattern[f[1]]:>1,HoldPattern[f[2]]:>2}

但是,使用HoldPattern进行转义(代替Verbatim)是IMO在概念上的错误。

修改

使用Cases稍微调整一下情况,这是一个简单的例子,我们使用涉及转换规则的Cases语法。这种扩展语法指示Cases不仅可以找到并收集匹配的部分,还可以在找到它们之后根据规则对其进行转换,因此生成的列表包含转换后的部分。

In[29]:= ClearAll[a, b, c, d, e, f];
Cases[{a, b, c, d, e, f}, s_Symbol :> s^2]

Out[30]= {a^2, b^2, c^2, d^2, e^2, f^2}

但是如果我们需要找到自己规则的元素呢?如果我们试试这个:

In[33]:= Cases[{a:>b,c:>d,e:>f},s_Symbol:>_]
Out[33]= {}

它不起作用,因为Cases将第二个参数中的规则解释为使用扩展语法的指令,查找符号并将其替换为_。由于它默认在级别1上搜索,并且符号在此处的级别2上,因此它什么也没找到。观察:

In[34]:= Cases[{a:>b,c:>d,e:>f},s_Symbol:>_,{2}]
Out[34]= {_,_,_,_,_,_}

无论如何,这不是我们想要的。因此,我们必须强制Cases将第二个参数视为普通模式(简单而非扩展的语法)。有几种方法可以做到这一点,但所有这些方法都以某种方式“逃避”RuleDelayed(或Rule):

In[37]:= Cases[{a:>b,c:>d,e:>f},(s_Symbol:>_):>s]
Out[37]= {a,c,e}

In[38]:= Cases[{a:>b,c:>d,e:>f},Verbatim[RuleDelayed][s_Symbol,_]:>s]
Out[38]= {a,c,e}

In[39]:= Cases[{a:>b,c:>d,e:>f},(Rule|RuleDelayed)[s_Symbol,_]:>s]
Out[39]= {a,c,e}

在所有情况下,我们要么避免使用Cases的扩展语法(最后两个示例),要么设法将它用于我们的优势(第一种情况)。

答案 1 :(得分:4)

Leonid,当然,完全回答了为什么temporary解决方案有效,但HoldPattern没有解决的问题。但是,作为解决您提取f[1]f[2]类型术语的原始问题的答案,他的代码有点难看。为了解决提取这些术语的问题,我只关注定义左侧的结构,并使用FreeQ在所有级别进行搜索的事实。所以,定义

f[1] = 1;  f[2] = 2;  f[_] := 0;
dvs = DownValues[f];

以下所有

Select[dvs, FreeQ[#, Verbatim[_]] &]
Select[dvs, FreeQ[#, Verbatim[f[_]]] &]
Select[dvs, ! FreeQ[#, HoldPattern[f[_Integer]]] &]

产生结果

{HoldPattern[f[1]] :> 1, HoldPattern[f[2]] :> 2}

如果f[...]的下限右侧没有Blank[](或者,对于第一个版本,f)条款,则上述之一将会可能是合适的。

答案 2 :(得分:3)

基于Simon的优秀解决方案here,我建议:

Cases[DownValues[f], _?(FreeQ[#[[1]], Pattern | Blank] &)]