Here is my approach built on RightComposition
, Through
and Curry
.
myOp=Curry[FixedPoint,{1,2}][Through@*{Head,Apply[List]/*Sow}/*First]/*Reap/*(#[[2,1,;;-3]]&)/*Total
myOp @ f[a, b][c, d]
(* Out[]= {a + c, b + d} *)
Where does it come from?
First we define helper operators pipe
and branch
:
pipe = RightComposition;
branch = Through @* {##} &;
pipe
is just an alias of RightComposition
for faster typing.
branch
will be used to distribute functions to arguments. e.g.
branch[f, g, h] @ a
(* Out[]= {f[a], g[a], h[a]} *)
branch[f, g, h] @@ {a, b}
(* Out[]= {f[a, b], g[a, b], h[a, b]} *)
branch[F, G, H] @@@ {{a, b}, {c, d, e}}
(* Out[]= {{F[a, b], G[a, b], H[a, b]}, {F[c, d, e], G[c, d, e], H[c, d, e]}} *)
Now we can define our desired operator as following:
myOp = pipe[
branch[Head, pipe[Apply@List, Sow]] /* First // Curry[FixedPoint, {1, 2}]
, Reap, #[[2, 1, ;; -3]] &, Total
]
(* Out[]= Curry[FixedPoint, {1, 2}][(Through@*{Head, Apply[List] /* Sow}) /*
First] /* Reap /* (#1[[2, 1, 1 ;; -3]] &) /* Total *)
Generate a lengthy example expression:
testExpr = 5 // pipe[
Range
, Map@branch[x, y]
, Fold[Apply, F, #] &
]
(* Out[]= F[x[1], y[1]][x[2], y[2]][x[3], y[3]][x[4], y[4]][x[5], y[5]] *)
Using myOp
on testExpr
gives desired result:
testExpr // myOp
(* Out[]= {x[1] + x[2] + x[3] + x[4] + x[5], y[1] + y[2] + y[3] + y[4] + y[5]} *)