Julia では、Array a に対して、 b=a としても a のコピーが作られる訳でなく、 b が a の参照になる。 もしもコピーがしたければ b=copy(a) とする。 いうようなことが某説明に書いてあった。
非常に分かりにくい。一度は「間違い」と思ったくらいである。
配列 a に対して、 b=a と c=copy(a) でどう違うかを見てみよう。
julia> a=ones(3) 3-element Array{Float64,1}: 1.0 1.0 1.0 julia> b=a 3-element Array{Float64,1}: 1.0 1.0 1.0 julia> c=copy(a) 3-element Array{Float64,1}: 1.0 1.0 1.0 julia> a==b true julia> a==c true julia> a===b true julia> a===c false |
== で値を調べると、b も c も a と同じ値を持つことが分かるが、 === で等しいか調べると、 b は a に等しいが、 c は a に等しくない。
ここで a の要素を書き換えてみよう。
julia> a[1]=2 2 julia> a 3-element Array{Float64,1}: 2.0 1.0 1.0 julia> b 3-element Array{Float64,1}: 2.0 1.0 1.0 julia> c 3-element Array{Float64,1}: 1.0 1.0 1.0 |
以上を見ると、次のことが観察される。
ここで a の要素 a[] でなく、 a そのものに代入を行うと、 a の内容は書き換わるが、 b は代入前の a の内容を保持することになる。
b が a の参照であるとき、a に代入を行うと |
julia> a=zeros(2) 2-element Array{Float64,1}: 0.0 0.0 julia> b 3-element Array{Float64,1}: 2.0 1.0 1.0 |
関数の引数にするときは、Array は参照渡しであり、 関数の中で引数を書き換えると、元に戻ったとき変更されてしまう。
(ここも、C言語などでプログラムを書いた経験があると、 何をやっているか、分かりやすいと思う。 そういう経験がない人にとって、 どのように感じられるか、なかなかおっかない。)
時々、同じサイズの配列が必要になることがある。 b=similar(a) とすると、 a と同じ大きさの Array b が用意される。 中身は初期化されていない (要するに値はゴミである)。
MATLAB で近いことをしようとすると、 b=zeros(size(a)) とするのだろうか (これは Julia でも有効である)。 これだと初期化という手間をかけることになる。
この辺、Julia は、一切の無駄なことはしない、 というポリシーが感じられる。
a と b が既に存在していて、 ディメンションが一致するとき、 b .= a とすると、 b の各要素に a の対応する要素がコピーされる。
copy() や similar() を使うと新しいメモリ領域を用意することになるが、
= や .= ではそうならない。
慣れるまでは色々うっかりミスをしそうだ…