# How can I write a Do loop that iterates over N iterators when N is not known a-priori?

For any positive integer $n$ which is not specified a priori, I can make $n$-tuple vector $v$ by v = Array[a, 1, n]. Now, given that $n$ is a positive integer which is not specified a priori, I want to write an iteration sentence which performs over $1\leq a_1,\ldots, a_n\leq 3$. ($a_i$ are integers and hence I will get $3^n$ iterations).

For example, if $n=2$, my sentence plays the same role as the following loop:

Do[EXPERIMENT, {i, 3}, {j, 3}]


If $n=3$, my sentence plays the same role as the following:

Do[EXPERIMENT, {i, 3}, {j, 3}, {k, 3}].


I can do it for any given SPECIFIED integer $n$, but I want to write the universal looping sentence which iterates for $1\leq a_1,\ldots, a_n\leq 3$ ($a_i$ are integers.)

-
Something like this? f[n_] := Module[{i = 1}, Do[Print@i++, Evaluate[Sequence @@ Thread[List[Array[a, n], 1, 3]]]]]; f[4] –  belisarius May 19 at 21:25
Also, the tagging looks inappropriate. Anyone? –  belisarius May 19 at 21:29
That's what I want! –  newbie0823 May 19 at 22:06

Following belisarius' suggestion you might use something like:

SetAttributes[f, HoldFirst]

f[body_, n_Integer?Positive, m__:3] := Block[{a},
Do[body, ##] & @@ Thread[{Array[a, n], m}]
]


Use:

f[Print[a[1], a[2], a[3]], 3]

f[Print[a[1], a[2]], 2, 4]

f[Print[a[1], a[2]], 2, 5, 7]


How are parameters evaluated for a Plot in Manipulate

The second parameter is your n value. The third and following parameters are the range specification for the loops.

I Blocked a to prevent a global assignment to that symbol from breaking the function.

-
Faster than me ;) +1 –  Rojo May 20 at 4:12
@Rojo Well it only took me 6+ hours... :^) And I thought you were in bed? –  Mr.Wizard May 20 at 4:13
Haha, I just came back home, was about to go to bed, saw the other question, commented, and when I was about to lie down, it was stronger than me to come and answer. Then I saw this one, started to type Do[ and your answer appeared –  Rojo May 20 at 4:22
@rojo I'd love that sort of auto-completion - start typing, and Mr Wizard fills the rest in for me...! –  cormullion May 20 at 6:32

Say for $n=1$, you have defined f[{i1}] as your first experiment. For $n=2$, your experiments are defined by f[{i1,i2}], for $n=3$ the experiments are defined by f[{i1,i2,i3}] and etc, with the idea that you wish to allow $n$ such experiments. If you structure your experiments this way, then you can create a list of all experiments by

m = 3; n = 3; c = Tuples[Range[m], n]


Here $m$ is the number of values each variable is to take on, and $n$ is how many variables you have. Now you can run all your experiments at once using

Map[f, c]


or use the shortcut

f /@ c


For $m=n=3$, this gives

{f[{1, 1, 1}], f[{1, 1, 2}], f[{1, 1, 3}], f[{1, 2, 1}], f[{1, 2, 2}],
f[{1, 2, 3}], f[{1, 3, 1}], f[{1, 3, 2}], f[{1, 3, 3}],
f[{2, 1, 1}], f[{2, 1, 2}], f[{2, 1, 3}], f[{2, 2, 1}], f[{2, 2, 2}],
f[{2, 2, 3}], f[{2, 3, 1}], f[{2, 3, 2}], f[{2, 3, 3}],
f[{3, 1, 1}], f[{3, 1, 2}], f[{3, 1, 3}], f[{3, 2, 1}], f[{3, 2, 2}],
f[{3, 2, 3}], f[{3, 3, 1}], f[{3, 3, 2}], f[{3, 3, 3}]}


so you can see all 3^3 experiments will run. In general you will have $n^m$ experiments. As Mr. Wizard suggests, an alternative to Map would be to use Scan:

Scan[Print[f[#]] &, c]


This might be preferred if your experiment function f has "side effects", such as making assignments, or generating output, since Scan will suppress these.

-
I thought about posting something like this but held off because I thought Do might be specified because of memory restrictions. Nevertheless the packed array from Tuples is compact, and this should be practical for a large range of applications. I would however mention Scan as that is more analogous to Do. +1 –  Mr.Wizard May 20 at 5:25
Mr. Wizard -- Yes, I agree I was taking some liberties with the question: but this is one of the things with functional programming - if you plan ahead and build your "experiments" correctly, then later steps (like this one) become almost trivial. In fact, I would say planning ahead is important in any kind of programming. –  bill s May 20 at 5:29