2015-10-18 66 views
2

在下面的代码中,我尝试从函数test()中修改所有全局变量(s,t,u,v)。由于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 

结果(与朱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)和(2)不被更新的tMod.v值。我是否在改变全局变量的价值方面犯了很大的错误或误解......?或者这是因为从函数内部或外部引用全局变量的某种不同机制?

回答

2

未得到“更新”功能的体内而唯一不变的是那些你标记const

(假设const修正仅变量的类型)

这种假设是不正确。虽然朱莉娅确实允许您更改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 -ness你的变量,当朱莉娅给你一个答案老,你不应该感到惊讶。

+0

嗯,好吧,现在我明白了...我总是假设'const'修复仅变量类型(因为它允许更改值),但是这似乎是因为汇编代码利用了假设常量性是危险的。 ..我试图在模拟中使用Julia模块中的const全局变量作为“可修改的参数”(遵循Fortran模块中流行的方式),但这似乎不是一个好主意。非常感谢:) – roygvib

+0

刚刚使用'const t = [3]'进行测试,作为LLVM优化的实用解决方案。类型信息得到保存:'typeof(t [1])== Int64',内容可以改变。再次,这是一个解决方法,但它的工作原理。 –

+0

@ user3580870嗨,我刚刚也证实你的方法有效。此外,似乎可以对const,全局复合类型使用相同的技巧(即Any在其字段仍然可变时不传播)。所以这样的const全局类型可能对我的目的有用...但我也会尝试考虑更多的“朱利安”来存储参数,而不是简单地从其他语言翻译。谢谢 :) – roygvib