替换规则中带有可选参数的模式

时间:2011-06-19 08:02:55

标签: wolfram-mathematica

我正在尝试使用可选参数color_RGBColor定义替换规则,当原始表达式中不存在时,该替换规则应替换为Sequence[]

style[line_Line, ___, 
  color_RGBColor: Unevaluated@Sequence[], ___] :> {color, line}

当原始表达式中存在RGBColor时,规则有效:

style[Line[], RGBColor[{}]] /. 
 style[line_Line, ___, 
   color_RGBColor: Unevaluated@Sequence[], ___] :> {color, line}

=> {RGBColor[{}], Line[]}

但是当它不存在时,它不会:

style[Line[], Thickness[0.01]] /. 
 Style[line_Line, ___, 
   color_RGBColor: Unevaluated@Sequence[], ___] :> {color, line}

=> style[Line[], Thickness[0.01]]

我的问题是:

1)为什么它不起作用?

2)是否有可能构建一个能够按预期工作的模式?

2 个答案:

答案 0 :(得分:7)

您的模式不起作用,因为模式匹配对默认(可选)参数起作用的方式,也因为您将头部限制为RGBColor。问题是默认参数值必须与模式匹配,而Unevaluated[Sequence[]]肯定与_RGBColor不匹配。

你有几种方法可以解决。第一次尝试是削弱你的类型检查:

In[10]:= style[Line[],Thickness[0.01]]/.
style[line_Line,___,color_: Unevaluated@Sequence[],___]:>{color,line}

Out[10]= {Thickness[0.01],Line[]}

但这不起作用,因为匹配不正确 - 输入确实太弱了。让它发挥作用的黑客方法是:

In[14]:= style[Line[], RGBColor[{}]] /. 
 style[line_Line, ___, color : (_RGBColor | _Unevaluated) : 
    Unevaluated@Sequence[], ___] :> {Evaluate@color, line}


Out[14]= {RGBColor[{}], Line[]}

In[15]:= style[Line[], Thickness[0.01]] /. 
  style[line_Line, ___, color : (_RGBColor | _Unevaluated) : 
     Unevaluated@Sequence[], ___] :> {Evaluate@color, line}

Out[15]= {Line[]}

建议的方法是:

In[18]:= style[Line[], Thickness[0.01]] /. 
style[line_Line, ___, color : (_RGBColor | Automatic) : Automatic, ___] :> 
  If[color === Automatic, {line}, {color, line}]


Out[18]= {Line[]}

In[17]:= style[Line[], RGBColor[{}]] /. 
 style[line_Line, ___, color : (_RGBColor | Automatic) : Automatic, ___] :> 
   If[color === Automatic, {line}, {color, line}]


Out[17]= {RGBColor[{}], Line[]}

模式匹配器的这个特性并不广为人知,所以我将再次强调它:(可选)模式x:ptrn:default的默认值必须与ptrn匹配。有关此类行为的另一个示例,请参阅this Mathgroup讨论。

答案 1 :(得分:2)

也许这适合你:

style[Line[a], RGBColor[{}]] /. 
 style[line_Line, ___, Longest[color___RGBColor], ___] :> {color,line}
(*
{RGBColor[{}], Line[a]}
*)

style[Line[]] /. 
 style[line_Line, ___, Longest[color___RGBColor], ___] :> {color, line}
(*
{Line[]}
*)

我猜你的替换规则不起作用只是因为没有头部RGBColor的元素,所以没有匹配。