2015-09-26 71 views
3

這個例子看看數組時:奇怪的行爲修改爲環

julia> VERSION 
v"0.4.0-rc1" 

julia> foo = [1,2] 
2-element Array{Int64,1}: 
1 
2 

julia> baz = Array(Any,3) 
3-element Array{Any,1}: 
#undef 
#undef 
#undef 

julia> for i = 1:3 
      foo[1] = -foo[1] 
      baz[i] = foo 
      println("loop",i) 
      println("foo: ",typeof(foo),"->",foo) 
      println("baz[",i,"]: ",typeof(baz[i]), "->", baz[i]) 
      println("baz: ",typeof(baz),"->",baz) 
     end 

loop1 
foo: Array{Int64,1}->[-1,2] 
baz[1]: Array{Int64,1}->[-1,2] 
baz: Array{Any,1}->Any[[-1,2],#undef,#undef] 
loop2 
foo: Array{Int64,1}->[1,2] 
baz[2]: Array{Int64,1}->[1,2] 
baz: Array{Any,1}->Any[[1,2],[1,2],#undef] 
loop3 
foo: Array{Int64,1}->[-1,2] 
baz[3]: Array{Int64,1}->[-1,2] 
baz: Array{Any,1}->Any[[-1,2],[-1,2],[-1,2]] 

結果是出乎意料的給我,我想baz應該是Any[[-1,2],[1,2],[-1,2]]。如果foo不是數組,則結果是合理的。

julia> foo = 1 
1 

julia> baz = Array(Any,3) 
3-element Array{Any,1}: 
#undef 
#undef 
#undef 

julia> for i = 1:3 
      foo = -foo 
      baz[i] = foo 
      println("loop",i) 
      println("foo: ",typeof(foo),"->",foo) 
      println("baz[",i,"]: ",typeof(baz[i]), "->", baz[i]) 
      println("baz: ",typeof(baz),"->",baz) 
     end 
loop1 
foo: Int64->-1 
baz[1]: Int64->-1 
baz: Array{Any,1}->Any[-1,#undef,#undef] 
loop2 
foo: Int64->1 
baz[2]: Int64->1 
baz: Array{Any,1}->Any[-1,1,#undef] 
loop3 
foo: Int64->-1 
baz[3]: Int64->-1 
baz: Array{Any,1}->Any[-1,1,-1] 

我的問題是這裏發生了什麼,什麼是在for循環指定數組的正確方法是什麼?

編輯:我加了baz = deepcopy(baz)和一切順利。還想知道原因。

回答

4

Julia has Noteworthy Differences from other Languages 例如,不像MATLAB Julia數組是通過引用來分配的。引用是別名或現有變量的備用名稱。例如,假設你爲保羅創建了一個引用(別名),你可以將該人稱爲彼得或保羅。 baz[i] = foo之後,foo的更改元素也將修改baz[i]

+0

所以正確的方法是使用'deepcopy',在這種情況下'baz [i] = deepcopy(foo)',用於「解耦」。這很有道理,非常感謝! – Gnimuc

4

這是一個常見的陷阱,出現因爲foo綁定。 John Myles White寫了一篇非常好的博客文章: http://www.johnmyleswhite.com/notebook/2014/09/06/values-vs-bindings-the-map-is-not-the-territory/

順便說一句,您應該儘量避免使用Any數組,這很慢。

Array(typeof(v), 3) 

或只是把顯式類型的v,例如:可以按如下方式很容易地做到這一點

Array(Vector{Int}, 3) 

這裏,Vector{Int}相當於(另一個名稱)Array{Int, 1}

另外請注意,不是所有的println S,你可以用好的@show

julia> a = 3 
3 

julia> @show a 
a = 3 
3 

@show也返回顯示的值。在以前版本的Julia上,輸出看起來像a => 3

+0

材料真的很有用,謝謝你的有用提示! – Gnimuc