2
$\begingroup$

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?

$\endgroup$
1
$\begingroup$
  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!

$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – R. Funden Jul 19 '18 at 18:27
  • $\begingroup$ 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. $\endgroup$ – R. Funden Jul 19 '18 at 18:42
1
$\begingroup$

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
$\endgroup$
0
$\begingroup$
  1. Don't do this.
  2. g[Sequence @@ VarList] = 3 f @@ ParList;
$\endgroup$

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.