7
$\begingroup$

Alternatives seems to work fine with these simple patterns

StringMatchQ["Eric", Alternatives["Eric", "Geoff"]] (* True *) StringMatchQ["Eric", Alternatives["Geoff", "Eric"]] (* True *) 

I have a more complex pattern that matches strings enclosed with parenthesis and optionally the string "sh" at the end. The patterns are below where I assign them to a variable

patternText = StartOfString ~~ "(" ~~ textContent : ((Join[{WordCharacter}, {"-", "+", "\\", ".", ",", "/", ":", " "}] ..)) ~~ ")" ~~ EndOfString patternTextShow = StartOfString ~~ "(" ~~ textContent : (Join[{WordCharacter}, {"-", "+", "\\", ".", ",", "/", ":", " "}] ..) ~~ ")sh" ~~ EndOfString 

The patterns work fine by themselves

StringMatchQ["(Eric)", patternText] (* True *) StringMatchQ["(Eric)", patternTextShow] (* False *) StringMatchQ["(Eric)sh", patternText] (* False *) StringMatchQ["(Eric)sh", patternTextShow] (* True *) 

The results are as expected.

When I use Alternatives, however, it only works if the matching pattern is first, fails otherwise.

StringMatchQ["(Eric)", Alternatives[patternTextShow, patternText]] (* False *) StringMatchQ["(Eric)", Alternatives[patternText, patternTextShow]] (* True *) StringMatchQ["(Eric)sh", Alternatives[patternTextShow, patternText]] (* True *) StringMatchQ["(Eric)sh", Alternatives[patternText, patternTextShow]] (* False *) 

Why is this?

I found that using Or solved the problem but would like to understand why the Alternatives approach fails.

Or[ StringMatchQ["(Eric)", patternTextShow], StringMatchQ["(Eric)", patternText] ] (* True *) Or[ StringMatchQ["(Eric)", patternText], StringMatchQ["(Eric)", patternTextShow] ] (* True *) Or[ StringMatchQ["(Eric)sh", patternTextShow], StringMatchQ["(Eric)sh", patternText] ] (* True *) Or[ StringMatchQ["(Eric)sh", patternText], StringMatchQ["(Eric)sh", patternTextShow] ] (* True *) 
$\endgroup$
2
  • $\begingroup$ I would love to. There used to be an In Out merge in the Markup menu but I no longer see it. Can you refresh my memory as to how to do it? Meanwhile I will manually edit. $\endgroup$ Commented Nov 29, 2020 at 17:39
  • $\begingroup$ Unfortunately I don’t know of an automated way here in the editor. Normally when I copy code from MMA by selecting it and CTRL+C, the In and Out don’t come with it. In fact I was wondering how you had gotten them in the first place :-) Thank you for editing them out. $\endgroup$ Commented Nov 29, 2020 at 17:53

1 Answer 1

8
$\begingroup$

The problem arises from naming the inner sub-patterns in your two pattern definitions with the same identifier. When you combine the patterns with Alternatives, you then have a pattern with two sub-patterns tagged with the same name, which is bad.

Consider this simpler case.

pattern1 = StartOfString ~~ "(" ~~ t : WordCharacter .. ~~ ")1" ~~ EndOfString; pattern2 = StartOfString ~~ "(" ~~ t : WordCharacter .. ~~ ")2" ~~ EndOfString; StringMatchQ["(Eric)1", pattern1 | pattern2] StringMatchQ["(Eric)1", pattern2 | pattern1] StringMatchQ["(Eric)2", pattern1 | pattern2] StringMatchQ["(Eric)2", pattern2 | pattern1] 

True
False
False
True

It is corrected by giving the tagged sub-patterns different names.

pattern1 = StartOfString ~~ "(" ~~ s : WordCharacter .. ~~ ")1" ~~ EndOfString; pattern2 = StartOfString ~~ "(" ~~ t : WordCharacter .. ~~ ")2" ~~ EndOfString; StringMatchQ["(Eric)1", pattern1 | pattern2] StringMatchQ["(Eric)1", pattern2 | pattern1] StringMatchQ["(Eric)2", pattern1 | pattern2] StringMatchQ["(Eric)2", pattern2 | pattern1] 

True
True
True
True

$\endgroup$
1
  • $\begingroup$ You nailed it. Thank you. When I named the patterns and used the variable names it obscured the fact that the identifier names were identical. $\endgroup$ Commented Nov 29, 2020 at 18:46

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.