As mentioned by @xzczd, one possibility that can work in some conditions is to use Inactivate
which works very well when there are certain explicit terms that need not be expanded, but it doesn't work terribly well with implicit terms (such as f
within g
as it isn't inactivated). It is possible to use Block[{f = Inactive[f]}, ...]
, but it still requires knowing the expansion.
I've managed to find another solution (for my use case) by manipulating the up and down values.
Consider the following base definitions:
const /: N[const] = 1 / Pi^2;
f[x_?InexactNumberQ] := const / x^2;
g /: N[g[x_]] := Pi * Sqrt[f[x]] * x^2;
Attributes[ExpandValues] = {HoldAll};
ExpandValues[symbol_] := Join @@ Through[
{OwnValues, DownValues, UpValues, SubValues, DefaultValues, NValues}[symbol]
] /. {
InexactNumberQ :> (True &),
HoldPattern[N[f_, __]] :> f
}
ExpandValues[symbol_, symbols__] := Join[ExpandValues[symbol], ExpandValues[symbols]]
The definition of ExpandValues
function looks at the symbol's values to create a list of replacement, and the left hand side of the rules so they can be applied more broadly (for example, but replacing N[f[x_]]
with just f[x_]
and removing checks for inexact numbers).
Here are some examples of it being used:
g[x] /. ExpandValues[g]
Pi x^2 Sqrt[f[x]]
g[x] / f[x] //. ExpandValues[g]
Pi x^2 / Sqrt[f[x]]
g[x] / f[x] //. ExpandValues[g, f]
Pi Sqrt[const / x^2] x^4 / const
Inactivate
?:Inactivate[g[x]/f[x], f] // N
$\endgroup$ – xzczd Sep 8 '20 at 6:13g[x]
contains a number of other functions which I don't want expanded? It then becomes a bit more difficult to useInactivate
(especially if I don't know a priori what functions went into definingg[x]
). $\endgroup$ – JP-Ellis Sep 9 '20 at 4:09Inactivate
all possible head that you don't want to expand? You may want to read the Scope section of document ofInactivate
. $\endgroup$ – xzczd Sep 9 '20 at 4:39Inactivate[..., Except[g]]
would work. If you want to post that as the answer? $\endgroup$ – JP-Ellis Sep 9 '20 at 12:22