-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
break
and continue
out of multiple loops
#5334
Comments
I know this seems limiting, but it is quite standard. At that point, you'd almost want to add goto (#101). Do you have an interesting use case for this? |
@JeffBezanson No, but Dart has this. |
The Dart spec is not too encouraging on this:
|
Well, Julia is significantly faster than most dynamic languages, it is beneficial to make it a compiler target. |
I sometimes wished we had this functionality when writing multi-dimensional loops, e.g.:
instead of
|
I've sometimes wanted multilevel
This is a strange idea. If you want a great compiler target, compile to LLVM. |
@StefanKarpinski Translating to Julia would be easier (and the code would be more readable) than compiling to LLVM |
@carlobaldassi I wonder if the better solution for that case is to consider nested loops defined in that syntax as one loop for the purpose of |
Yes, that is probably a more intuitive solution and I'd welcome that change. I also agree that goto is better than multilevel break/continue, if feasible. |
One might get complaints from people who'd want to make a seemingly-small change like
But the |
To clarify, what I meant was that if someone starting writing some code with the one-loop syntax, counting on how |
Honestly, I think the way |
I'm on board with that. |
@StefanKarpinski, it's not that I'm worried about people using
and
I've made such conversions myself many times, and currently there is no penalty for doing so. Nothing else in julia changes its meaning when you do so, but if we introduce the asymmetry in If we just use a different word from |
That is why I originally made the multi-loop syntax just a syntax rewrite. With the change though, we'd be thinking about these not as nested loops but a single loop over a multi-dimensional space, like |
Don't get me wrong, I also think breaking out of the whole thing is the more intuitive behavior, even if it doesn't work that way in C, and I'm just worried about how we deprecate |
|
To break out of all loops in the current scope? |
for the particular case of nested loops chained together with commas, at least. |
Oo, that seems more confusing to me since I would expect |
Hmm, more boring than my idea of |
|
I like it! Can we have more such keywords please? |
Or, in German: |
|
Do you sing Blue Danube, too? |
I do not, but I sing some mean Prince at karaoke. @JeffBezanson can bear witness. |
easy peasy |
The power button is even more emphatic than More seriously, Presumably we'd be planning to make it an error to use |
Stefans suggestion makes me feel so privileged having umlauts on my keyboard. More seriously, I would make the behavior change now and use |
I kind of like the comma separating these. Once you get what it means, it's pretty clear and general. |
I'm reopening because I think the |
Right. Forgot to actually reopen. Thanks, @pao. |
Implementing this in the parser is beyond me but as it happens "break; continue" is currently valid Julia syntax. The semantics are less useful but nothing a little macro magic can't fix. Proof of concept implementation as a macro in this gist for those who want to try it out. |
x-ref a julia-users discussion: https://groups.google.com/d/msg/julia-users/byhFGOJz7tQ/xu16ktAVAAAJ I think explicit or implicit named loops would be safer than the |
I agree with @ihnorton that explicit labels are attractive. We can reuse for i=1:3
for j=1:3
for k=1:3
@info "indices" (i, j, k)
if k == 2
@goto end_j
end
end
end
@label end_j
end To extend for i=1:3
@label for j=1:3
for k=1:3
@info "indices" (i, j, k)
if k == 2
@goto end_j
end
end
end
end We'd also need This would need changes to lowering to support correct placement of [Edit: or in hindsight this doesn't looks so fantastic. Maybe better just to go with |
would this stop at function boundaries? Or could I escape a loop in the caller function? Not that it is a good idea, its just something that made me thinking 😀 |
Yes. |
Now available as the registered package Multibreak. The difference to the proposed |
Thanks for the working functionality, @GunnarFarneback. Regarding the still-open issue for the core language, just a thought: I looked at Go, Java, JavaScript, Perl, Dart, and modern Fortran for their multilevel break/continue done via labeling, as I'm sure is background for this thread. I now understand the reluctance to adopt the same in Julia--because disappointingly (to me) all use goto-style labeling for break/continue. I say "goto-style" because all follow the ubiquitous This tradition seems in part why people spoke of offering goto "instead of" labeled break/continue in Julia: "goto would be simpler and more general than break with labels"; and "I've never really cared much for the break LABEL and continue LABEL style. goto LABEL seems clearer to me." (Taken from the thread.) Under goto-style labeling, I must agree. But these quips never made full sense to me, because labeled break/continue when offered is supposed to be modern structured programming, thus incomparable to goto and independent of its offering. And certainly not conflated with it, despite that both require a labeling. (Nothing against gotos.) Maybe that's unfair ragging, so to the point: non-goto-style labeling for break/continue. Compare in Julia: continue labeled goto-style,
...vs. a more structured programming look like I'd expect,
Besides the unobtrusive readability, importantly the latter While of course doing so in slightly simpler reading than the goto workaround with label above the final end. Note Python's PEP for multilevel break/continue had precisely the same thought, a postfixed labeling, which if adopted would have bucked the goto-style tradition above. Goto-style labels have never been very satisfying for this... if we interpret "the statement immediately following" such a label as what to break/continue (not where), this antagonizes the label's other meaning as a code location for goto used traditionally. Which makes the resulting break/continue unnatural to read, as remarked in the above quips and this thread's 2014 discussion that led to its closing, dismissing labeled break/continue as little more than a limited goto syntax. Whereas the variant here clearly is not, as a modern-structured-programming structure independent of goto. (Just as a bare single-level break/continue is not dismissed as a limited goto syntax.) An alternative observation of this distinction from goto labeling, pre/post-fixing aside, is to simply note that the statement immediately following a goto's label can normally be anticipated to be swapped--throughout code development and maintenance as lines are inserted/removed there. So the label naturally occupies its own line. (What I've called a code location.) Whereas the new keyword attaches specifically to a statement, for reference to it. (This gives self-referencing code.) Might I ask, @JeffBezanson, since you closed the issue back when labeled break/continue was the option on the table, before 2016's unlabeled variant led to reopening, can you confirm that the reasoning behind closing no longer quite applies here the same, no longer indicates closing the door on labeled break/continue? I do not presume to abandon the 2016 unlabeled variant, before the two compete for adoption. Also I'm a nobody here, so I won't debate beyond this post. Interestingly, Julia might be better positioned than most languages containing goto to adopt unique-from-goto labeling for break/continue, due to goto and its labels being relegated to macro-hood. (To give credit where due, Fortran already achieved this separation actually, albeit slightly ironically (to me): break/continue labeling is done goto-style, as I call it, and goto labeling via old-school numbering. The former does employ a nice terminology though, "named constructs", which could be borrowed.) On that note, distancing the new keyword from
(using Now, the weighing of unlabeled vs. labeled syntax has not been taken up here, although I'll note once as others have that any break/continue by reference is arguably safer read/stated than the clever proposal of |
An interesting idea would be to consider the loop variable an implicit label for a loop. E.g. you could write |
That opens up for interesting surprises if you carelessly switch the loop order. From my point of view the main attraction of |
I wonder: are those cases any worse than the other kinds of order dependence which can make switching loops invalid? I would guess there's more insidious cases which already exist in normal julia code, such as |
By which rules we determine the loop variables of while loops? |
One of the things that bothers me about |
Yeah, that's an issue—that isn't clear at all. |
But for cartesian for loops that might be the perfect solution. Is it necessary to tackle all types of loops with the same solution? Because breaking intermediate cartesian for loops currently can only be done by splitting them up. Besides that in the case of cartesian for loops continuing a layer is equivalent of breaking the next inner layer. |
As a baseline,
|
I completely agree with this. In addition I find that many places where I might want this can be replaced with a little refactoring and an early return. So I feel like the bar should be fairly high for new syntax. In particular, introducing a keyword to label loops feels excessive. Hence the idea of trying to use a macro to allow labeling loops in some way (eg, some variant of reusing the |
To expand on this: we could declare that
This should allow |
In Julia, the statements
break
andcontinue
affects the nearest enclosing loop, and there is currently no way to point them to outer loops.The text was updated successfully, but these errors were encountered: