-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
each instance of a comprehension variable should be different #1571
Comments
+1 |
This distinction suggests to me that the |
Ok then let's change this for for loops according to the existing issue,
|
This is tangentially related to the discussion on Parellel Callbacks in C on the list back in August, specifically Stefan's post regarding having threads with completely independent global state. This pretty much eliminates the (user-facing) differences between multithreading and multiprocessing, and is pretty much the model I reference in my link to "Writing Perfect Multithreaded Programs with ZMQ" further down the discussion. But this is discussing more the difference between distributed and parallel (or lack thereof), not the instance at hand. |
I think it would make sense to extend this change to all variables that are local to a for loop/comprehension.
just as well as |
That seems like the best semantics to me as well. I'm not sure how hard it will be to implement though. |
If all loop-local variables are fresh on each iteration, then this loop won't work:
In parallel loops and comprehensions, it's reasonable to disallow dependence on previous iterations, but this seems really strict for ordinary |
This example seems pretty weird to me – I would never write a loop like that, but maybe other people do. I was thinking that only the loop variable |
Also, this example currently works but is useless since the scope of |
I agree my example is weird. It's not totally useless though since I could imagine using the value of It's easy to make only |
I prefer the precise approach. Otherwise, if I'm understanding correctly, there would be no difference between let x = 1
# ...
end and let
x = 1
# ...
end Which seems weird. Why even bother with the first one in that case? |
There is one obscure difference: in |
Right. I think I'd still prefer the precise approach where the local variables in the let block are normal locals. |
That might be ok, but we would have
Or, if not in comprehensions, then in this case:
|
Yeah, it's a tough call. For comprehensions it is pretty clearly more intuitive for |
Yes, I'm really starting to think every scope block should allocate new bindings for its variables every time it is entered. Jameson agrees too. |
I think that's the least gotcha behavior by far and if we can do it without performance issues, we should. Simply avoiding the entire if issue of when there are new bindings and when there aren't is a big win. |
the most problematic change was forcing for loop variables to be loop-local, instead of reusing existing local vars. for example local i for i = 1:2 end return i currently works and returns 2. for now, the behavior is to introduce new variables for each iteration unless we are overwriting an existing local. comprehensions, however, always introduce fresh variables and never overwrite existing ones.
To clarify that commit message, for now I'm keeping the behavior where |
Yes, I like that approach. It seems the least surprising. |
jb/newvars branch merged. |
I'm unreasonably excited about this. |
So, I immediately set out trying to break this and mostly everything is cool, but this seems inconsistent: julia> for i = 1:5
if i == 1
x = 1
else
x = x+1 # x is undefined
end
println(x)
end
1
2
3
4
5
julia> a = {}
0-element Any Array
julia> for i = 1:5
if i == 1
x = 1
else
x = x+1 # x is undefined
end
println(x)
push!(a,()->x)
end
1
ERROR: x not defined
in anonymous at no file:5 Of course, I never would have thought to even write an evil loop like this except that you used it as an example above, but it seems like these should either both succeed or both fail. |
There is a small change I can make to fix this. So far I've left it this way (1) to ease the transition, since less code will break, and (2) because fixing it requires adding an enormous number of |
Honestly, it is probably fine to leave it this way. |
Currently we have this:
I think this should definitely evaluate to
[1:10]
. I also think that's what for loops should do, but in the case of comprehensions, I think the case is much more powerful.I've tagged this with "parallel" because comprehensions are a very natural place for implicit parallelism in the language, but that essentially would require the semantics I'm proposing in order to work correctly. Note that I'm talking about evaluating a normal comprehension using multiple threads, rather than producing a
DArray
distributed across multiple machines.The text was updated successfully, but these errors were encountered: