7

I have a list of variables variables={a,b} and a list with values values={1,2}. I'd like to define a function using the variables in variables like so:

f=Function[variables,2a+b];

Then, I'd like to call it in a way like

result=f@@values  

or

result=f@@variables/.(Rule@@@Transpose@{variables,values})

or something similar.

Is there a way to create a function where the names of the variables are in a given list?

Ragnar
  • 173
  • 1
  • 6

2 Answers2

4

Taking the question at face value you merely need to add Evaluate:

variables = {a, b};
values = {1, 2};

f = Function[Evaluate @ variables, 2 a + b];
f @@ values
4

However, I recommend that you keep the Symbols in a Hold expression rather than a List to prevent unwanted evaluation. You will then need something like this to "inject" those values into the Function:

{a, b} = {"fail!", "fail!"}; (* prove it works even with a and b assigned *)

variables = Hold[a, b];
values = {1, 2};

f = variables /. _[vars__] :> Function[{vars}, 2 a + b];
f @@ values
4
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Nice solution! I just got the solution of the other answer to work, so I won't change it now. What exactly is the pattern _[vars__]? (I suppose _[] matches the Hold[], and __ for the list of variables, because we want the whole list, not just one element.) – Ragnar Jan 14 '14 at 21:44
  • 1
    @Ragnar vars__ is a pattern that represents an arbitrary sequence of expression named vars (see BlankSequence in the docs) -- it matches a, b in Hold[a, b]. This sequence is then inserted in the place of vars on the right-hand-side of :> (SetDelayed), forming Function[{a, b}, . . .]. See this for another example. – Mr.Wizard Jan 14 '14 at 21:49
1

Perhaps something like this?

ClearAll[def];
Attributes[def]={HoldAll};
def[f_Symbol,vars_List,body_] := With[{x=vars}, f = Function[vars,body]];

used as follows:

def[f, {a, b}, a + b]

to define the function f:

f @@ {1, 2}

3

user8074
  • 1,592
  • 8
  • 7
  • That's a lot of stuff I don't know yet :) Let's test it... – Ragnar Jan 14 '14 at 20:56
  • It works when I remove the HoldAll line. Otherwise, I can't use v={a,b} as the second argument, because it will still be interpreted as a symbol instead of a list of symbols. Thanks! – Ragnar Jan 14 '14 at 21:04
  • 1
    You can read the reply by Leonid Shifrin to this post: Pure Functions with Lists as arguments, which contains much better material than mine – user8074 Jan 14 '14 at 21:14
  • Thanks for the link, but I like your solution better, because it doesn't involve in-depth programming (and I have to show my code to my teachers, who wouldn't understand it easily I guess). Also, I changed HoldAll to HoldFirst, and added another definition, where f is not a symbol, which clears it before assignment. – Ragnar Jan 14 '14 at 21:22