Skip to content
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

feature request: blocks #19423

Open
dlangBugzillaToGithub opened this issue Apr 13, 2018 · 2 comments
Open

feature request: blocks #19423

dlangBugzillaToGithub opened this issue Apr 13, 2018 · 2 comments

Comments

@dlangBugzillaToGithub
Copy link

FeepingCreature (@FeepingCreature) reported this on 2018-04-13T08:56:30Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=18759

CC List

  • Simen Kjaeraas

Description

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; }
@dlangBugzillaToGithub
Copy link
Author

simen.kjaras commented on 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)

@dlangBugzillaToGithub
Copy link
Author

hsteoh commented on 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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant