2
$\begingroup$

Is it possible, to have several variables defined in a manner similar to vars={x1, x2, x3, x4, x5, x6, x7, x8, x9, x10} and then use an expression like eg. vars={0.1, 1, 5.11, 0.01, 0., 1.22, 56.66, 12., 0.0234, 10} to initialize the xi's?

The motivation is initializing objects with many (more than 10) parameters in an automated way. Ideally, I could load parameter values from a file (as an intermediate result of another calculation).

currently I do something like

path = NotebookDirectory[];
imported = Import[StringJoin[path, "params.txt"], "Table"]
Module[{vars},
  (
    vars = #;
    calculate[vars]
   ) & /@ params
 ]

I understand that vars=# is not setting the xi's.

Also, calculate stands for code that effectively uses the xi's at different places and in different combinations eg w=somefunc[x1,x5]; res=anotherfunc[w,x8];

As it stands, I'm using var[[i]] to access the values of the xi's inside calculate.

Another thought is to use something like init[var[tag, i]] so as to initialize a variable named tag during iteration i

Clear[init]
Module[{tags, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, i, var},
  tags = {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10};
  MapIndexed[(
    {i} = #2;
    Scan[
      (init[var[#[[1]], i]] ^= #[[2]]) &,
      Transpose[{tags, #1}]
     ];
    f[];
   ) &, params]
]

This feels a bit cumbersome although it has the added benefit that if forces me to be explicit about which parameter is used every time.


This is an example parameter file:

1.044   2.291   3.581   0.863   1.347   1.819   107.288 24.18   0.965   12.703
1.153   2.464   4.898   0.868   0.982   3.891   3.513   25.114  0.461   1.715
1.663   1.872   6.782   1.806   0.549   1.896   29.598  9.43    0.289   6.712
0.759   1.072   5.115   1.558   0.79    2.083   4.243   16.295  0.439   21.295
0.857   2.599   8.699   0.973   1.662   2.521   40.431  6.744   1.569   19.568
0.633   1.628   11.683  0.314   0.357   1.568   74.998  2.89    0.649   6.64
1.993   1.614   9.142   0.605   0.977   3.444   24.548  21.119  0.644   3.769
1.313   0.881   1.853   0.63    0.822   1.963   69.966  1.79    0.867   2.069
1.791   2.801   8.764   1.197   0.625   2.809   92.26   8.101   1.061   15.962
1.341   3.116   7.668   0.334   0.319   3.014   71.549  19.36   0.045   12.627
0.392   0.276   9.23    0.104   0.661   1.056   21.396  2.922   0.518   13.152
1.057   0.734   8.805   0.913   0.185   1.641   36.06   11.362  1.313   6.663
2.097   2.625   7.498   0.741   1.983   1.466   94.043  4.878   1.286   3.234
1.786   3.218   10.717  0.017   1.37    1.573   109.555 6.13    0.322   14.407
1.079   1.604   10.488  1.461   1.902   2.961   83.925  18.375  0.957   11.84
1.674   2.081   10.699  1.407   1.286   2.712   113.456 16.668  0.585   10.112
0.766   2.093   3.382   0.038   0.723   1.966   23.117  10.286  0.248   16.182
0.302   2.117   0.579   1.592   1.068   3.651   27.161  21.71   1.606   7.82
0.139   1.095   1.552   1.569   1.701   2.888   58.326  17.189  0.198   6.011
0.787   1.64    3.169   1.739   1.238   2.933   105.238 17.607  0.122   12.633
0.195   0.508   7.326   1.431   0.541   3.959   73.477  5.734   0.029   2.962
1.335   2.651   6.1 0.193   0.713   1.476   80.253  7.991   0.865   14.636
1.034   2.11    6.272   0.103   0.924   2.06    29.236  22.536  1.315   16.036
1.206   3.369   8.935   0.398   1.015   2.929   25.779  11.385  0.358   4.918
0.183   1.935   10.402  1.254   1.634   3.774   2.327   7.516   1.508   1.826
0.858   3.209   0.992   0.21    1.865   1.598   27.886  9.473   0.158   15.426
0.479   1.514   11.51   1.898   1.274   3.432   7.957   2.484   0.618   16.689
0.676   1.837   4.174   1.201   0.833   1.792   17.348  21.553  1.975   14.202
2.046   2.313   8.704   1.781   1.179   1.991   16.893  21.075  1.014   9.952
0.746   2.849   9.286   0.973   0.064   2.828   98.833  23.344  1.993   18.61
$\endgroup$
5
$\begingroup$

One simple way of doing this is to force evaluation of the l.h.s. of = using Evaluate:

vars = {x1, x2, x3};

Evaluate@vars = {1, 2, 3};

{x1, x2, x3}
(* {1, 2, 3} *)

Of course, this only works if the xi didn't have a value before.

Update

For the general case (where some of the variables already have values) we can do the following:

varList /: Set[n_Symbol, varList[vars__]] :=
 (
  n := {vars}; 
  n /: Set[n, vals_List] := {vars} = vals;
  varList[vars]
 )
SetAttributes[varList, HoldAll]

(* Test it a bit *)
x1 = 1; x3 = 3;

vars = varList[x1, x2, x3]
(* varList[x1, x2, x3] *)

vars
(* {1, x2, 3} *)

vars = {2, 3, 4}
(* {2, 3, 4} *)

x3 = 5;

vars
(* {2, 3, 5} *)

How this works

varList does two things: It has attribute HoldAll so that variable names inside it won't get replaced by values. Secondly, we define an UpValue using TagSetDelayed that matches anything of the form n = varList[...], where n is a symbol. In that case, the normal Set (=) procedure is overridden by the following:

  • First, make sure that n evaluates to the current values (hence the SetDelayed (:=)) of the variables anytime it's used
  • Define an UpValue for n: Anytime something of the form n = {...} appears, set the values of the variables instead.
  • Return varList[vars] to make it more consistent with the default behavior of =
$\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.