新井です。

In message "[ruby-list:33911] [Summary]arguments for def"
  on 14 Feb 2002 02:58:49 +0900,
  Masaaki Sakano <mas / star.le.ac.uk> 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)