全局变量值的变化没有立即更新?

时间:2015-10-18 23:01:47

标签: global-variables julia

在以下代码中,我尝试在函数s中修改所有全局变量(tuvtest()) 。由于uv位于模块中,Mod.uMod.v是只读变量,因此我尝试通过setter函数更改其值(set_uset_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)中更新。我是否犯了一些关于改变全局变量值的重大错误或误解......?或者这是因为从函数内部或外部引用全局变量的某种不同机制?

1 个答案:

答案 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 - 谎言撒谎,当朱莉娅给你一个旧答案时,你不应该感到惊讶。