为什么在 Julia 0.7 和 1.0 中循环内的这个赋值会失败? [英] Why does this assignment inside a loop fail in Julia 0.7 and 1.0?
问题描述
(k, a, b, a1, b1) = (BigInt(2), BigInt(4), BigInt(1), BigInt(12), BigInt(4))
while k <= BigInt(4)
(p, q, k) = (k*k, BigInt(2)*k+BigInt(1), k+BigInt(1))
end
此代码在 Julia 0.6 中编译和运行,但在 1.0 中会产生 ERROR: UndefVarError: k not defined
.
This code compiles and runs in Julia 0.6, but in 1.0 produces ERROR: UndefVarError: k not defined
.
版本之间有什么变化吗?Julia 1.0 中的这段代码有什么问题?
Did something change between versions? What's wrong with this code in Julia 1.0?
推荐答案
shadowtalker的回答是正确的.然而,这段代码有一个重要问题值得添加更多解释(而且评论太长了).
The answer by shadowtalker is correct. However, there is one important issue with this code that is worth adding some more explanation (and it was too long for a comment).
Julia 中针对此案例的相关范围规则如下(如果您想阅读详细信息,可以在此处找到它们https://docs.julialang.org/en/latest/manual/variables-and-scoping/#Local-Scope-1):
The relevant scoping rules in Julia for this case are the following (and if you want to read the details you can find them here https://docs.julialang.org/en/latest/manual/variables-and-scoping/#Local-Scope-1):
while
块引入了一个新的局部作用域;- 本地范围从封闭的全局范围继承变量仅用于读取(除非它们使用
global
关键字限定,如 暗语者); - 本地作用域从封闭的本地作用域继承变量以进行读写,除非它们用
local
关键字限定.
while
block introduces a new local scope;- local scope inherits variables from enclosing global scope only for reading (unless they are qualified with
global
keyword as explained by shadowtalker); - local scope inherits variables from enclosing local scope for reading and writing unless they are qualified with
local
keyword.
现在 - 为什么这很重要?原因是,如果您在全局范围内(例如在 Julia REPL 中)运行代码,您的代码的行为会有所不同,而如果您在本地范围内(例如在函数内部)运行,代码的行为会有所不同.
Now - why this is important? The reason is that your code will behave differently if you run it in global scope (e.g. in Julia REPL) and differently if you have it in a local scope (e.g. inside a function).
如果您在全局范围内运行它,则需要 shadowtalker 显示的内容.但是,如果你运行它,例如在函数内部,您不必更改任何内容.例如此函数将正常工作:
If you run it in global scope then what shadowtalker showed is needed. However, if yourun it e.g. inside a function you do not have to change anything. For example this function will work correctly:
function f()
(k, a, b, a1, b1) = (BigInt(2), BigInt(4), BigInt(1), BigInt(12), BigInt(4))
while k <= BigInt(4)
(p, q, k) = (k*k, BigInt(2)*k+BigInt(1), k+BigInt(1))
end
end
如果你也没有创建一个函数,例如在全局范围内使用 let
块,代码将按预期运行:
also without creating a function if you e.g. use let
block in a global scope the code will just run as intended:
let
k, a, b, a1, b1 = BigInt(2), BigInt(4), BigInt(1), BigInt(12), BigInt(4)
while k <= BigInt(4)
(p, q, k) = (k*k, BigInt(2)*k+BigInt(1), k+BigInt(1))
end
k, a, b, a1, b1
end
因为 let
创建了一个本地范围(我在 let
块的末尾添加了语句,以使其评估为引入变量的值,以便您可以检查他们).
because let
creates a local scope (I have added the statement at the end of let
block to make it evaluate to the values of the introduced variables so that you can inspect them).
与 Julia 0.6 及更早版本相比,这是一个重大变化,其中 Julia 区分了硬本地范围和软本地范围(请参阅此处 https://docs.julialang.org/en/release-0.6/manual/variables-and-scoping/#scope-of-variables-1),但是这种区别已经消失了——所有的局部作用域现在的行为都是一样的.这是一个重大的变化,实际上它意味着如果您将其复制粘贴到全局范围内,您可以期望在某个本地范围内正确运行的代码(大多数情况下是一个函数)将改变其行为.根据我使用 let
块的经验,如上所示是缓解此问题的最简单方法.
This is a significant change from Julia 0.6 and earlier where Julia made a difference between hard and soft local scopes (see here https://docs.julialang.org/en/release-0.6/manual/variables-and-scoping/#scope-of-variables-1), but this distinction is gone - all local scopes now behave identically. This is a significant change an in practice it means that you can expect that the code that runs correctly inside some local scope (a function in most cases) will change its behavior if you copy-paste it to a global scope. From my experience using let
blocks as shown above is the simplest way alleviate this problem.
这篇关于为什么在 Julia 0.7 和 1.0 中循环内的这个赋值会失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!