From: matz@... (Yukihiro Matsumoto) Date: 1998-11-19T15:51:34+09:00 Subject: [ruby-dev:3598] Re: Multiple assignment at yield() まつもと ゆきひろです 親知らず抜いて来ました.痛かったです.(;_;) In message "[ruby-dev:3596] Re: Multiple assignment at yield()" on 98/11/18, Shin-ichro Hara writes: |原です。 |なーるほど。まず右辺は配列になるわけですね。私は次のように |リスト(=カンマで区切られた式)を中心に考えていたんです。 |(もちろんリストって現実には配列で表現されるんでしょうが。) | | (1L) 右辺が配列ならリスト化,そうでなければそのまま | | (2L) 先頭に * が付いた変数には代入しなかった残りが配列とし | て代入される とすると(1L)により,右辺がリストでなく,結果が配列でない時に は,そのまま左辺に代入されるんですね.その場合,以下の代入は どうふるまうべきですか? a, b = 5 a, *b = 5 *a = 5 つまり,配列でないものを多重代入する時の振る舞いという意味で すが. 私自身の解釈としては(既に述べましたが), * 多重代入の右辺は配列化される * 先頭に * が付いた変数には代入しなかった残りが配列として 代入される と思っています.つまり,*a = x と a = x の違いは右辺が配列化 されるかどうかにあると思っているわけです. ||上記の変更を施したruby 1.1dの挙動は以下の通りです. これなんですが,ちょっとまずい点があったので,修正しました. まとめると9通りの組合せがあるわけです. 0 - block引数: &block 1 - block引数: {|*x| block.call(*x)} 2 - block引数: {|*x| block.call(x)} 3 - block引数: {|x| block.call(*x)} 4 - block引数: {|x| block.call(x)} 5 - 暗黙block: { |*x| yield(*x) } 6 - 暗黙block: { |*x| yield(x) } 7 - 暗黙block: { |x| yield(*x) } 8 - 暗黙block: { |x| yield(x) } で,これを実行して試してみましょう. class Foo def initialize(e); @body = e; end def each0(&block); @body.each(&block); end def each1(&block); @body.each { |*x| block.call(*x) } end def each2(&block); @body.each { |*x| block.call(x) } end def each3(&block); @body.each { |x| block.call(*x) } end def each4(&block); @body.each { |x| block.call(x) } end def each5; @body.each { |*x| yield(*x) } end def each6; @body.each { |*x| yield(x) } end def each7; @body.each { |x| yield(*x) } end def each8; @body.each { |x| yield(x) } end end Foo.new([0]).each0 { |x| p x } #=> 0 Foo.new([1]).each1 { |x| p x } #=> 1 Foo.new([2]).each2 { |x| p x } #=> [2] Foo.new([3]).each3 { |x| p x } #=> 3 Foo.new([4]).each4 { |x| p x } #=> 4 Foo.new([5]).each5 { |x| p x } #=> [5] Foo.new([6]).each6 { |x| p x } #=> [6] Foo.new([7]).each7 { |x| p x } #=> [7] Foo.new([8]).each8 { |x| p x } #=> 8 Foo.new([[0]]).each0 { |x| p x } #=> [0] Foo.new([[1]]).each1 { |x| p x } #=> 1 Foo.new([[2]]).each2 { |x| p x } #=> [2] Foo.new([[3]]).each3 { |x| p x } #=> 3 Foo.new([[4]]).each4 { |x| p x } #=> [4] Foo.new([[5]]).each5 { |x| p x } #=> [5] Foo.new([[6]]).each6 { |x| p x } #=> [6] Foo.new([[7]]).each7 { |x| p x } #=> [7] Foo.new([[8]]).each8 { |x| p x } #=> [8] これで「変じゃない」挙動を定義できたと思います. ただ,原さんの定義による挙動の方がよりよいことが示されれば, 変更するのは可能だと思います.鍵は *a という左辺を持つ多重代 入の解釈かな? まつもと ゆきひろ /:|)