We have:
loop {
break value;
}
'label: loop {
break 'label value;
}
'label: {
break 'label value;
}
It would be nice to extend this to other blocks:
'label: if cond {
break 'label value;
} else {
break 'label value;
}
'label: if let pat = expr {
break 'label value;
} else {
break 'label value;
}
'label: match expr {
pat => {},
}
'label: try {
break 'label value;
}
As opposed to:
'label: {
if cond {
break 'label value;
} else {
break 'label value;
}
}
'label: {
if let pat = expr {
break 'label value;
} else {
break 'label value;
}
}
'label: {
match expr {
pat => {},
}
}
'label: {
try {
break 'label value;
}
}
This avoids a whole level of indentation and an unnecessary pair of {}.
Note that while let and while wouldn't be changed because those can't return values.
(Note that IDEs/rustfmt are unable to cope with:
'label: { if cond {
break 'label value;
} }
Instead, they rewrite it to:
'label: {
if cond {
break 'label value;
}
}
)
cc #2046, @ciphergoth
Do you have a specific use case for this? (I'm not asking for hypotheses on how this could be used; do you have something specific you want to use this for?)
Much of the motivation for introducing labeled break was for macro authors, and the extra level of indentation doesn't really matter there. And the ability to break from multiple branches of an if, for instance, seems like it will increase the tendency to produce spaghetti code with non-obvious control flow.
Mainly combining 'label and try, to avoid nesting.
See:
// as part of a very complex function, like a game loop
let x = try {
if self.ready {
let a = do_complex_thing?;
more_complex_things(a)
} else {
Err(NotReady)
}
}
// Vs:
let x = 'label: try {
if !self.ready {
break 'label Err(NotReady);
}
// avoids nesting
let a = do_complex_thing?;
more_complex_things(a)
}
(I find the latter much more readable, as the "normal" case is at the bottom of the block, not nested, and the "exceptional" case is out of the way. and yes I know about "omg please split your functions" but uh... no?)
Or just using throw (cc #2426):
let x = try {
if !self.ready { throw NotReady; }
let a = do_complex_thing?;
more_complex_things(a)
}
I'm glad label-break-value was accepted, but hope it's only rarely seen outside of macros offering interesting control flow constructs. I see it and loop as the very bottom level of intraprocedural control flow constructs -- while, for, loop-break, continue, return, etc are all just sugar for some combination of those two.
Any time LBV is actually used the control flow is already unusual, so I actually appreciate the explicitness that comes from having a dedicated {} pair just for the label scope. It avoids confusion like "is it doing 'label: try { or try 'label: { or can I do 'foo: try 'bar?". I definitely never want to see the last of those, nor something like else 'label: {.
Closing since this doesn't seem to be going anywhere. If you want to continue with this proposal, please open a topic on internals.rust-lang.org, or write up a formal RFC proposal.
Most helpful comment
Do you have a specific use case for this? (I'm not asking for hypotheses on how this could be used; do you have something specific you want to use this for?)
Much of the motivation for introducing labeled
breakwas for macro authors, and the extra level of indentation doesn't really matter there. And the ability to break from multiple branches of anif, for instance, seems like it will increase the tendency to produce spaghetti code with non-obvious control flow.