# Built-in functions on the LHS won't pattern-match

I have this pattern-matching problem:

F[X_,myminus[X_]]:=0

F[1,myminus[1]]

Works.

G[X_,-X_]:=0

G[1,-1]

Oops. (Doesn't match with Minus either.)

I simply use

H[X_,Y_]]:=0/;X==-Y

H[1,-1]

which also leaves no question about

H[-1,1]

but there sure must be a way to use only one LHS variable and this would speed up the pattern matching (uhm, does it really)?

EDIT: I should emphasize that a) speed is the thing that matters most and b) technically my X_ variable can only take three values, {0,1,-1}, and even these values are meaningless, so I could as well call them {a,b,c}, and only F[a,b] and F[b,a] shall trigger the rule. My own alternative idea is using the first approach and defining myminus[a]=b,myminus[b]=a which also may shorten my other rules.

• The problem is that "-X_" is interpreted as a product of -1 times X. "-1" on the other hand is a number, no product implied. You could try a condition on the LHS: G[X_,Y_]; X==-Y:=0 Aug 30, 2021 at 11:07

You could post-process the definitions:

ClearAll[FixMinusPattern];

SetAttributes[FixMinusPattern, HoldAll];

FixMinusPattern[fn_] :=
DownValues[fn] =
Quiet@ReplaceAll[DownValues[fn],
HoldPattern[
Verbatim[HoldPattern][
fn[PatternSequence[otherArgs1___, Verbatim[Pattern][a_, type_],
otherArgs2___, -1*Verbatim[Pattern][a_, type_],
otherArgs3___]]]] :>
Module[{Arg2},
HoldPattern[
Condition[
fn[otherArgs1, Pattern[a, type], otherArgs2,
Pattern[Arg2, type], otherArgs3], a == -Arg2]]]]


## Examples

ClearAll[f];
f[x_, -x_] := {x};

{f[1, 1], f[1, -1]}
(*Out: {f[1, 1], f[1, -1]} *)

FixMinusPattern[f];

{f[1, 1], f[1, -1]}
(*Out: {f[1, 1], {1}} *)


You could define other arguments:

ClearAll[g];
g[a_, c_, b_, -c_] := {a, b, c};

{g[1, 2, 3, 2], g[1, 2, 3, -2]}
(*Out: {g[1, 2, 3, 2], g[1, 2, 3, -2]} *)

FixMinusPattern[g];

{g[1, 2, 3, 2], g[1, 2, 3, -2]}
(*Out: {g[1, 2, 3, 2], {1, 3, 2}} *)


Notes:

• It'll manipulate function's DownValues in-place.
• The normal pattern and minus one should have the same name and type.
• The minus pattern should appear after the normal one, which can be easily fixed. (add another replace rule with Verbatim and -1*Verbatim reversed)
• It uses Condition[..., a == -b], you could change it easily too.

A slightly pointless way of solving the problem with a single variable...

G[X : Repeated[_, {2}] /; {X} . {1, 1} == 0] := 0

G[4, -4]
(* 0 *)