# Cleanest way to take a[b[c]] to a[b][c]

As indicated in the title I'm looking for the fastest way to transform a[b[c]] into a[b][c], and the natural generalization to an arbitrary chaining of arguments. I'm sure there's got to be a convenient way that I've overlooked.

In my cases a, b, and c can be any expression with any complicated internal structure they like.

As an example, we could have some terrible deeply nested thing like:

bleh =
Nest[f, 10, 10]@
Nest[b, 100, 100]@Nest[c, RandomReal[{}, {1000, 1000}], 1000];


And then we can to convert this into:

blehm =
Nest[f, 10, 10][
Nest[b, 100, 100]][Nest[c, RandomReal[{}, {1000, 1000}], 1000]]

• The solution likely would use Operate. – QuantumDot Jan 23 '19 at 6:20
• f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result. – Shredderroy Jan 23 '19 at 6:29
• How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...? – David G. Stork Jan 23 '19 at 6:40
• @b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution. – David G. Stork Jan 23 '19 at 6:49
• If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to? – Kuba Jan 23 '19 at 9:14

Operate[#[[0]], First@#] &[a[b[c]]]


a[b][c]

ClearAll[deCompose]
deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

deCompose@a[b[c]]


a[b][c]

exp = Compose[a, b, c, d, e, f, g]


a[b[c[d[e[f[g]]]]]]

deCompose @ exp


a[b][c][d][e][f][g]

test = a[b[c[d]]];

Fold[
Construct,   (* or Compose, see [1] *)
]

a[b][c][d]


Alternatively, thanks to OP and Mr.Wizard:

HeadCompose @@ Level[test, {-1}, Heads -> True]

• No Operate, No # and no _, a clear winner here :P – Kuba Jan 23 '19 at 9:20
• Oh A+ that's slick – b3m2a1 Jan 23 '19 at 9:20
• One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True] – b3m2a1 Jan 23 '19 at 9:22
• @evanb Compose will do as well. – Kuba Jan 23 '19 at 9:37
• +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True] – WReach Jan 23 '19 at 22:49

This works on any level:

a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
(* a[b][c] *)

a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
(* a[b][c][d][e][f][g][h] *)


simpler syntax but same thing:

a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
(* a[b][c][d][e][f][g][h] *)


Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.

This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.

• For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation. – Roman Jan 23 '19 at 10:19
• Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c]. – march Jan 23 '19 at 16:51
• @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic. – Roman Jan 23 '19 at 17:47

Not particularly "clean," but it works:

Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


For the full generalization:

Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
a[b[c[d[e]]]]