For some function f, consider the following expression:

 f[2] f[5] - f[1] f[2] f[5] - f[2] f[3] f[5] + f[1] f[2] f[3] f[5] - f[2] f[4] f[5] + f[1] f[2] f[4] f[5] + f[2] f[3] f[4] f[5] - f[1] f[2] f[3] f[4] f[5]

How can I manipulate this expression so that it instead reads:

f[2,5] - f[1,2,5] - f[2,3,5] + f[1,2,3,5] - f[2,4,5] + f[1,2,4,5] + f[2,3,4,5] - f[1,2,3,4,5]

I.e. the function is now implemented on a list of the individual arguments. I've had a go at trying Map to achieve this but with no luck.


To make this more meaningful for functions, how can the above string be passed as a single vector. Specifically, how can we obtain the output

f[{2,5}] - f[{1,2,5}] - f[{2,3,5}] + f[{1,2,3,5}] - f[{2,4,5}] + f[{1,2,4,5}] + f[{2,3,4,5}] - f[{1,2,3,4,5}],

this form can then be applied to a predefined function f[u] that operates on the list u. The function should also be able to take additional arguments.


1 Answer 1


Try using upvalues:

Times[f[x__], f[y__]] ^:= f[x, y]

and then evaluating the expression f[2] f[5] - f[1] f[2] f[5] - ... again.

You could also do it without modifying f and using ReplaceRepeated (//.):

expr //. Times[f[x__], f[y__]] :> f[x, y]
  • $\begingroup$ This works great. Sometimes, it doesn't apply the same ordering. I.e. f[2] f[3] f[5] //. Times[f[x__], f[y__]] :> f[x, y] gives f[5, 2, 3] not f[2, 3,5]. Is there a simple fix for this? $\endgroup$
    – Sid
    Commented Mar 19, 2021 at 0:12
  • 2
    $\begingroup$ @Sid - Once you have defined UpValues for f you do not need to use /. or //. If you want the arguments ordered use ClearAll[f]; Times[f[x__], f[y__]] ^:= f @@ Sort[{x, y}] Then just evaluate f[2] f[3] f[5] and the result will be f[2, 3, 5] $\endgroup$
    – Bob Hanlon
    Commented Mar 19, 2021 at 0:56
  • $\begingroup$ @Sid Another way: you can evaluate SetAttributes[f, Orderless], and f will thereafter always automatically put its arguments in canonical order (the same ordering Times uses). $\endgroup$
    – thorimur
    Commented Mar 19, 2021 at 4:03
  • 1
    $\begingroup$ @Sid expr //. Times[f[x__], f[y__]] :> f[x, y] /. f[x__] :> f[{x}] $\endgroup$ Commented Mar 19, 2021 at 15:26
  • 1
    $\begingroup$ @Sid Or expr //. Times[f[x__], f[y__]] :> f[x, y] /. f :> (f@*List) $\endgroup$ Commented Mar 19, 2021 at 15:27

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.