## Patterns

### Simple Patterns

Patterns and how to use them might be the most important thing to understand in Mathematica

At some level, due to its expression-centered structure, Mathematica is just a huge pattern matching machine

The most basic pattern is just an underscore, but of course it has an expression structure:

 _ // FullForm

 Blank[]


We can also provide a name for our pattern which has in various function

 p_//FullForm

 Pattern[p,Blank[]]


You'll notice the Blank[] remains. Blank[] matches any single expression. For pattern matching there's the function MatchQ . It will return whether the expression as in its first argument matches the pattern in its second.

It doesn't have to have a pattern as its second argument though:

 MatchQ[a,a]

 True


But the following will also match:

 MatchQ[a,_]

 True


As will the following where we simply named one of the parameters:

 MatchQ[a, p_]

 True


Patterns of this type can also have a Head that must match, which is specified after the underscore.

 _a//FullForm

 Blank[a]


Any expression with a as its Head will match this pattern. For instance an empty invocation:

 MatchQ[a[], _a]

 True


With arguments

 MatchQ[a[1,2,3], _a]

 True


Or incredibly deeply nested:

 MatchQ[a[a[a[a[a[a[]]]]]], _a]

 True


But the following won't:

 MatchQ[a, _a]

 False


Along with a head one can also specify a test condition which will be applied to the thing that's being matched against

 _a?test//FullForm

 PatternTest[Blank[a],test]


Which means the following will match:

 MatchQ[a[1,2,3],_a?(Length@#>1&)]

 True


But the other cases will not. Here we clearly have too few arguments:

 MatchQ[a[], _a?(Length@#>1&)]

 False


Here it's hard to see, but the outer-most structure has only one argument, so it also won't match:

 MatchQ[a[a[a[a[a[a[]]]]]],_a?(Length@#>1&)]

 False


Patterns can also be specified as parts of an expression:

 MatchQ[a[1,2,3],a[_,_,_]]

 True


Patterns can also be specified as matching 1 or more elements with a double underscore:

 __//FullForm

 BlankSequence[]


Since we have arguments this matches:

 MatchQ[a[1,2,3], a[__]]

 True


But this does not:

 MatchQ[a[], a[__]]

 False


or 0 or more elements via a triple underscore:

 ___//FullForm

 BlankNullSequence[]


This will match since all of these arguments have head Integer :

 MatchQ[a[1,2,3], a[___Integer]]

 True


And this will match since there aren't any arguments anyway:

 MatchQ[a[],a[___]]

 True


Everything that applies to single element patterns applies as well to these multi-element patterns.

### Complex Patterns

Often it's useful to be able to match more than one type. For this, there's a built-in head Alternatives , which is represented by a vertical bar |

An Integer matches this pattern:

 MatchQ[10, _Integer|_String]

 True


As does a String :

 MatchQ["10", _Integer|_String]

 True


But a Symbol does not:

 MatchQ[π, _Integer|_String]

 False


Alternatives can be used with any pattern and simplifies life tremendously in describing complicated structures concisely

One issue, however, is that a set of alternatives can't be matched multiple times with the double or triple underscores. To fix this issue there is Repeated ( .. ) and RepeatedNull ( ... ) which have the same meanings as __ and ___ respectively.

Here's an example of matching a complex structure:

 MatchQ[RandomChoice[{A,B,C}]@(Sequence@@(
If[RandomInteger[]==0,ToString@#,#]&/@RandomInteger[10,RandomInteger[10]]
)),
(A|B|C)[(_String|_Integer)...]
]

 True


It is impossible to know ahead of time what the head will be or how many arguments there will be or whether they'll be strings or integers, but that doesn't matter. We can still represent this pattern in under one line. Yet the pattern is robust enough that by doing something like appending in a symbol, our pattern catches that:

 MatchQ[
Append[
RandomChoice[{A,B,C}]@(
Sequence@@(
If[RandomInteger[]==0,ToString@#,#]&/@RandomInteger[10,RandomInteger[10]]
)
),
RandomChoice[{A,B,C}]
],
(A|B|C)[(_String|_Integer)...]
]

 False


There is one further useful addition to this current redux on patterns. Sometime you know you'll, say, see pairs of a patterns, and so a simple .. or __ isn't precise enough. For this case there is the head PatternSequence which can capture this:

 MatchQ[
A@@(If[OddQ@#,ToString@#,#]&/@Range[10]),
A[PatternSequence[_String,_Integer]..]
]

 True


### Except

The final piece of patterns is the head Except . It specifies that anything Except the pattern inside should match. It is a negation pattern, in essence.

 MatchQ[1,Except[_String]]

 True


These examples show a basic usage:

 MatchQ[<|a->b|>, Except[_String]]
MatchQ[Graphics@Disk[], Except[_String]]
MatchQ["asdasd", Except[_String]]

 True

 True

 False


One interesting case is the two argument form of Except , where the second argument is a pattern that should match and the first argument is a list of exceptions to that pattern.