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

RFC: disallow return inside generator and comprehension expressions #27034

Closed
wants to merge 1 commit into from

Conversation

JeffBezanson
Copy link
Member

This allows us to avoid defining whether a generator expression is wrapped in a function, and avoids possible confusion about where the return will actually return from (since it's not lexically obvious that the generator expression is nested inside a function). Alternatively, we could decide that a generator officially introduces a nested function, and fix this case in the special alternate comprehension lowering.

ref #27023

@JeffBezanson JeffBezanson added breaking This change will break code compiler:lowering Syntax lowering (compiler front end, 2nd stage) triage This should be discussed on a triage call labels May 8, 2018
@ararslan ararslan deleted the jb/generatorreturn branch May 9, 2018 21:25
@ararslan
Copy link
Member

ararslan commented May 9, 2018

I guess we're not doing this, then? :/

@JeffBezanson
Copy link
Member Author

We can still discuss it, I just decided to fix the bug (the discrepancy between the special lowering and normal lowering of comprehensions) first.

@StefanKarpinski StefanKarpinski removed the triage This should be discussed on a triage call label May 18, 2018
@mbauman
Copy link
Member

mbauman commented May 18, 2018

We did talk about this on the triage call — folks there seemed to be generally in favor since it's not at all obvious what you're returning from.

@StefanKarpinski
Copy link
Member

It is not actually unclear at all: you are returning from the innermost function body—that's always what return does. The body of a comprehension is not a function body, regardless of how it may be implemented, so you are not returning from that. On the other hand, I do also think that doing this is bad form so I don't really have a problem with disallowing it.

@mbauman
Copy link
Member

mbauman commented May 18, 2018

To split a hair: sure, it may be a well-defined behavior, but I maintain it's not obvious — at least it wasn't to me.

I fully understand why it works the way it currently does, but my initial thought pattern here went something like:

  • wait, that's legal?
  • oh, does it return from the comprehension loop itself, leaving uninitialized values at the tail? And ditching out of a generator early?
  • oh, of course, we create an anonymous function that generates each element, so that's where the function boundary is

As Jeff said in the first post: "it's not lexically obvious that the generator expression is nested inside a function." If return from do-blocks was ever questionable (#1288), this is even more so.

@StefanKarpinski
Copy link
Member

A do block is just a syntax for passing an anonymous function, comprehensions are not—if an anonymous function is used in the implementation of a comprehension, that implementation detail should be hidden. For do blocks, it's not an implementation detail, it's the definition of what the syntax means. In this case, whenever the return is evaluated, the computation should abandon whatever it's doing and return from the innermost enclosing function body. I still don't see what's unclear.

@StefanKarpinski
Copy link
Member

To be clear, I'm not arguing for allowing this—I don't care—I'm just arguing that if we did allow this there is only one correct behavior.

@JeffBezanson
Copy link
Member Author

you are returning from the innermost function body—that's always what return does. The body of a comprehension is not a function body, regardless of how it may be implemented

Oh, well since comprehension bodies are implemented as functions, that is in fact what it will return from currently. Making it do anything else is pretty difficult. This is partly exposed via generators; if you inspect the object (a for b in c) you can see a function wrapped in a generator.

Consider this example:

function f()
    g = (return 0 for i in 1:1)
    global G = g
    first(g)
end

If the return 0 returns from f(), what happens if, after f returns, I call first(G)?

@StefanKarpinski
Copy link
Member

Sure, I can see that it's hard to implement and highly marginal, so just disallowing it seems good.

@StefanKarpinski
Copy link
Member

Perhaps return in a generator expression should also be disallowed?

@mbauman
Copy link
Member

mbauman commented May 18, 2018

Ah, now I see how we were talking past each other — I was talking about how the currently-implemented behavior is not obvious. We're in agreement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code compiler:lowering Syntax lowering (compiler front end, 2nd stage)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants