Skip to content

Add the 'nonlocal' keyword to allow non-local returns #1776

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

Closed
gosoccerboy5 opened this issue Aug 3, 2021 · 5 comments
Closed

Add the 'nonlocal' keyword to allow non-local returns #1776

gosoccerboy5 opened this issue Aug 3, 2021 · 5 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@gosoccerboy5
Copy link

gosoccerboy5 commented Aug 3, 2021

I was recently reading this blog post by @munificent. I came across the Beatiful example 2: Finding an item section and Bob pointed out how Dart doesn't have non-local returns. After seeing a little bit of other languages where lambdas can return from the scope outside of them, maybe Dart should have a feature like that.

bool contains(Iterable haystack, needle) {
  haystack.forEach((item) nonlocal {
    if (item == needle) return true;
  });
  return false;
}

The nonlocal keyword would mean that any return (or even break, continue, or yield?) statements perform that action in the scope from which the lambda was called, and not just inside the lambda itself.
That's about it, so tell me if this is a good or terrible idea, I suppose.

@gosoccerboy5 gosoccerboy5 added the feature Proposed language feature that solves one or more problems label Aug 3, 2021
@Levi-Lesches
Copy link

Well in this case, there's obviously Iterable.contains, but I'll ignore that for the sake of the question. I don't think this is impossible (it's essentially a try-catch with values instead of exceptions), but personally I think it's simpler the way it is now.

An alternative that's commonly used is to return a value with some meaning, and then the enclosing scope looks for and interprets that value. For example, Iterable.any:

bool any(bool test(E element)) {
  for (E element in this) {
    if (test(element)) return true;
  }
  return false;
}

In fact, that solves your example just as well as Iterable.contains does:

bool contains<E>(Iterable<E> hasystack, E needle) => 
  iterable.any((E item) => item == needle);

There can also be an advantage to letting the enclosing scope have full control over the lambda, instead of giving the lambda free reign to jump out-of-scope:

bool findInFile(File file, bool Function(String) predicate) {
  // in order to close the file, the stream must be fully read or cancelled
  bool found = false;
  await for (final List<int> chunk in file.openRead()) {
    final String decoded = utf8.decode(chunk);
    if (predicate(decoded)) found = true;
  }
  return found;
} 

A predicate that can return out of this function prematurely might not let Dart free up resources.

@munificent
Copy link
Member

I think non-local returns are important in a language like Smalltalk that doesn't have a lot of built in control flow syntax and does have an extremely lightweight syntax for blocks. You basically need them to implement useful control flow.

But Dart has if, for, for-in, while, do-while, break, continue, yield, await, etc. The built-in language is quite rich when it comes to imperative control flow. Because of that, I don't think users often feel the need to add their own control flow constructs. And without that, I don't think non-local returns add much value. I can't honestly say I've found myself wanting them in the many years I've been writing Dart code.

@gosoccerboy5
Copy link
Author

That makes sense.

@munificent
Copy link
Member

I'm going to close this because I don't think the language team is likely to do nonlocal returns any time soon.

@gosoccerboy5
Copy link
Author

Ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants