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
    Jul 4, 2013 at 6:44
  • $\begingroup$ Apply[(f[##] g[##] + h[##]) &, {arguments}], crude version of what Mr. Wizard have showed. $\endgroup$
    – Kuba
    Jul 4, 2013 at 6:57
  • $\begingroup$ Ah, yes, that is what I want @VF1 $\endgroup$ 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
    Jul 4, 2013 at 7:00
  • $\begingroup$ This works great, thanks! $\endgroup$ 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
    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
    Jul 4, 2013 at 7:22
  • $\begingroup$ Will do. Thanks. $\endgroup$
    – VF1
    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
    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
    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$

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .