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[], ___] :> {color, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With