Cleanest way to take a[b[c]] to a[b][c]
test = a[b[c[d]]];
Fold[
Construct, (* or Compose, see [1] *)
Level[test, {-1}, Heads -> True]
]
a[b][c][d]
[1] - Is there a name for #1@#2&?
Alternatively, thanks to OP and Mr.Wizard:
HeadCompose @@ Level[test, {-1}, Heads -> True]
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]
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.