From: Shin-ichro Hara Date: 1998-11-22T16:59:53+09:00 Subject: [ruby-dev:3625] Re: Multiple assignment at yield() 原です。 また新たな提案ですが、値を送る側ではリストの前方に *a が出 てくるのを許してもいいのではないでしょうか。つまり、 a = [1, 2]; f(*a, 3) #=> f(1, 2, 3) ができると便利なんですがどうですか? 話戻して、 In message "[ruby-dev:3622] Re: Multiple assignment at yield()" on 98/11/21, Shin-ichro Hara writes: |実際にイテレータに不定個のパラメータを渡す事はめったにないこ |と いや、そうでもなかった。モジュールだったら何が来るかわからな いから、これはそんなに希な状況でもないです。 例えば、Enumerable の each_with_index の現在の定義は多分 module Enumerable def each_with_index(&block) i = 0 each { |x| block.call(x, i) i += 1 } end end だと思います。そして、現在の Hash に対する each_with_index は {1 => 2}.each_with_index {|x| p x} #=> [[1,2], 0] です。 さて、これを #=> [1,2, 0] としたくなったとする。そこで、Hash の らっぱーを Hash1 として class Hash1 include Enumerable def initialize(h); @body = h; end def each(&block); @body.each{|x,y| block.call(x,y)}; end end とつくってみます。比較のために class Hash2 include Enumerable def initialize(h); @body = h; end def each(&block); @body.each{|x,y| block.call([x,y])}; end end も定義すると、残念ながら結果は同じです。 Hash1.new(1=>2).each_with_index {|x| p x} #=> [[1,2], 0] Hash2.new(1=>2).each_with_index {|x| p x} #=> [[1,2], 0] ここで、*x = Y は強制的に x = [Y] とする様に仕様を変えます。 そして更に module Enumerable def each_with_index(&block) i = 0 each { |*x| x += [i] block.call(*x) i += 1 } end end と each_with_index の定義も変えると、 Hash1.new(1=>2).each_with_index {|x| p x} #=> [1,2, 0] Hash2.new(1=>2).each_with_index {|x| p x} #=> [[1,2], 0] となるはずです。 この新しい Enumerable の each_with_index は Hash1 に対して欲 しい each_with_index の動作を誘導しています。一方 Hash2 に対 してはいままで通りの動作を保っている。つまり、表現力が増して いるわけです。