Clear[x]
StringCases["abcadcacb","a"~~x_~~"c"->x]
{b,d}
x=99;
StringCases["abcadcacb","a"~~x_~~"c"->x]
{99,99}
This fails even if x is local in a Module
Module[{x}, StringCases["abcadcacb", "a" ~~ x_ ~~ "c" -> x]]
Why x_->x
causes problems is explained in:
Unexpected behavior of rule matching a pattern
Shortly, use :>
.
Why Module
fails to help? While Rule
is not a scoping construct it is considered one by Module
. Which means x
inside will not be scoped by Module
if x_
appears in a left hand side of rule.:
Module[{x},
Hold @ Column @ {
Rule[x_, x]
, RuleDelayed[x_, x]
, Module[{x}, x]
, DirectedEdge[x_, x]
, foo[x_, x]
, Rule[y_, y x]}
]
Relevant part of docs:
Symbols that occur as pattern names in lhs are treated as local to the rule. This is true when the symbols appear on the right-hand side of /; conditions in lhs, and when the symbols appear anywhere in rhs, even inside other scoping constructs.
ref/Rule/Details
About issues with nested scoping constructs you can take a look at:
which also explains the last example with y_->y x
.
Also related:
RuleDelayed
(:>
) instead ofRule
(->
) to fix this problem. Also, I'm not entirely sure whyModule
doesn't work in this case, butBlock
does, for good reasons:Block
's purpose is to locally scope variables that have definitions elsewhere. $\endgroup$x
is not locally scoped in the string expression, because it is. Evaluate"x"
afterx=99
to see that this is true. The problem is that thex
at the end of theRule
is not locally scoped. $\endgroup$RuleDelayed
when replacing expression via patterns. I only useRule
when I'm replacing an expression with something that doesn't depend on that pattern. There are use cases for both, butRuleDelayed
allows you to circumvent these scoping problems for the most part, and you can always inject an expression into the right-hand side of a delayed rule using theWith
scoping construct. Still, the implementation ofModule
here is a little wired to me. $\endgroup$