How to replace the first Head of a currying expression like "a" in a[b,c][d]?
y = a[b, c][d];
y[[0, 0]] = w;
y
(* w[b, c][d] *)
For arbitrarily nested heads I would use recursion and pattern matching, like this:
ClearAll[replaceFirstHead]
replaceFirstHead[head_[body___], newHead_] := replaceFirstHead[head, newHead][body]
replaceFirstHead[head_, newHead_] := newHead
replaceFirstHead[a[1][2][3][4, 5, 6], x]
(* x[1][2][3][4, 5, 6] *)
There is no need to test for _Symbol
or _?AtomQ
on the head but the order of definitions is critical.
I find this paradigm very natural for Mathematica. Pattern matching and multiple definitions are often more convenient than explicit If
and explicit extraction or structure manipulation (Part
, Head
, ReplacePart
, etc.)
As @Itai notes in the comments, this function will replace atomic expressions, e.g.
replaceFirstHead[1, x]
Whether this is desirable or not depends on the particular applications. The following wrapper can prevent this for atoms that cannot be decomposed into a head and arguments using pattern matching:
replaceFirstHead2[arg : _[___], newHead_] := replaceFirstHead[arg, newHead]
replaceFirstHead2[arg_, newHead_] := arg
Do keep in mind though that some atoms act as if they were compound in some pattern matching operations. The basic examples are Rational
and Complex
. Thus:
replaceFirstHead2[1/2, h]
(* h[1, 2] *)
replaceFirstHead2[I, h]
(* h[0, 1] *)
Other atoms cannot be decomposed by pattern matching, even though their InputForm
appears compound. One example is Graph
:
replaceFirstHead2[ Graph[{1 <-> 2}], h ]
(* output: unchanged graph *)
When dealing with atoms in Mathematica, there are no consistent rules. Therefore it is hard to make a clear decision about what should be considered the "correct behaviour". It is best to think about the particular way that this function will be used, and consider special cases.
The following wrapper simply prevents it from operating on any atom, but may not be the best solution for all applications:
replaceFirstHead3[atom_?AtomQ, newHead_] := atom
replaceFirstHead3[compound_, newHead_] := replaceFirstHead[compound, newHead]
One can use Operate[]
with Apply[]
:
Operate[w @@ # &, a[b, c][d]]
(* w[b, c][d] *)
Or leave out Apply
and write:
Operate[w &, a[b, c][d], 2]
(* w[b, c][d] *)
With deeper expressions:
Operate[w &, a[b][c][d], 3]
(* w[b][c][d] *)