15
$\begingroup$

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?

$\endgroup$
3
  • $\begingroup$ 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}]? $\endgroup$
    – VF1
    Commented Jul 4, 2013 at 6:44
  • $\begingroup$ Apply[(f[##] g[##] + h[##]) &, {arguments}], crude version of what Mr. Wizard have showed. $\endgroup$
    – Kuba
    Commented Jul 4, 2013 at 6:57
  • $\begingroup$ Ah, yes, that is what I want @VF1 $\endgroup$ Commented Jul 4, 2013 at 7:03

3 Answers 3

13
$\begingroup$

Edit:

Mr.Wizard helped to refine my old function to:

SetAttributes[Through2, HoldFirst]
Through2[head_[args___]] := Replace[head, s : _Function | _Symbol :> s[args], -1]

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[{head = Head@expr, arg = First@expr}, 
  With[{funcs = Cases[head, _Function | _Symbol, -1]}, 
   head /. Thread[funcs -> Through[funcs[arg]]]]]
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]} *)
$\endgroup$
2
  • $\begingroup$ Interesting interpretation. +1 I still wonder what the OP actually wants however. $\endgroup$
    – Mr.Wizard
    Commented Jul 4, 2013 at 7:00
  • $\begingroup$ This works great, thanks! $\endgroup$ Commented Jul 4, 2013 at 8:07
7
$\begingroup$

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`".

$\endgroup$
11
  • $\begingroup$ 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. $\endgroup$
    – VF1
    Commented Jul 4, 2013 at 7:13
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Jul 4, 2013 at 7:22
  • $\begingroup$ Will do. Thanks. $\endgroup$
    – VF1
    Commented Jul 4, 2013 at 7:24
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Jul 4, 2013 at 7:26
  • $\begingroup$ 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? $\endgroup$
    – Kuba
    Commented Jul 4, 2013 at 7:29
0
$\begingroup$

For example...

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

Using substitution rule...

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

Gives...

54-Sqrt[3]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.