# Distribute arguments over a function in all ordered combinations

I'm looking for a function that can do this

applyDistributed[F, Dot[a, b, c]]
= {Dot[F[a, b, c]],
Dot[F[a, b], F[c]],
Dot[F[a], F[b, c]],
Dot[F[a], F[b], F[c]]}


Honestly I don't even know where to start. I can't imagine how to program in the number of arguments that F should take

• Do you mean this? applyDistributed[F_, a_, b_, c_] := {Dot[F[a, b, c]], Dot[F[a, b], F[c]], Dot[F[a], F[b, c]], Dot[F[a], F[b], F[c]]} Commented Feb 9, 2023 at 1:20

Clear["Global*"];


Using @bmf' s definition for the partitioning

applyDistributed[func_, x_] :=
Module[{list = List @@ x, func2 = Head@x},
func2 @@@ Apply[func, InternalPartitionRagged[list, #] & /@
Apply[Join, Permutations /@
IntegerPartitions[Length[list]]], {2}]]

applyDistributed[F, a . b . c]

(* {F[a, b, c], F[a, b] . F[c], F[a] . F[b, c], F[a] . F[b] . F[c]} *)

applyDistributed[F, a*b*c]

(* {F[a, b, c], F[c] F[a, b], F[a] F[b, c], F[a] F[b] F[c]} *)

applyDistributed[F, a + b + c]

(* {F[a, b, c], F[c] + F[a, b], F[a] + F[b, c], F[a] + F[b] + F[c]} *)

applyDistributed[F, a . b . c . d]

(* {F[a, b, c, d], F[a, b, c] . F[d], F[a] . F[b, c, d], F[a, b] . F[c, d],
F[a, b] . F[c] . F[d], F[a] . F[b, c] . F[d], F[a] . F[b] . F[c, d],
F[a] . F[b] . F[c] . F[d]} *)

• very nicely done!
– bmf
Commented Feb 9, 2023 at 2:40
• Oh that's great that it works with any head. Amazing! Commented Feb 9, 2023 at 10:18

One way to achieve that is to start from

list = {a, b, c};


and after you generate all the sublists

res = InternalPartitionRagged[list, #] & /@
Apply[Join, Permutations /@ IntegerPartitions[Length[list]]]


you can apply a function on the above result

ResourceFunction["ThroughOperator"][{foo}] @@@ res


As you see I have used a new resource function, available to us as of 2022 which is called ThroughOperator. This is a development thanks to @Sjoerd Smit.

It was first suggested here. In the comment section under the answer @Sjoerd Smit gives motivation for its development and subsequent use for those interested. It was further used in this thread if you want to further study it.

• ThroughOperator noted, thanks! Also thank you for the references Commented Feb 9, 2023 at 10:20
• @Albercoc glad I was able to help. Check the other answer by BobHanlon. It's more direct and really elegant :)
– bmf
Commented Feb 9, 2023 at 10:21
• (+1) Very nice. Without being pedantic, I think (since v11.1) that TakeList could be substituted for InternalPartitionRagged (but you probably already know that)? : res2=TakeList[list,#]&/@Apply[Join, Permutations /@ IntegerPartitions[Length[list]]] Commented Feb 9, 2023 at 20:26
• @user1066 you are not being pedantic at all. Indeed, TakeList should have been the go-to approach, I just like undocumented stuff. Maybe a bit too much (blushing)
– bmf
Commented Feb 10, 2023 at 1:52
alist = {a, b, c};
ReplaceList[alist, {w__, x___, y___} ->
{F @@ {w}, F @@ {x}, F @@ {y}}
] /. F[] :> Nothing // DeleteDuplicates // Dot @@@ # &


{F[a] . F[b, c], F[a] . F[b] . F[c], F[a, b] . F[c], F[a, b, c]}

list = {a, b, c};


Using TakeList and Splice (new in 12.1)

args =
Map[TakeList[list, #] &] @
Map[Splice @* Permutations] @ IntegerPartitions[Length @ list]


{{{a, b, c}}, {{a, b}, {c}}, {{a}, {b, c}}, {{a}, {b}, {c}}}

Using ComapApply (new in 14.0)

ComapApply[{f}] /@ args


Using Query

Query[All, f] @ args


Both return

{f[{{a, b, c}}], f[{{a, b}, {c}}], f[{{a}, {b, c}}], f[{{a}, {b}, {c}}]}