About shorthand notation for conditional pattern (Paul Wellin "Essentials of Programming in Mathematica")
__?test
is not a shorthand for s__ /; test[s]
in the sense that it is an alias. There are major differences that one needs to be aware of.
The third bullet point under "Details" in the documentation for PatternTest
(?
) is this:
In a form such as __?test, every element in the sequence matched by __ must yield True when test is applied.
MatchQ[Range[10], {s__ /; NumberQ[s]}]
will evaluate
NumberQ[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
This will give an error (and return False
) because NumberQ
hasn't been defined to take that many arguments. You can fix it, in a sense, like this:
MatchQ[Range[10], {s__ /; NumberQ[{s}]}]
but now it returns False
because NumberQ[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]
sees a list, which is not a number.
To actually get what we want using this method, we have to do this:
MatchQ[Range[10], {s__ /; AllTrue[{s}, NumberQ]}]
__?test
is much shorter for this type of test, but as we have seen it is not a shorthand in the sense that we can use it as a drop-in replacement wherever we want. ?
essentially does the AllTrue[{s}, test]
part for us.
In short: you are confusing Blank[]
(_
) and BlankSequence[]
(__
). (There is also BlankNullSequence[]
(___
), but I shall skip talking about that to keep it short.)
What Wellin said about the patterns involving Blank[]
(_
) is mostly true, in that one has the choice of using Condition
(/;
) or PatternTest
(?
). So, you can do n_?NumberQ
(the form often preferred for relatively simple expression tests) or n_ /; NumberQ[n]
(more often used if the expression test is sufficiently complicated, e.g. n_ /; NumberQ[n] && Positive[n]
). It is possible to express one in terms of the other, but the preferences I gave are common.
In your attempt, you were trying to use /;
with BlankSequence[]
(__
); recall that __
is supposed to match one or more things, when the expression test NumberQ[]
can only take one argument. So NumericQ[s]
will choke if s
was e.g. 1, 2
, as you are now trying to give it two arguments.
In contrast, the pattern s__?NumberQ
is fine; it is the way to test that s
is one or more things that satisfy the expression test NumericQ[]
.
If you had really insisted on using /;
for this, one way in this case is to use something like VectorQ[]
:
MatchQ[Range[10], {s__} /; VectorQ[{s}, NumberQ]]