2

I am trying to avoid dealing with long explicit lists of variables.

What i do so far is the following:

VarList={x_, y_};
ParList={x, y};
ValList={2, 3};

What works

f[x_, y_] := x^2 + 3 y^3;
g[x_, y_] := 3 f[x, y];

f@@ValList
g@@ValList

Out[1]=85
Out[2]=255

Now what i would like to do but it does not work:

Clear[f, g];

f[Sequence@@VarList] := x^2 + 3 y^3;
g[Sequence@@VarList] := 3 f@@ParList;

f@@ValList
g@@ValList

Out[3]=85
Out[4]=3 (x^2 + 3 y^3)

How can I achieve numerical evaluation of g in the last step?

Edit:

Regarding the first solution by @kglr: The solution works as given but there are subtle issues that i want to describe here.

The suggestion is:

g[Sequence @@ VarList] := Evaluate[3 f @@ ParList];
g @@ ValList

255

This works. However,

g[Sequence @@ VarList] := 3 Evaluate[ f @@ ParList];
g @@ ValList

3 (x^2 + 3 y^3)

Does not. Also, it does not seem to work for more complicated constructs. Concretely i wanted to use something along

g[Sequence @@ VarList] := Evaluate[ArrayFlatten[{{SparseArray[{{f @@ ParList}}]}}]];
g @@ ValList //MatrixForm

(x^2+3 y^3)

Does not work. To finally make my confusion complete, note that the last expression works again, if i drop both of the outer pair of curly brackets. That is

g[Sequence @@ VarList] := Evaluate[ArrayFlatten[SparseArray[{{f @@ ParList}}]]];
g @@ ValList //MatrixForm

(85)

works again. Do you undestand this strange behavior?

R. Funden
  • 23
  • 3

3 Answers3

1
  1. Because Mathematica functions are really pattern-matching, it's possible to simplify the function definition by making f and g take a list of parameters as input:
VarList={x_, y_};
ParList={x, y};
ValList={2, 3};

f[VarList] := x^2 + 3 y^3;
g[VarList] := Evaluate[3 f@ParList]

Print@ f[ValList]
Print@ g[ValList]

Try it online!

That way you use f[{2, 3}] or f@{2, 3} to call it.

  1. Pattern (:) can be used:
VarList=ParList:{x_,y_};
ValList={2, 3};

f[VarList] := x^2 + 3 y^3;
g[VarList] := 3 f@ParList

Print@ f[ValList]
Print@ g[ValList]

Try it online!

Explanation: The definition of f and g expands to

f[ParList:{x_,y_}] := x^2 + 3 y^3;
g[ParList:{x_,y_}] := 3 f@ParList

This also makes Evaluate unnecessary. It may be undesirable to use Evaluate, for example:

ParList={x};

f[ParList:{x_}] := Simplify@x;
g[{x_}] := Evaluate[f@ParList];

Print@ f@{a*b+a*c+a*d+a*e}
Print@ g@{a*b+a*c+a*d+a*e}

Try it online!

user202729
  • 502
  • 3
  • 11
  • I find that this solution is superior to the others because it spares the Evaluate and i really only want to evaluate the code in the very last step for reasons of runtime. Nevertheless, before i accept the answer let me ask one thing: After implementing your solution my code takes roughly ~3 times as much time as before, which is undesirable. The evaluate is gone, so what takes extra time here? Isn't there a way to make it run as fast as before. I mean in the end all what i ask for is just a nicer optical appearance of my code without lengthy list of parameters everywhere. Thanks. – R. Funden Jul 19 '18 at 18:27
  • I am sorry this was my mistake, your code works just fine, without any loss of speed! (I had overlooked some instances of Evaluate which were in place after i tried to implement the solution of @kglr above.). Thanks. – R. Funden Jul 19 '18 at 18:42
1

I prefer user202729's alternative using Pattern but adhering to your original specification your goal can be achieved with a method from Injecting a sequence of expressions into a held expression:

VarList = {x_, y_};
ParList = {x, y};
ValList = {2, 3};

{VarList, ParList} /. {{var__}, {par__}} :> 
  (
   f[var] := x^2 + 3 y^3;
   g[var] := 3 f[par];
  )

g @@ ValList
255
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
0
  1. Don't do this.
  2. g[Sequence @@ VarList] = 3 f @@ ParList;
Alan
  • 13,686
  • 19
  • 38