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

break with value + loop else clauses #22891

Open
StefanKarpinski opened this issue Jul 20, 2017 · 2 comments
Open

break with value + loop else clauses #22891

StefanKarpinski opened this issue Jul 20, 2017 · 2 comments
Labels
speculative Whether the change will be implemented is speculative

Comments

@StefanKarpinski
Copy link
Member

Once upon a time, I proposed giving a meaning to for-else and while-else that would be quite at odds with the meaning given to these constructs in Python. In version 1.19, Rust introduced a different feature which finally made Python's for-else and while-else contructs make sense to me: break with a value. Of course, Python still doesn't have break with a value and Rust doesn't have for-else or while-else, but these features really dovetail nicely. Let me explain by showing how this would work in Julia...

Loops in Julia are expressions like everything, but they evaluate to nothing. If we added break with a value, then a loop that's exited with break x would evaluate to x, allowing one to write something like this:

using Primes

values = rand(1:100, 10)

p = for x in values
    isprime(x) && break x
end

After this executes, p is equal to the first number in values that's prime (of course, we could use findfirst, but bear with me). This code is type-unstable, however: if values happens to contain no primes, then the loop evaluates to nothing. Enter the Python-style else clause on a for loop:

p = for x in values
    isprime(x) && break x
else
    maximum(values) # makes no sense, but whatever
end

Now p is set to the first prime occurring in values, or it is set to the maximum value of values. This is a silly example, but you get the point. This is all non-breaking since all of these syntaxes are currently errors.

@StefanKarpinski StefanKarpinski added the speculative Whether the change will be implemented is speculative label Jul 20, 2017
@StefanKarpinski StefanKarpinski added this to the 1.x milestone Jul 20, 2017
tkluck added a commit to tkluck/julia that referenced this issue Aug 14, 2017
This commit enables a combination of two language features that dovetail
nicely together (as remarked by @StefanKarpinski in [1]): for/else and
break-with-value, which together allow something like:

    name = for person in people
        if person.id == id
            break person.name
        end
    else
        generate_name()
    end

The parsing patch is pretty straightforward. As for the code lowering
part, I opted to make a second version of `'break-block`, called
`'break-block-with-value`, which passes a target variable for the return
value onto the `break-labels` stack. That's where the `'break` operation
finds it.

An alternative approach would be something more similar to the existing
`replace-return` function: Instead of having an intermediate node
representing `'break-block-with-value`,we could traverse the expression
tree and replace `break-with-value` by an assignment followed by a
break.

I have no opinion either way; the current commit seemed like the obvious
implementation to me, but that was before I saw `replace-return`'s prior
art.

This patch still has a few places marked `TODO`, where scoping issues
for the `else` block need to be resolved. I'll tackle that after
awaiting feedback.

[1] JuliaLang#22891
@tkluck
Copy link
Contributor

tkluck commented Aug 14, 2017

I took a jab at this with the pull request mentioned above; I took it as an opportunity to learn a bit about Julia's internals. Let me know what you think!

I'm not particularly attached to the current implementation; I'll be happy to learn from any suggestions or alternative patches.

tkf added a commit to JuliaFolds/Transducers.jl that referenced this issue Jun 24, 2019
@jakobjpeters
Copy link
Contributor

Since this issue is still open but most of the discussion appears to occur in #23260, I posted some ideas #23260 (comment) for if this is ever taken up again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
speculative Whether the change will be implemented is speculative
Projects
None yet
Development

No branches or pull requests

4 participants