在以下代码中,我尝试在函数s
中修改所有全局变量(t
,u
,v
,test()
) 。由于u
和v
位于模块中,Mod.u
和Mod.v
是只读变量,因此我尝试通过setter函数更改其值(set_u
和set_v
)。
s = 1
const t = 2
module Mod
u = 3
const v = 4
set_u( u_ ) = ( global u ; u = u_ )
set_v( v_ ) = ( global v ; v = v_ )
end
function test()
global s, t
s = "S" ; t = 200
@show s, t
Mod.set_u( "U" ) ; Mod.set_v( 400 )
@show Mod.u, Mod.v
end
test()
@show s, t
@show Mod.u, Mod.v
结果(使用Julia v0.4.0获得)
WARNING: redefining constant t
(s,t) = ("S",2) # (1)
WARNING: redefining constant v
(Mod.u,Mod.v) = ("U",4) # (2)
(s,t) = ("S",200) # (3)
(Mod.u,Mod.v) = ("U",400) # (4)
这里,(3)和(4)是我的预期结果(假设const
仅修复了变量的类型)。但我无法理解为什么{1}和t
的值未在(1)和(2)中更新。我是否犯了一些关于改变全局变量值的重大错误或误解......?或者这是因为从函数内部或外部引用全局变量的某种不同机制?
答案 0 :(得分:2)
在函数体内未被“更新”的唯一常量是您标记为const
的常量。
(假设
const
仅修复了变量的类型)
这个假设是不正确的。虽然Julia允许您更改const
绑定的值,但重新定义const
变量肯定会导致问题。请注意,它警告您这不是一个好主意。
这是一个简单的例子,展示了正在发生的事情:
julia> const t = 3
f() = t
f (generic function with 1 method)
julia> @code_llvm f()
define i64 @julia_f_21636() {
top:
ret i64 3
}
julia> t = 4
@code_llvm f()
WARNING: redefining constant t
define i64 @julia_f_21636() {
top:
ret i64 3
}
你不需要非常精通读取LLVM IR就可以看到它返回整数3并且不进行查找。它看到t
被标记为常量,并在编译函数时使用该信息对其进行优化。中断const
并更改t
的值不会导致f
重新编译,因此会返回旧值。对于非常量全局,LLVM更复杂,但它仍然非常易读。你可以看到它正在从某个地方加载一个值:
julia> s = 2
g() = s
@code_llvm g()
define %jl_value_t* @julia_g_21649() {
top:
%0 = load %jl_value_t** inttoptr (i64 4417498392 to %jl_value_t**), align 8
ret %jl_value_t* %0
}
简而言之:如果你对变量的const
- 谎言撒谎,当朱莉娅给你一个旧答案时,你不应该感到惊讶。