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?
Asked
Active
Viewed 462 times
15
Kuba
- 136,707
- 13
- 279
- 740
Nilay Kumar
- 253
- 1
- 6
3 Answers
13
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]} *)
VF1
- 4,702
- 23
- 31
-
Interesting interpretation. +1 I still wonder what the OP actually wants however. – Mr.Wizard Jul 04 '13 at 07:00
-
7
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`".
Mr.Wizard
- 271,378
- 34
- 587
- 1,371
-
Yes, I'd say that our functions do the same thing (with yours being more elegant and direct). In hindsight,
Casesand thenReplaceAlldoes 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 04 '13 at 07: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 04 '13 at 07:22
-
-
@VF1 It just occurred to me that my
{-1}code is broken forFunctionas that will not be found at level{-1}; Please use theHeads -> Falsecode, assuming that isn't broken. – Mr.Wizard Jul 04 '13 at 07:26 -
Is there a difference between Yours
applyand @VF1 'sThrough2exept that the latter works for 1 argument only (after edit it works for many) and Yours can not handleMinusand otherSystemcontext functions? – Kuba Jul 04 '13 at 07:29 -
Heads->Falsedidn't work either on examples such asThrough2[{#1 &, Im}[x]], unfortunately, asFunctionis a head. However, using the "relative" level of-1instead of{-1}seems to be a fix. – VF1 Jul 04 '13 at 07:32 -
@Kuba Indeed, but as Mr.Wizard mentions in his answer, the context can be changed. – VF1 Jul 04 '13 at 07:45
-
@VF1 "Indeed" implies "there is a difference" other than those I've mentioned. Sorry for catching the words but I want to be sure :) – Kuba Jul 04 '13 at 07:50
-
@VF1 I was not thinking very well; of course
Heads -> Falseis the default forReplace. By the way I meant use the version with-1rather than{-1}, just as you did. I'm now deleting that section of my answer. – Mr.Wizard Jul 04 '13 at 10:03 -
@Kuba Referring to the code presently in both answers, they are entirely different approaches. Mine works based on the idea that active functions can be referenced by context, whereas VF1's method works by recognizing any Symbol (or
Function) that does not itself have arguments. Arguably both are useful. – Mr.Wizard Jul 04 '13 at 10:07 -
@Mr.Wizard I have asked a vague question, I know that aproaches differ. I meant, are there others differences in effect/application of those two? – Kuba Jul 04 '13 at 10:10
0
For example...
f=#&;
g=2#^2&;
h=-Sqrt[#]&;
Using substitution rule...
f*g+h /. z:(f|g|h)->z[3]
Gives...
54-Sqrt[3]
Ymareth
- 4,741
- 20
- 28
x? Your example isPlus[Times[f,g],h], so the functions you want applied to x areLevel[f*g + h, {-1}]? – VF1 Jul 04 '13 at 06:44Apply[(f[##] g[##] + h[##]) &, {arguments}], crude version of what Mr. Wizard have showed. – Kuba Jul 04 '13 at 06:57