From: Koji Arai Date: 2002-02-14T04:08:04+09:00 Subject: [ruby-list:33912] Re: [Summary]arguments for def 新井です。 In message "[ruby-list:33911] [Summary]arguments for def" on 14 Feb 2002 02:58:49 +0900, Masaaki Sakano wrote: > 坂野 正明です。 > [Q] > Ruby の def 文においては、引数の受渡しは、多重代入と大体同じ > (違いは引数の数のミスマッチに関する厳しさだけ?)。よって、 & によるブロックの受渡しがメソッド引数にはありますね。 # もっと、細かいことを言えば、def foo(a,) とは書けないとか # あります。 蛇足ですが、ブロック引数は(私が知り得る限りでは)多重代入と同 じですね。 def foo yield 1, [2, 3], 4 end foo() {|a, (b,c), d| p [a, b, c, d]} => ruby 1.6.6 (2002-02-13) [i586-linux] [1, 2, 3, 4] こういうネストした多重代入の挙動も同じ。 > def文の中で、破壊的メソッドを使う時は要注意。引数にとった > オブジェクトを誤って"破壊"しないためには、どうすればいいか? > > # なお、(私の理解が正しければ) Numeric, True/False/NilClass, Proc > # クラスなどには破壊的メソッドは存在しないので、気にしなくてもいい。 immutable ですから。脱線しますが、ruby においては immutable なオブジェクトは clone できないようですが、逆に class Object def immutable? begin self.clone false rescue TypeError true # clone できなければ、immutable end end end とも定義できるといっていいのかな? 1.6 では Numeric 系で上記が通用しないので、 class Object def immutable? begin self.equal?(self.clone) rescue TypeError true # clone できなければ、immutable end end end の方が良いですが。 > [A5] (邪道派?) > > def で 引数を受け取った直後に、他の変数(もしくは自分自身)に .clone する。 > > これを簡単に行うためには、例えば、以下のような方法。 > > 1. 以下の1行ファイル( clone.rb )を用意して、ライブラリパスに置く。 > def clone(*a) a.map{|i| i.clone} end で、immutable なオブジェクトを考慮すれば def clone(*a) a.map {|i| i.clone rescue i} end でしょうか > 2. ruby -rclone で clone.rb を require。 > 3. def 文において、 > def xyz(a,b,*c) > (a,b,*c)=clone(a,b,*c) > ... > などとして、最初に一気に引数を(同じ名前で) .clone する > # Editor で括弧ごとコピーすればいいので、考えなくてよくて楽。 1 引数のメソッドだとこのままでは単純にコピーとはいかないですね。 def clone(*a) a.map {|i| i.clone rescue i} end def xyz(a) a = clone(a) end p xyz(1) => [1] -- 新井康司 (Koji Arai)