开发者

Pattern with optional argument in replacement rule

I am trying to define a replacement rule with optional argument color_RGBColor which should be replaced with Sequence[] when it is absent in the original expression:

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

When RGBColor is present in the original expression, the rule works:

style[Line[], RGBColor[{}]] /. 
 style[line_Line, ___, 
   color_RGBColor: Unevaluated@Sequence[], ___] :> {c开发者_如何学编程olor, line}

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

But when it is absent, it does not:

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

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

My questions are:

1) Why it does not work?

2) Is it possible to construct a single pattern which will work as desired?


Your pattern does not work because of the way the pattern-matching works for the default (optional) arguments, and also because you restricted the head to be RGBColor. The problem is that the default argument value must match the pattern, while Unevaluated[Sequence[]] certainly does not match _RGBColor.

You have several ways out. A first attempt is to weaken your type-checking:

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

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

But this does not work since the matching is incorrect - the typing is indeed too weak. The hacky way to make it work is this:

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[]}

The recommended way to do it is this:

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[]}

This feature of the pattern-matcher is not very widely known, so I will stress it again: the default value for the (optional) pattern x:ptrn:default must match ptrn. For another example of such behavior, see this Mathgroup discussion.


Perhaps this works for you:

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[]}
*)

I guess your replacement rule does not work just because there is no element with a Head RGBColor, so there is no match.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜