3
$\begingroup$

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.

$\endgroup$
1
  • 6
    $\begingroup$ 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 $\endgroup$ Aug 30, 2021 at 11:07

2 Answers 2

1
$\begingroup$

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.
$\endgroup$
0
$\begingroup$

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 *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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