From: "俊(とし)" Date: 2011-09-25T13:21:09+09:00 Subject: [ruby-list:48405] Re: 要素のない配列の挙動? sora_h さんとだんさんの説明が非常にわかりやすかったと思います. 私が先にブロック内のローカル変数云々で言いたかったのも,同様のことだったのですが, うまく表現できていませんでした.知らず知らずのうちに,参照する先を新しく生成した オブジェクトに切り替えてしまい,元のオブジェクトを参照しなくなった,と言うべきでした. たしかにブロックは本質的ではありません. また,破壊的メソッドと非破壊的メソッドの違いは,これまでもよく理解していたつもりですが, うっかりするとよく間違えます.私自身はcollect と collect! をよく使います. だんさんの実例は,昔よくはまった例で,これが最も問題の本質を表しているように 思います.昔々 C 言語で初めてポインタを習った時のことを思い出しました. ありがとうございました. ついでに質問ですが,Array#dup と Array$clone も,単にポインタのコピーにすぎませんよね? オブジェクトまでコピーしようという時に私がよく使うのは,r[0..-1] というオブジェクト生成法です. もっとスマートな方法はありませんか? r = [1, 2, 3] x = r y = r[0..-1] x = [3, 4, 5] r = [5, 6, 7] p r #=> [5, 6, 7] p x #=> [3, 4, 5] p y #=> [1, 2, 3] -- 俊(とし) 2011年9月25日10:34 Shota Fukumori (sora_h) : > sora_hです. > > On 9/25/11 9:21 AM, dezawa wrote: >> r.each do |x| >> if x.empty? >> x = [""] # <== ここで、 >> >> end >> } >> >> x(すなわち r の要素)に 新しい object [""] が作られて代入されたのです > > その言い方だと誤解が含まれるので補足します. > > r.each do |x| ... end で変数 x には r の要素が入っています. > しかし,x は要素が入っているだけで変数であるので,x = [""] を実行すると > 入っている r の要素から新しく [""] が x に代入されました.なので,変数 x > にあった r の要素への参照から,新しく作られた [""] への参照に変更された > ということです. > > 配列を別の中身に入れ替えるためには,Array#replace を用いて > > r.each do |x| > if x.empty? > x.replace([""]) > end > end > > とすることも可能です. > > また,すでに言及されていますが Array#map (実態は Enumerable モジュールか > らインクルードされているため Enumerable#map になりますが), Array#map! > (Array#map の破壊的メソッド[1]) を用いることで実現することも可能です. > > p r.map {|x| if x.empty?; [""]; else; x; end } #=> [[""],[""]] > p r #=> [[],[]] > > # Array#map! (破壊的メソッド) を利用する > p r.map! {|x| if x.empty?; [""]; else; x; end } #=> [[""],[""]] > p r #=> [[""],[""]] > > [1] 破壊的メソッドというのは,参照を変更せずその参照しているオブジェクト > そのものを変更することです. > > -- > Shota Fukumori a.k.a. sora_h - http://sorah.jp/