Opposite of Alternatives in a Rule
The following code defines AndRuleDelayed
to take a number of patterns followed by a (single) replacement and build a rule. The rule matches if and only if all patterns match, and the replacement can involve variables from any of the patterns. If the same variable name appears in two patterns, the combined pattern will only match if all occurrences of that name match the same thing (exactly like Mathematica does normally in patterns like {a_,a_}
).
Clear[AndRuleDelayed];
AndRuleDelayed::usage =
"AndRuleDelayed[p1_,p2_,...,rhs_] is p1&p2&...:>rhs.";
Begin["AndRule`"];
SetAttributes[AndRuleDelayed, HoldAll];
SyntaxInformation[AndRuleDelayed] = {"ArgumentsPattern" -> {_, __}};
AndRuleDelayed[patts__, rhs_] :=
(total_ :>
With[{result =
Cases[{Table[total, {Length[{patts}]}]}, {patts} :> rhs]},
result[[1]] /; result =!= {}]);
End[];
(I've put the code in a scope because I suspect that there may be issues with name collisions otherwise.) Examples:
Cases[{2/3, 1 + Pi, 3 - Gamma[I], 1 + x},
AndRuleDelayed[Plus[a_, b_], c_?NumericQ, {a, b, c}]]
(*=> {{1, Pi, 1 + Pi}, {3, -Gamma[I], 3 - Gamma[I]}}*)
Cases[{{5, 2, 3, 5}, {3, 4}, {6, 3, 6}},
AndRuleDelayed[{___, 3, a_}, {a_, b_, ___}, l_List,
g[a, b, Length[l]]]]
(*=> {g[5, 2, 4], g[6, 3, 3]}*)