# Sort the arguments of a function using replace

I want to sort the arguments of a function f while multiplying with the signature of the permutation, i.e. f is totally antisymmetric function. My idea was something like

f[2, 4, 3, 1] /. {f[x1_, x2_, x3_, x4_] -> Signature[{x1, x2, x3, x4}]*f[Sort[{x1, x2, x3, x4}][[1]], Sort[{x1, x2, x3, x4}][[2]], Sort[{x1, x2, x3, x4}][[3]], Sort[{x1, x2, x3, x4}][[4]]]}


where I would have expected the output to be

- f[1, 2, 3 ,4]


f[2, 4, 3, 1]


Any ideas on how to achieve this?

• How about f[{2, 4, 3}] /. f[l_List] :> (Signature[l] f[Sort[l]]), which gives -f[{2, 3, 4}] Commented Jul 16 at 22:02
• The signature of {2,4,3,1} is 1, not -1, so that part's not the issue. Use RuleDelayed instead of Rule, i.e., replace -> with :>. Then your code works. But f[4, 2, 3, 1] /. f[xs__] :> Signature[{xs}] f @@ Sort[{xs}] is shorter. Commented Jul 17 at 0:09

Signature and Sort work on arbitrary heads, not just List:

f[3, 4, 2, 1] /. y_f :> Signature[y] Sort[y]

(* -f[1, 2, 3, 4] *)

f[3, 4, 2, 1] // Signature[#] Sort[#] &

(* -f[1, 2, 3, 4] *)


Another way:

Block[{f},
call : f[x__] /; ! OrderedQ[{x}] && ! TrueQ@$$sorting := Block[{$$sorting = True}, Signature[call] Sort[call]];
f[3, 4, 2, 1]
]

(* -f[1, 2, 3, 4] *)


If you remove the enclosing Block[{f},...], the definition becomes permanent so that the antisymmetric property is automatically done. That's up to you.

Note: Instead of OrderedQ[{x}], one could use OrderedQ[Unevaluated@call]. Like Sort, its argument may have any head. But I chose the code with fewer letters.