-
-
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
Comment on method addition change from 0.4 to 0.5 #15950
Comments
I like the 0.5 behavior. |
I think semantically this boils down to the answer to the following two questions: "Is the scope of the inside of a |
To my reading, 0.5 matches the documentation: http://docs.julialang.org/en/latest/manual/variables-and-scoping/#for-loops-and-comprehensions
|
@mbauman I thought that at first as well, but I think the crux of the discussion is the scoping of |
Wow, I really take issue with those sources' use of the term "late binding". This is almost as bad as python calling arrays lists. This does not have to do with when variables are looked up (there is no dynamic scoping here either; this is all lexical scope), but with when new variables are allocated. What that comes down to is how a high-level construct like julia or python's Choice 1: allocate variable "outside" the loop, ala python
Choice 2: allocate variable "inside" the loop, ala julia:
We picked the second one in 0.4 or earlier. I think what really changed here has to do with when Long story short, this is a method-addition change and not a scoping change. |
I would argue that the old behavior was actually a bug since |
So the conclusion here is that the new behavior is preferable and the old behavior was basically a bug. |
The Julia analogue of this Python snippet changes behavior going from 0.4 to 0.5:
In Julia v0.4, the program produces the result
3
(as do the equivalent Python 2.x and 3.x programs). However in Julia v0.5, the program produces the result1
.The difference here is that Julia v0.5 produces a new function
f
at each iterationbut Julia v0.4 does not:
According to @JeffBezanson, the change was unintentional, and so the issue here is whether or not this change in behavior is desirable.
Related Python resources: PEP 289 and this blog post.
Catalogued below are illustrative variant programs.
Workaround using default arguments
In the Python world, the behavior above is termed "late binding" (see, e.g. here and here and here, not to be confused with "late binding" in the context of dynamic dispatch of a generic function). An apparently standard hack is to use default arguments to get lexical scoping of
i
. In Julia, the equivalent code isProgram B outputs 1 on both 0.4 and 0.5. Unlike in Program A, 0.4 appears to generate a new function at each iteration in Program B:
Anonymous functions (from @JeffBezanson)
On both 0.4 and 0.5, the output of Program C is
1
, and a new function is created with each iteration of the loop.Anonymous functions referencing
i
in global scope (from @mbauman)Program D outputs 3 on both 0.4 and 0.5. In both versions, the function generated does not change in each iteration:
According to @yuyichao, #14948 is a related issue.
Named functions referencing
i
in global scopeThe behavior of Program E is identical to that of Program D.
Thanks to @JeffBezanson @mbauman @yuyichao for participating in the discussion of this issue prior to filing.
The text was updated successfully, but these errors were encountered: