I sometimes want to apply a linear combination of functions to an argument. This can be more difficult if the linear combinations are generated by code, so that rewriting them some form to make Through
convenient is difficult. So I usually use a utility like the following:
linearThrough[(Optional[a_?NumericQ] f_ + Optional[b_?NumericQ] g_)[x__]] :=
a f[x] + b g[x];
OP's example:
linearThrough[(f - g)[x]]
(* f[x] - g[x] *)
You can also use Subtract
if you prevent it from evaluating to Plus[f, Times[-1, g]]
prematurely:
Through[Unevaluated@Subtract[f, g][x]]
(* f[x] - g[x] *)
Since I somewhat broadened the scope by bring in linear combinations of functions, here is a similar utility, in which the linear operators are specified as a argument, everything else is assumed to be constant:
linearOperate[heads_List][comb_[x__]] :=
(comb /. F : Alternatives @@ heads :> F[x]) /;
Internal`LinearQ[comb, heads] || FreeQ[comb, Alternatives @@ heads];
Examples:
linearOperate[{f, g}][(f - g)[x]]
(* f[x] - g[x] *)
linearOperate[{f, g, h}][(a f - g + h - b + 9)[x]]
(* 9 - b + a f[x] - g[x] + h[x] *)
linearOperate[{f, g, h}][(a f)[x]]
(* a f[x] *)
linearOperate[{f, g, h}][(3)[x]]
(* 3 *)
This last example is the reason for the extra test, ... || FreeQ[comb, Alternatives @@ heads]
: Internal`LinearQ
says a constant is not linear:
Internal`LinearQ[3, {f, g, h}]
(* False *)
SetDelayed (:=)
instead ofSet (=)
when definingf
andg
(i.e.,ClearAll[f, g]; f[x_]:= x
andg[x_]:= x^2
) if you wantThrough[(f + g)[z]]
to givez+z^2
(notf[z]+g[z]
). $\endgroup$SetDelayed(:=)
andSet(=)
in this case. I understand general definitions ofSetDelayed(:=)
andSet(=)
$\endgroup$