I'd like to assign an "UpUpValue" in a way generalized to any nested head surrounding the value for which the UpUpValue would be defined. That is, if a function h[x]
is called and it is nested within another two functions f[g[h[x]]]
, I'd like it to have a specific behavior generalizable to any head g
.
I had thought this would work:
h /: f[g_[h[x_]]] := (f[x] + g[x] + h[x])
However, TagSetDelayed
is limited to 2nd level specification (such that it returns that "TagSetDelayed::tagpos : "Tag h in f[g_[h[x_]]] is too deep for an assigned rule to be found."). I then tried bypassing this by defining it manually using:
UpValues[g] = {HoldPattern[f[h_[g[x]]]] :> HoldPattern[f[x] + h[x] + g[x]]}
However, it seems this does not fire successfully.
The following using UpSetDelayed
also doesn't work:
f[g_[h[x_]]] ^:= (f[x] + g[x] + h[x])
As this seeks to apply the rule to specific heads only (not general g
that can be used on the RHS).
Can anyone conceive of a way to accomplish this in a way that preserves generality in the head of g
? For any single function g
, I could simply define an UpValue or DownValue, but I would like to do so in a general way such that it is applied to any function g
when it is fed the head h
.
Clarification on SetDelayed:
xzczd pointed out that the following would work in principal:
f[g_[h[x_]]] := (f[x] + g[x] + h[x])
However, this associates a DownValue
with the symbol f
. DownValues are checked exhaustively upon calling a function, such that making many additions to DownValues of a function f
that is called many times can become inefficient when compared to making UpValues
(or "UpUpValues") associated with a more rarely used function h
.
For example, if you wanted to define special handling for 1000 different functions sitting in h
's position, this would define 1000 different DownValues of f
that must be checked each time f
is called, rather than one "UpUpValue" for each unique function sitting in h
's spot.
f[g_[h[x_]]] ^:= (f[x] + g[x] + h[x])
doesn't work (and it's expected). 2. Why not simplyf[g_[h[x_]]] := (f[x] + g[x] + h[x])
? $\endgroup$step
function to do one evaluation step at a time, and then apply some additional rules each time before doing the next "normal" step $\endgroup$h
such that it does not populate the list of Downvalues forf
, which would slow down very large development projects for whichf
might be called many, many times whereash
is only called rarely. This is an important enough point I will edit the main blog post to avoid confusion, because I too felt my request foolish for a minute after seeing your response. $\endgroup$