# Using Through to evaluate complex expressions

Suppose we're given the expression f*g+h, where f,g,h are all pure functions. How can we evaluate this expression on some x? If there were only one operation, say f+g, we could simply use Through[(f+g)[x]], but Through only deals with one operation, as far as I can see. How is this done?

-
To clarify, you are asking for through to apply the pure functions at the most nested level to x? Your example is Plus[Times[f,g],h], so the functions you want applied to x are Level[f*g + h, {-1}]? –  VF1 Jul 4 '13 at 6:44
Apply[(f[##] g[##] + h[##]) &, {arguments}], crude version of what Mr. Wizard have showed. –  Kuba Jul 4 '13 at 6:57
Ah, yes, that is what I want @VF1 –  Nilay Kumar Jul 4 '13 at 7:03

Edit:

Mr.Wizard helped to refine my old function to:

SetAttributes[Through2, HoldFirst]

This locates the most nested functions and symbols and evaluates their value for the parameter arguments.

Below is my older, less robust function:

SetAttributes[Through2, HoldFirst]
Through2[expr_] :=
With[{funcs = Cases[head, _Function | _Symbol, -1]},
Through2[(f*g + h)[x]]
(* f[x] g[x] + h[x] *)
Through2[(f*g + (h*Minus)^2)[x]]
(* f[x] g[x] + x^2 h[x]^2 *)
Through2[{Re, Im + Re}[x]]
(* {Re[x], Im[x] + Re[x]} *)
-
Interesting interpretation. +1 I still wonder what the OP actually wants however. –  Mr.Wizard Jul 4 '13 at 7:00
This works great, thanks! –  Nilay Kumar Jul 4 '13 at 8:07

Perhaps you want something like this?

apply = (# /. s_Symbol /; Context[s] =!= "System" :> s[##2]) &;

apply[f*g + h, x]
f[x] g[x] + h[x]

This is a limited implementation but it can be extended if this is in fact the kind of operation you desire. The idea is to recognize any Symbol not belonging to the System context as a function to apply to x. Alternatively one could apply only symbols in the Global context using Context[s] === "Global".

-
Yes, I'd say that our functions do the same thing (with yours being more elegant and direct). In hindsight, Cases and then ReplaceAll does seem a bit redundant - and dangerous, too, if one of the pure functions is used on a higher level in the expression. Your solution will be more robust. –  VF1 Jul 4 '13 at 7:13
@VF1 Thanks for the check. If you'd like to put this in your answer instead that's fine with me; it was your idea to look at the levelspec. –  Mr.Wizard Jul 4 '13 at 7:22
Will do. Thanks. –  VF1 Jul 4 '13 at 7:24
@VF1 It just occurred to me that my {-1} code is broken for Function as that will not be found at level {-1}; Please use the Heads -> False code, assuming that isn't broken. –  Mr.Wizard Jul 4 '13 at 7:26
Is there a difference between Yours apply and @VF1 's Through2 exept that the latter works for 1 argument only (after edit it works for many) and Yours can not handle Minus and other System context functions? –  Kuba Jul 4 '13 at 7:29

For example...

f=#&;
g=2#^2&;
h=-Sqrt[#]&;

Using substitution rule...

f*g+h /. z:(f|g|h)->z[3]

Gives...

54-Sqrt[3]
-