Bug 18759 – feature request: blocks

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-04-13T08:56:30Z
Last change time
2024-12-13T18:58:21Z
Assigned to
No Owner
Creator
FeepingCreature
Moved to GitHub: dmd#19423 →

Comments

Comment #0 by default_357-line — 2018-04-13T08:56:30Z
Blocks are a generalization of foreach opApply overloading. They allow any struct expression to be followed by a statement, which is packaged into a delegate that returns a control flow type (or, if you want to be cheap about it, an int like opApply does) and passed to opBlock in the struct, which decides the control flow of the statement. Advantages: * callback-heavy code looks a lot more straightforward * break/continue/return can be used from within what would otherwise be callbacks * reduce lambda abuse for control flow (.each is a natural candidate) * comparatively little effort because it's just an extension of opApply Example: import core.controlflow; struct indefinitely { // alternatively: opBlockLoop for 'opBlock that handles break/continue' static ControlFlow opBlock(ControlFlow delegate() action) { while (true) { auto flow = action(); // flow.ended: control flow reached end of block // otherwise, something like a return statement, break, continue or goto if (!flow.ended) return flow; } } Usage: indefinitely { writeln("This is repeated indefinitely."); } Other cool example: If combined with variable declaration expressions, a construct like foreach can in theory be implemented entirely in the library: ForeachStruct foreach(T)(T iterable, out int indexVariable, out ElementType!T loopVariable) - array.foreach(int index, auto value) { return value; }
Comment #1 by simen.kjaras — 2018-04-13T14:56:49Z
I'd suggest posting this on the forum. You're gonna have to write a DIP for it to actually be added to the language. This definitely needs more detail about the behavior of 'break', 'continue' and 'return' - constructs that don't make sense in all possible use cases. There should be a way to declare which of these are valid. I'd also like to see more complete examples. While your 'indefinitely' example is great, it does not show how to deal with arguments - multiple input, multiple output, inference. For instance, what would myFoo look like in a case like this: myFoo (ref e, out int n, float f; a, b) { if (f < 1) continue; n = e * f; e++; if (f > 2) break; if (e == 14) return; } (feel free to use a completely different example, this is just to highlight the different complications possible)
Comment #2 by hsteoh — 2018-04-18T14:53:51Z
This definitely needs to be discussed in the forum, and will need a DIP if there's any hope of actually implementing it. (And great idea BTW; I came up with a similar idea a long time ago but didn't pursue it beyond a cursory forum discussion. Perhaps you'll have better luck this time.)
Comment #3 by robert.schadek — 2024-12-13T18:58:21Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19423 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB