2015-09-26 72 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