When using the same name for part of patterns inside Alternatives how come it behaves differently for strings than in normal patterns?

{StringMatchQ["ab", (x_ ~~ "c") | ("a" ~~ x_)],
 StringMatchQ["ab", ("a" ~~ x_) | (x_ ~~ "c")]}
(* False, True *)

{MatchQ[{1, 2}, {x_, 3} | {1, x_}],
 MatchQ[{1, 2}, {1, x_} | {x_, 3}]}
(* True, True *)

StringMatchQ["ab", (x_ ~~ "c") | (x_ ~~ "b")]
(* False *)
  • $\begingroup$ You are binding the first x_ with the first alternative. Try {StringMatchQ["ab", (x_ ~~ "c") | ("a" ~~ y_)], StringMatchQ["ab", ("a" ~~ x_) | (y_ ~~ "c")]} instead $\endgroup$ Commented Sep 17, 2013 at 18:04
  • $\begingroup$ @belisarius I don't think it's that simple, look for instance at: StringMatchQ["ab", (x_ ~~ "c") | (x_ ~~ "b")] if x was bound to "a" then it would still match on the second one $\endgroup$
    – ssch
    Commented Sep 17, 2013 at 18:19
  • $\begingroup$ perhaps x is bound to Undefined in the first try. Just ranting. Of course if you replace the secon x_ by y_, it works again $\endgroup$ Commented Sep 17, 2013 at 18:22
  • 2
    $\begingroup$ You may see that x_ becomes bounded to an empty string FullForm@StringReplace["ab", Alternatives[(x_ ~~ "c"), ("a" ~~ y_)] :> 2 x] $\endgroup$ Commented Sep 17, 2013 at 19:22
  • 6
    $\begingroup$ String patterns are fundamentally different from ordinary patterns, as they are actually converted into regular expressions and passed off to the PCRE library for processing. As such, their features, limitations, and behaviors are exactly those of PCREs. Why this particular behavior arises I don't personally know, but if you look into the PCRE documentation you might find an answer. $\endgroup$ Commented Sep 17, 2013 at 19:42

1 Answer 1


As @OleksandrR pointed out string patterns are translated to PCRE

The tutorial,in the Implementation Details section, mentions PatternConvert that shows the translation used:

StringPattern`PatternConvert[(x_ ~~ "c") | ("a" ~~ x_)]
(* {"(?ms)(?:(.)c|a(?:\\1))", {{Hold[x], 1}}, {}, Hold[None]} *)

The relevant part here is (?:(.)c|a(?:\1)) when I was expecting something like: (?:(?<x>.)c|a(?<x>.))


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.