-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Early termination for loops and comprehensions #3158
Comments
I'd be happy to try my hand at implementing this if it seems like a good idea. |
I agree this would be a lovely addition to the current comprehensions' features. |
Beware that the proposed syntax is already valid syntax in some cases. For example, this currently compiles: smallNumbers = (n for n in numbers while n < 10)
# Equivalent to:
smallNumbers = ((n for n in numbers) while n < 10) Which evaluates to an empty array as the |
Interesting, I didn't see that the comprehension syntax with I wonder if anyone is actually using |
It's not so much about who's using it, but about consistency. (I find it difficult to come up with a meaningful example though; mostly because of the post-fix |
Cool idea, but the "manual" |
Thanks for considering it! I'm interested in your thought process here. To me, adding |
It does make a decent amount of sense. If you can find a way to have a single new (or perhaps reused) keyword instead of two, and no conflicts with the current valid syntax ... let us know and we'll reopen. |
The common terminology for this is "take while" and "take until" (used in at least Python, Haskell, C#, Scala, Groovy, and Clojure). Whatever we choose, we could probably skip the "until" variant, though it would be nice to find a syntax that worked for both. Some options using new keywords: smallNumbers = (n for n in numbers takewhile n < 10)
smallNumbers = (n for n in numbers takeuntil n >= 10)
smallNumbers = (n for n in numbers whilst n < 10)
smallNumbers = (n for n in numbers aslongas n < 10) Another option is to reuse smallNumbers = (n for n in numbers break unless n < 10)
smallOddNumbers = (n for n in numbers when n % 2 break if n >= 10)
for n in numbers break unless n < 10
alert "#{n} is small"
for n in numbers when n % 2 break if n >= 10
alert "#{n} is small and odd" |
I thought about this a bit more and came up with what I think is an even more useful/general feature that only requires a single new keyword: theItem = (item for item in items when item.foo is 'bar')[0] This both reads a little awkwardly, and is inefficient, since it will continue searching through the whole array even after the one item I care about has been found. The proposalAny loop or comprehension can be suffixed with a new
smallNumbers = (n for n in numbers take while n < 10)
# => [0, 1, 1, 2, 3, 5, 8]
smallOddNumbers = (n for n in numbers when n % 2 take until n >= 10)
# => [1, 1, 3, 5]
firstThreeEvenNumbers = (n for n in numbers when not (n % 2) take 3)
# => [0, 2, 8]
for n in numbers take while n < 10
alert "#{n} is small"
for n in numbers when n % 2 take until n >= 10
alert "#{n} is small and odd"
for n in numbers when not (n % 2) take 3
alert "#{n} is one of the first three even numbers" I believe this doesn't introduce any ambiguous syntax. start = Date.now()
doSomething n for n in numbers take while n < 10 while Date.now() - start < 5000
# Equivalent to:
start = Date.now()
while Date.now() - start < 5000
for n in numbers
break unless n < 10
doSomething n |
I like your most recent proposal, @aroben. I'd like to go through some of the CoffeeScript projects I work on to see how frequently this form is applicable. |
@aroben Nice work. Do you have any interest in taking a stab at this and reopening as a pull request? |
I'm definitely interested in implementing this. I've been mulling over whether the order of (n for n in numbers when n % 2 take until n >= 10)
(n for n in numbers take until n >= 10 when n % 2) To me, even though the order is different, these both read as the But I certainly can imagine situations where you would want the It kind of feels like we're building a query language, similar to .NET's LINQ. Am I over-thinking this? In CoffeeScript today, the ordering of
…no matter what order they appear in the source. But it would make it harder to ask "Which of the 10 most populous states have income over $40,000?" as I explained above. |
And you could keep the ordering arbitrary (or not). |
That's true, in the And I think for |
It would be useful to have a syntax to terminate loops and comprehensions early. I'm imagining something like this:
The
while
oruntil
clause would come after anywhen
orby
clauses.This would result in more concise code with a better clarity of intent than using manual
break
statements. It also wouldn't require any new keywords. I believe the syntax is also unambiguous because it currently is an error to writefor n in numbers while
andfor n in numbers until
.The text was updated successfully, but these errors were encountered: