9
$\begingroup$

I was looking at this question (here) and I tried to find any thing gives the opposite of Alternatives. In other words, some pattern matching function that gives true when expression matches ALL patterns. Is there any function for that?

For example:

x has to be Integer AND Real

The other thing is that from Mr.Wizard solution, suppose I want to make a rule in which x has to be Integer and Real and also x>10, how can I define that in external rule or pattern in one shot and use pattern test ? or pattern : ( for example to do something like this f[x_?match] or f[x:(pattern)])

I hope I made the question clear.

Thank you

$\endgroup$
  • 5
    $\begingroup$ In Mathematica a number cannot be both Integer and Real; those are two completely different heads. $\endgroup$ – J. M. is away Jul 16 '15 at 7:23
  • $\begingroup$ Can you give an example of a situation which you cannot formulate as a single pattern without using such a construct? I cannot come up with with a non-convoluted one. x_Integer /; x > 10 works. $\endgroup$ – Szabolcs Jul 16 '15 at 7:53
  • 1
    $\begingroup$ I guess you have to resort to MatchQ and && in the rare cases when this is necessary. For example, require that a sequence contain both a,a,a and a,a,b, which may or may not be overlapping. Then seq_ /; MatchQ[seq, {___, a,a,a, ___}] && MatchQ[seq, {___, a, a, b, ___}]. $\endgroup$ – Szabolcs Jul 16 '15 at 7:57
  • $\begingroup$ Related or possible duplicate: (6834) $\endgroup$ – Mr.Wizard Jul 16 '15 at 8:54
14
$\begingroup$

To directly get the opposite of Alternatives, you could negate each pattern with Except and then negate the Alternatives:

also[patts__] := Except[Alternatives @@ Except /@ {patts}]

Cases[Range[1, 15, 1/2], _Integer ~also~ _?(# > 10 &)]

(* {11, 12, 13, 14, 15} *)

Generally some other approach will be simpler, though, as discussed in the comments.

$\endgroup$
5
$\begingroup$

Usually one does not need what you ask for. E.g. a pattern for an even integer greater than 10:

x_Integer?EvenQ /; x > 10

(_Integer is not strictly necessary here as only integers will pass EvenQ however it should make the pattern a bit more efficient.)

But since it is an interesting quesiton here is one idea:

matchAll[expr_, form_] := matchAll[form][expr]
matchAll[form_List][expr_] := (And @@ (MatchQ /@ form))[expr] // Through

Now a function that matches each of three specifications:

test = matchAll[{_foo, _[__Integer], x_ /; Length[x] == 3}];

And its use:

test /@ {{1, 2, 3}, foo[1, 1.5, 2], foo[7, 8], foo[4, 5, 6]}
{False, False, False, True}

It can of course be turned into a pattern simply with _?test.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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