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$
10
  • $\begingroup$ Why not simply #1^2 + #1 - 2 & ? And see mathematica.stackexchange.com/questions/33112/… $\endgroup$ Apr 7, 2017 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, 2017 at 2:03
  • $\begingroup$ h = f@# + g@# &? $\endgroup$
    – wxffles
    Apr 7, 2017 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, 2017 at 2:24
  • 5
    $\begingroup$ Related: Distributing function arguments with function compositions $\endgroup$
    – jkuczm
    Apr 7, 2017 at 9:55

2 Answers 2

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$
0
3
$\begingroup$

Use With:

h = With[{f = f, g = g},  f[#] - g[#] &]
$\endgroup$
6
  • $\begingroup$ It will work but it is not the same as OP's h $\endgroup$
    – Kuba
    Apr 7, 2017 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, 2017 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, 2017 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, 2017 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, 2017 at 16:36

Your Answer

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

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