# Partially Orderless Arguments in Functions

I am a Mathematica beginner and I'm trying to implement a function of type

f[i1_,i2_,i3_,i4_]


such that it is orderless in the first two arguments and in the last two separately. Namely, I want

f[i4,i3,i2,i1]


returning

f[i3,i4,i1,i2]


and

f[i1,i2,i3,i4]==f[i2,i1,i3,i4]
f[i1,i2,i3,i4]==f[i1,i2,i4,i3]


returning

True
True


How can I define such object?

• Can you elaborate on what you are trying to achieve? Orderless does more than what you show. It does not only ensure equality in cases like your example, but also affects pattern matching. Ensuring this sort of equality is easy enough. How to also handle pattern matching, I don't know (maybe not possible). Nov 25, 2021 at 11:08
• Not an answer because I don't know if this is what you really want. f[a1_, a2_, b1_, b2_] /; Not[OrderedQ[{a1, a2}] && OrderedQ[{b1, b2}]] := f @@ Join[Sort[{a1, a2}], Sort[{b1, b2}]]. Now try f[4, 3, 2, 1]. Nov 25, 2021 at 11:10
• Sure! I am trying to define rules to be applied on patterns of type a[i_] F[t[i_],t[j_],s[i_],s[j_]]. F is a symmetric function in the first two variables and last two separately and I want the same rule to be applied if the pattern is a[j_] F[t[i_],t[j_],s[i_],s[j_]]. I tried that if I consider only two variables a[i_] F[t[i_],t[j_]] everything works by setting F Orderless. I wanted something similar with 4 variables as too many rules would be necessary otherwise. Thanks! Nov 25, 2021 at 16:58

Assume that "f2" is the function you want. Then we first define a function of 2 arguments that is orderless:

ClearAll[fol,f1,f2]
SetAttributes[fol, Orderless]


Now we define the final function "f1" using "fol";

f1[x1_, x2_, x3_, x4] = f2[fol[x1, x2], fol[x3, x4]]


To test if this works:

d= f1 @@ # & /@ Permutations[{1, 2, 3, 4}];
AllTrue[d, d[] == # &]
(*True*)

ClearAll[f]
f[OrderlessPatternSequence[i1_, i2_], OrderlessPatternSequence[i3_, i4_]] :=
FOO[i1, i2, i3, i4]

f[i4, i3, i2, i1]

 FOO[i3, i4, i1, i2]

f[i1, i2, i3, i4] == f[i2, i1, i3, i4]

True

f[i1, i2, i3, i4] == f[i1, i2, i4, i3]

True

f[4, 3, 2, 1] == f[4, 3, 1, 2] == f[3, 4, 2, 1] == f[3, 4, 1, 2]

True


Edited after comment below

The proposed solution can be useful if the objective is solely to manipulate a symbolic inert function (a symbol without an explicit definition and that does not evaluate anything).

In such a scenario, to avoid defining an auxiliary function as FOO in @kglr's answer or fol in @DanielHuber's answer, one solution is to add a canonical sorting operation in the definition of the function:

ClearAll[f];
f[a_, b_, c_, d_] :=
f[Sequence@Sort[{a, b}], Sequence@Sort[{c, d}]]


Another possibility is to define in a similar fashion a rule that keeps a canonical ordering of the arguments.

Test: Using the code above, the cell below evaluates to 0.

f[a,b,c,d]-f[b,a,c,d]+f[a,b,d,c]-f[b,a,d,c]

• I rather think FOO[..] was meant to represent the body of the function, that is, what was to be calculated. For instance f could be the function f[OrderlessPatternSequence[i1_, i2_], OrderlessPatternSequence[i3_, i4_]] := (i2 - i1) + (i4 - i3);. Then f[1, 5, 6, 2] == f[5, 1, 2, 6], both being 8. OTOH, kglr didn't explain anything and the OP didn't really make clear if the "function" f[a,b,c,d] was really a function (that evaluated to something else) or an inert expression. Jun 26 at 1:21
• I also wondered if FOO was supposed to be an explicit function. I was personally looking for a solution in the case where f was just a symbol rather than an explicit function and I was not satisfied with the solutions here as they all involved using an auxilary function. BTW I was not sure whether it was ok to reference the other users to explain what I meant by auxiliary function. Perhaps I should have instead tried to keep my answer in isolation from any other answer here (as they might not be fond of being referenced). Jun 26 at 17:05
• @MichaelE2 I edited my answer accordingly Jun 26 at 17:17