Because Mathematica prioritizes specific function definitions over general ones, simply making the definition
M[i_, j_] := -M[j, i]
will work as long as you only try to evaluate M
with values for i
and j
for which either M[i, j]
or M[j, i]
have been explicitly defined. Otherwise you get infinite recursion:
M[1, 2] := a
M[4, 3] := b
M[1, 2]
(* a *)
M[2, 1]
(* -a *)
M[3, 4]
(* -b *)
M[1, 3]
(* $RecursionLimit::reclim2: Recursion depth of 1024 exceeded during evaluation of M[3,1]. *)
(* Hold[-M[3, 1]] *)
Clear[M]
To avoid this, we can make a definition for M
that only allows itself to be recursed twice, like so:
Module[{n = 0},
M[i_, j_] /; n < 2 := Block[{n = n + 1}, -M[j, i]]
]
The variable n
counts the number of times that this definition of M
has been called recursively. If n
is less than two, the definition applies, and the i
and j
are swapped. When n
is equal to two, the definition doesn't apply, and evaluation terminates. Since at this point the definition has been applied twice, the original expression is returned.
Now we have
M[1, 2] := a
M[4, 3] := b
M[1, 2]
(* a *)
M[2, 1]
(* -a *)
M[3, 4]
(* -b *)
M[1, 3]
(* M[1, 3] *)
(Side note: Mathematica colors the n
in the Block
expression red, because it thinks that we've created a naming conflict between the Module
and the Block
, but in fact it works just how we want.)
f[x_?Internal`SyntacticNegativeQ] := -f[-x]
$\endgroup$