3
$\begingroup$

I'm having a problem concerning function addition. The following code shows an example that illustrates my problem. I had this list of functions that have the same variable. I had them by using the Total function and declared a function of that variable equal to the Total[list], like in this example:

f1[x_] := 2 x + 1;
f2[x_] := x;
f3[x_] = 4 x;
l1 = List[f1[x], f2[x], f3[x]];
o[x_] := Total[l1];
o[1]

The output of o[1] was 1+7x, instead of 8, which is what I want. Any suggestion on how to approach this problem? Thank you

$\endgroup$
4
  • $\begingroup$ If you do this, you'll get 8 f1[x_] := 2 x + 1; f2[x_] := x; f3[x_] = 4 x; l1[x_] := List[f1[x], f2[x], f3[x]]; o[x_] := Total[l1[x]]; o[1] $\endgroup$
    – Nasser
    Oct 7, 2017 at 19:32
  • 4
    $\begingroup$ On top of what @Nasser gave you, the issue with your code has to do with how variables are scoped. The x_ parameter is scoped differently from the x symbol you provide in l1. So you could also mostly keep your code but replace o with this: o[v_] := Total[l1] /. x -> v $\endgroup$
    – b3m2a1
    Oct 7, 2017 at 19:33
  • 1
    $\begingroup$ Or include Evaluate in definition of o[x_], i.e., o[x_] := Evaluate@Total[l1]; $\endgroup$
    – Bob Hanlon
    Oct 7, 2017 at 20:03
  • 1
    $\begingroup$ @BobHanlon There is a shortcut for the combination of SetDelayed and Evaluate! $\endgroup$
    – Roman
    Dec 22, 2022 at 9:04

2 Answers 2

4
$\begingroup$

Try this (as a side note, when defining functions using SetDelayed one doesn't have to include the semi-colon at the end of the line).

f1[x_] := 2 x + 1
f2[x_] := x
f3[x_] := 4 x

Use SetDelayed (i.e., :=) again to defrine l1

l1[x_] := List[f1[x], f2[x], f3[x]]

Inside the defintion for o use l1 with an argument

o[x_] := Total[l1[x]]

Then test

o[1]
(* 8 *)

o[2]
(* 15 *)

This is similar but not quite identical to what Nasser wrote in his comment.

$\endgroup$
2
  • $\begingroup$ Is it possible to get a specific element of the l1 list, now that it is a list of functions? $\endgroup$
    – RicardoP
    Oct 7, 2017 at 23:30
  • $\begingroup$ l1[x][[2]] would, for example, get element 2 $\endgroup$ Oct 8, 2017 at 2:52
4
$\begingroup$

My new resource function ThroughOperator can do this:

f1[x_] := 2 x + 1;
f2[x_] := x;
f3[x_] := 4 x;
o = ResourceFunction["ThroughOperator"][f1 + f2 + f3];
o /@ Range[5]

{8, 15, 22, 29, 36}

If you have a list of functions or if somehow the expression f1 + f2 + f3 evaluates to something else inside of ResourceFunction["ThroughOperator"], you can also use:

list = {f1, f2, f3};
o = ResourceFunction["ThroughOperator"][list, Plus];
o /@ Range[5]
$\endgroup$
3
  • $\begingroup$ Nice answer! What 's the advantage of this ResourceFunction compared to a list of pure functions {f1,f2,f3} and Total@Through[{f1, f2, f3}[5]]? $\endgroup$ Dec 23, 2022 at 15:20
  • $\begingroup$ @UlrichNeumann Through[{f1, f2, f3}[5]] is annoying to map over lists, which is one of the main motivations I made ThroughOperator. Another reason is that Through[h[f1, f2][x]] sometimes suffers from order-of-evaluation issues that are difficult to circumvent. $\endgroup$ Jan 9, 2023 at 10:47
  • $\begingroup$ Thank you for your explanation! $\endgroup$ Jan 9, 2023 at 10:56

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.