Only Break from innermost loop

How could I Break from only the innermost loop in a

Do[stuff,{i1,i1min,i1max},{i2,i2min,i2max},...]


?

I get the desired behaviour if I use

Do[Do[...Do[stuff,{i1,i1min,i1max}],...]


but this hard to utilize because the number of loops in my program is not fixed, and therefore I normally create a Table the iterator specs with a function myiterators[n] where n is the number of loops, and use

Do[stuff,Evaluate[Sequence@@myiterators[n]]]


If stuff contains a Break here, it breaks all n loops... Instead of only generating the iterators, I could of course generate the full Do[Do[... structure using Fold or similar, but this does not seem like the best way.

In my case, the function myiterators contains a call to a compiled function to evaluate the upper limits of the iterators. This precludes the use of Evaluate[Sequence@@...] since Evaluate forces the evaluation of the compiled function before the iterators aquire values in mulitDo. My solution was to use

ClearAll[multiDo2];
SyntaxInformation[
multiDo2] = {"LocalVariables" -> {"Table", {2, Infinity}}};
SetAttributes[multiDo2, HoldAll];
multiDo2[code_, {rest___, iter_}] :=
multiDo2[Do[code, iter], {rest}];
multiDo2[code_, {}] := code;


and call it with

multiDo2[stuff,myiterators[n]]


Works like a charm!

• Use Catch & Throw instead of Break. May 14, 2015 at 16:01
• @ChrisDegnen, how? Catch[Do[If[j > 7, Throw[Null]]; Print[{i, j}], {i, 9}, {j, i + 1, 10}]] never reaches i>1... May 14, 2015 at 16:04
• See Catch - Generalisations & Extensions for use of tags. May 14, 2015 at 16:07

I think this is a good case for a simple code generation. Here is one way to generate multiple Do in a macro-like fashion:

ClearAll[multiDo];
SyntaxInformation[multiDo] = {"LocalVariables" -> {"Table", {2, Infinity}}};
SetAttributes[multiDo, HoldAll];
multiDo[code_,  rest___, iter_] := multiDo[Do[code, iter], rest];
multiDo[code_] := code;


Basically, multiDo is a new language construct. It constructs the nested Do code at run-time, without evaluating the body, and then evaluates the code, after it has been fully constructed. Notice that (as MichaelE2 pointed out in comments), the outer-most iterator in the multiple-iterator syntax becomes the inner-most one in the generated code.

Here is an example:

sum = 0;
multiDo[If[i > j, Break[], sum += i], {j, 10}, {i, 10}];
sum

(* 220 *)


In this case, similar result can be accomplished by

sum = 0;
Do[sum += i, {i, 10}, {j, i, 10}]
sum

(* 220 *)


but in general, one can't easily reduce the multiDo to a simple Do with multiple iterators.

• Doesn't the normal order of iteration have the last iterator be the inside iterator? E.g. multiDo[code_, rest___, iter_] := (* same *)? May 14, 2015 at 16:27
• @MichaelE2 You are right, nicely spotted! Will edit. May 14, 2015 at 16:30
• @LeonidShifrin, thanks for teaching me this way of doing it. I discovered that Do[Catch[stuff;Throw[something]],i1spec,i2spec,...] also seems to work. Do you know why? I don't understand how Catch somehow is outside only the innermost loop. May 14, 2015 at 16:40
• @MariusLadegårdMeyer Indeed, it works, although it's not obvious at all that it should. I can well imagine an implementation of Do[body, iter1, ..., itern], which would satisfy all the Do specs but where this won't work. So, unless I am missing something, this means relying on hidden deatails or an implementation (which one also often does, but which is generally considered not to be a great practice). May 14, 2015 at 17:20
• Another advantage of the method I proposed is that it won't be too hard to get it into Compile, if needed. May 14, 2015 at 17:32