11
$\begingroup$

Is there an easy way to combine pure functions into a single pure function? For example, say I have

f = #1^2 &;
g = #1 - 2 &;

and I want to define a new pure function h that is the difference of the two functions (as currently defined, so that h will not change if f or g are redefined). h = f - g doesn't work because it doesn't combine them into a single function. The best I've been able to come up with is

h = Evaluate[f@# - g@#] &

but this seems a bit hack-ish. Is there a more natural way to combine them?

Edit: I was looking for something where Mathematica performs its automatic simplifications, just as if we'd had f = x^2; g = x - 2; h = f - g, but for pure functions.

$\endgroup$
  • $\begingroup$ Why not simply #1^2 + #1 - 2 & ? And see mathematica.stackexchange.com/questions/33112/… $\endgroup$ – David G. Stork Apr 7 '17 at 1:43
  • $\begingroup$ @DavidG.Stork Well of course if the functions are known and this short, then you can just define the combined function manually. But I want to be able to handle the case where the functions are unknown and/or extremely complicated. $\endgroup$ – tparker Apr 7 '17 at 2:03
  • $\begingroup$ h = f@# + g@# &? $\endgroup$ – wxffles Apr 7 '17 at 2:05
  • 3
    $\begingroup$ Wanting h to not be affected by later changes to f and g is an important point you should put in the question. $\endgroup$ – wxffles Apr 7 '17 at 2:24
  • 5
    $\begingroup$ Related: Distributing function arguments with function compositions $\endgroup$ – jkuczm Apr 7 '17 at 9:55
5
$\begingroup$

This is a solution for the simplest case.

Not meant to prevent evaluation (except of the components' functions bodies).

It only works with expressions with slots & kind of pure functions etc. So it won't merge named arguments or resolve attributes from Function.

mergeF[expr_] := Function @@ (Hold[expr] /. Function[body_] :> body)

  (* or Replace[Function[expr], Function[body_] :> body, {1, -1}]*)

mergeF[(f - g)/Exp[g]]

enter image description here

If don't need to care at all you can drop Hold.

$\endgroup$
3
$\begingroup$

Use With:

h = With[{f = f, g = g},  f[#] - g[#] &]
$\endgroup$
  • $\begingroup$ It will work but it is not the same as OP's h $\endgroup$ – Kuba Apr 7 '17 at 13:06
  • $\begingroup$ @Kuba I'm not sure what you mean. His use of Evaluate accomplishes nothing, but the use of With achieves what he was asking for (i.e., eliminates the appearance of f and g in the own values of h, as he requested in his comments). $\endgroup$ – Alan Apr 7 '17 at 15:40
  • 1
    $\begingroup$ I'm not sure what do you mean too :) this is what OP's h is: 2 - #1 + #1^2 & and this is what is yours: (#1^2 &)[#1] - (#1 - 2 &)[#1] &. Of course Evaluate does its job there. $\endgroup$ – Kuba Apr 7 '17 at 15:46
  • $\begingroup$ @Kuba On Evaluate: right, I see what he did. (I had thought he evaluated the function expression, not just the argument.) On the difference: does it make a difference? Hmm, I suppose Evaluate could lead to simplifications, avoiding the need to recompute them every call. So then, was using Evaluate that way a good solution after all? I thought using With was the standard answer. $\endgroup$ – Alan Apr 7 '17 at 16:34
  • $\begingroup$ I wouldn't say one way is better than another unless OP narrows the case. As you noticed your solution prevents simplifications/evaluation, which is reasonable choice. $\endgroup$ – Kuba Apr 7 '17 at 16:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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