How to create functions of arbitrary number of variables?


In the following code what would be the simplest way to generalize it to say some $N_f$ number of $z$ instead of just $z_1$ and $z_2$?

$Assumptions = {1 > y > 0, 1 > z1 > 0, 1 > z2 > 0}; 
Nmax = 40; 
LnMT1 = -Sum[Log[1 - (1/(1 + x^n)) (x^(n/2) (y^(n/2) + z1^n + z2^n) + 
   x^(n/2) (y^(-n/2) + z1^(-n) + z2^(-n)))], {n, 1, Nmax}]; 
LnMT2 = Sum[(1/n) (Sum[x^(k*(n/2))*Subscript[f, k][y, z1, z2, n], 
   {k, 1, Nmax}]/(1 - x^(2*n))), {n, 1, Nmax}]; 

For[i = 1, i <= Nmax, i++, 
  temp[y_, z1_, z2_] = Simplify[Solve[SeriesCoefficient[LnMT1 - LnMT2, {x, 0, i/2}] == 0, 
     Subscript[f, i][y, z1, z2, 1]][[1, 1, 2]]]; 
  Print["coefficient of ", x^{i/2}, " = ", Expand[Simplify[temp[y, z1, z2]]]]; 
  Subscript[f, i][y_, z1_, z2_, n_] = temp[y^n, z1^n, z2^n]
  • I guess the places where there is a sum over the nth powers of z1 and z2, they canbe replaced by Sum[z[j]^n, {j, 1, Nf}] but the problem is with the "functions" "temp" and $f_i$ which will need to handle $N_f$ number of variables. I tried defining expressions like, g[Table[z[i], {i, 1, Nf}]] = Sum[z[j]^2, {j, 1, Nf}] but I couldn't do anything with them. And I anyway don't know how to define a function of $N_f$ variables. ( can't pass values to the above $g$...and in the above code one would want to even functionally update $f_i$ as in the last line of the loop.

  • Also in the "Print" line when I am printing out the evaluated expression for temp often I want to print the value of temp with one or more of its variables (y and z) being set to 1. If the above code can be generalized to arbitrary number of z then how would this setting to one be done then?

Note: in all of it I am assuming that at the start there will be a new line declaring the value of $N_f$ to be used as is being done now for Nmax


Posted 2012-12-13T02:23:42.953

Reputation: 1 091

Question was closed 2013-08-16T18:01:26.723

3You code cannot be executed by copy&paste. Can you please recheck it and reduce it to the smallest possible part which still shows your behavior? – halirutan – 2012-12-13T02:50:20.613

I again converted the code into "InputForm" and pasted it. I have checked that it works. – user6818 – 2012-12-13T03:10:05.870



When you define a function, you use Blank to match exactly one expression. Therefore z1_ stands for match one parameter. As you might have seen, we have BlankSequence (__) and BlankNullSequence (___) too. The former matches one or more expressions, while the latter matches zero, one or more expressions. Therefore, you can define a function like

f[z__] := {z}


to match as many parameters as you like. You can of course do something with the parameters

g[z__] := Sum[Sqrt[elm], {elm, {z}}]
(* Sqrt[a]+Sqrt[b]+Sqrt[c]+Sqrt[d] *)

You may now say *but I cannot access single z1 for instance. First, yes you can

h[y__] := With[{z = {y}}, z[[1]] + z[[5]]]
h[a, b, c, d, e]
(* a + e *)

but secondly, what would be the use of this? When I access z[[5]], the function is not general anymore, because I expect always at least 5 parameters.


Posted 2012-12-13T02:23:42.953

Reputation: 109 574

Didn't understand how your answer corresponds to my question. Now I can define 2 variable functions like $f[z1_,z2_] := $ and I can manually keep increasing it by adding extra zs through the code by hand. What I want to do is to define $f$ such that it is a function of $Nf$ zs and be able to set the value of Nf at the beginning. – user6818 – 2012-12-13T03:12:33.843

@user6818 Can you come to chat?

– halirutan – 2012-12-13T03:37:25.917

yes I am logged into chat – user6818 – 2012-12-13T03:59:28.773


Perhaps you can use Repeated?

A function with five arguments:

  h[z : Repeated[_, {5}]] := Plus @@ {z}
  {h[1], h[1, 2, 3, 4, 5], h[a, b, c, d, e], h[1, 2, 3, 4, 5, 6, a]}
  (* {h[1],15,a+b+c+d+e,h[1,2,3,4,5,6,a]} *)

another example with five arguments:

   h2[z : Repeated[_, {5}]] := {z}[[2]] + {z}[[3]]
   {h2[1], h2[1, 2, 3, 4, 5], h2[a, b, c, d, e], h2[1, 2, 3, 4, 5, 6, a]}
   (* {h2[1],5,b+c,h2[1,2,3,4,5,6,a]}  *)

Another alternative is to use Condition

  ClearAll[h3, h4, h5];
  mm = 5;
  h3[z___ /; Length[{z}] == mm] := Max[z]
  h4[z___] /; Length[{z}] == mm := Max[z]
  h5[z___] := Max[z] /; Length[{z}] == mm


Posted 2012-12-13T02:23:42.953

Reputation: 302 076


Looking just at the question in the title without going through the rest of the code, my simple answer would be to define your functions to take exactly one argument zList at all times, where zList is a List (as the name says). This list can have any number of arguments, and the function can run through them in a way that adapts to Length[ zList ] (preferably by using constructs like Map that operate on the whole list at once).


Posted 2012-12-13T02:23:42.953

Reputation: 93 191

The issue is with being able to treat each of these zs as variables to which values can be passed. You can see how "temp" needs to be defined in the first line of the loop and how $f_i$ is updated by temp in the last line of the loop. How would one achieve these even if I make these functions of tables of z? Also in the "Print" line I often want to print the value of temp with all of its arguments set to a value 1. How does one achieve that? – user6818 – 2012-12-13T08:53:38.977