我有一个模块,我想将其用作一组全局变量。
文件Global.jl:
module Global
export data
export dataLoaded
data = zeros(Int32, 20, 12, 31, 24, 60, 5);
dataLoaded = false;
end
文件main2.jl:
include("Global.jl")
import .Global
println(Global.data[10,1,1,1,1,1])
println(Global.dataLoaded)
Global.data[10,1,1,1,1,1] = 5
println(Global.data[10,1,1,1,1,1])
Global.dataLoaded = true
println(Global.dataLoaded)
我没想到 dataLoaded
不能像 data
那样进行更改。有没有办法允许更改dataLoaded
?
$ /usr/local/julia-1.2.0/bin/julia main2.jl
0
false
5
ERROR: LoadError: cannot assign variables in other modules
Stacktrace:
[1] setproperty!(::Module, ::Symbol, ::Bool) at ./Base.jl:14
[2] top-level scope at /usr/home/.../main2.jl:11
[3] include at ./boot.jl:328 [inlined]
[4] include_relative(::Module, ::String) at ./loading.jl:1094
[5] include(::Module, ::String) at ./Base.jl:31
[6] exec_options(::Base.JLOptions) at ./client.jl:295
[7] _start() at ./client.jl:464
in expression starting at /usr/home/.../main2.jl:11
最佳答案
正如我在 How to define global variables to be shared later in Julia 中评论的那样不允许您从模块外部更改变量的绑定(bind)。
首先,解释一下正在发生的事情:
x = [1,2,3]
x[1] = 10
第二个操作x[1] = 10
不会更改x
的绑定(bind),它仅更改存储在向量x的第一个元素中的值
(因为向量是可变的)。
另一方面写:
y = 1
y = 10
首先将 y
定义为值 1
(Int
类型,不可变),然后 y = 10
重新绑定(bind) y
以保持 10
。
现在 - 如何解决您的问题。有两种方法:
第一个是在 Global
模块中定义一个 setter 函数,如下所示:
function setdataloaded(value::Bool)
global dataLoaded = value
end
由于 setdataloaded
是在 Global
模块中定义的,因此它可以更改该模块中变量的绑定(bind)。然后您可以从模块外部调用setdataloaded
来更改dataLoaded
的值。
第二个是使用可变容器而不是不可变容器。最简单的是Ref
。所以你可以定义:
dataLoaded = Ref(false)
然后您可以获得 dataLoaded[]
的值,并从 Global
外部设置其值,例如 dataLoaded[] = true
模块(因为这次您要改变容器的内容,而不是重新绑定(bind) dataLoaded
)。
编辑
正如评论中所指出的,从技术上讲,您可以在 Global
模块内评估 dataLoaded = 10
表达式,甚至可以从该模块外部的代码中编写:
@eval Global dataLoaded = 10
或
Global.eval(:(dataLoaded = 10))
事实上,每个模块(baremodule
除外,但这是一种罕见的用例)都有自己的 eval
模块本地定义。
在某种程度上,eval
方法是我描述的第一种方法(使用 setter 函数),默认情况下是允许的。
关于global-variables - 为什么我可以更改另一个模块中的数组的值,但不能更改变量的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57939498/