问题
This snippet of code is from JuliaBoxTutorials
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
while i <= length(myfriends)
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i += 1
end
giving this error when run with Julia v1.0
UndefVarError: i not defined
Stacktrace:
[1] top-level scope at ./In[12]:5 [inlined]
[2] top-level scope at ./none:0
But when i += 1
is replaced with global i += 1
it works. I guess this was still working in v0.6 and the tutorial will be adapted once the new Intro to Julia is published this Friday.
I was just wondering, is it possible, to make a while loop without stating a global variable?
回答1:
As @Michael Paul and @crstnbr already replied in the comments, the scoping rules have been changed (Scope of variables in Julia). The for
and while
loop introduce a new scope and have no access to the outside (global) variables. You can get scope access using the global
keyword but the recommended workflow is wrapping your code in functions.
One of the benefits of the new design is that the user is forced to avoid such global constructs which directly affect the performance of functions - which cannot be type stable when they access global variables.
One downside is the confusion when experimenting in the REPL and seeing such errors.
In my opinion the new behaviour is the cleaner one with respect to predictability. It was however a very tough and long-running discussion within the whole Julia community ;)
There is currently a discussion if the REPL will be changed to behave like the old one by making use of let
-wraps: https://github.com/JuliaLang/julia/issues/28789
This is something which is not practical to be done manually (much more complicated then using the global
keyword), see the example by Stefan Karpinski: https://github.com/JuliaLang/julia/issues/28789#issuecomment-414666648
Anyways, for the sake of completeness (although I would not recommend doing this) here is a version using global
:
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
N = length(myfriends)
while i <= N # you cannot even call a function here
# with a global, like length(myfriends)
global i, myfriends
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i += 1
end
Note however that this is also completely valid:
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
greet(friend) = println("Hi $friend, it's great to see you!")
for friend in myfriends
greet(friend)
end
回答2:
I found that this works in Julia v1.0:
let
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
while i <= length(myfriends) # this function here seems to work no problem
friend = myfriends[i]
println("Hi $friend, it's great to see you!")
i = i + 1 # gives syntax error when prefixed with global
end
end
In fact, it will give me a syntax error if I try to make i global :) within the while loop.
来源:https://stackoverflow.com/questions/52037753/while-without-global