From: Shin-ichro Hara Date: 1998-12-04T02:16:46+09:00 Subject: [ruby-dev:3739] Re: multiple assignment, yield and return 原です。 In message "[ruby-dev:3732] Re: multiple assignment, yield and return" on 98/12/03, MAEDA Shugo writes: | |前田です。 |原> ええ、もうモデルを完全に変更するという前提で話をしています。(^^; | |でもまつもとさんはあまり乗り気じゃなさそうですね(^^; そうみたいだなー。(^^;; |原> つまり yield への値の渡し方をフラグ式でも原式Listでも前田式配列 |原> でもどれでもいいから yield([1,2]) と yield(1,2) が区別できるよう |原> に変更して、ブロックパラメータへの代入は従来の多重代入の方法を用 |原> いる。ここで *x = a のみ x = [a] とする非互換を設ける、という考 |原> えなんだけど。 | |yieldの仕様を僕の提案のようにした場合、多重代入のモデルだと、 | |yield(1) | |として、|x| で受けとった時、x = [1] になって非互換になるので、 ||*x| の時の挙動の変更だけでは不十分な気がするのですが。 すいません、私は私の案の主張ばかりしています。 前田さんの方法では yield(1) で args = [1] となります。そこで この arg へ値の渡し方を私の案に採り入れる事もできて、その場合 |x| の x への代入の仕方は、args.size == 1 か否かで処理をスイッ チする事になります。args.size == 1 という「フラグ」が立ってい ると [1] を 1 に直してしまう。 くどいけど、もう一度整理してみますね。 話が混乱しないように yield(Y) の引数 Y からブロックパラメータ |X| への代入を2段階に分けます。つまり args で yield(Y) が途中 内部的に生成するものを表す事にします。すると、 yield(Y) -> args (= Yで決まる何か) -> X = args がブロックパラメータへの代入のプロセスです。(ここで X, Y は 一般のリストだとします。) (A)[ruby-dev:3704] での前田さんの提案は args = [Y] (Y が何でも) であり、 X = args の方は (a1) X が何であろうとそれぞれに args の各要素を当てはめる リストの最後に *x があれば、arg の代入されなかった残 りを配列にして x とする です。(すっきりしている。) (B)ところで現行は args = Y .. Y が単項(1項のリスト)の時 Array(Y) .. Y が復項(2項以上リスト)の時 です。次に X = args の方は、(現行の)多重代入です。これを詳しく 書くと (b1) X が単項 x のとき x = arg (b2) X がそれ以外とき arg が Array ならそのまま、そうで     ないなら arg.to_a の各要素を当てはめる     左辺の最後の *x には代入されなかった残りを配列にして x にする となっています。 (C)私の案は、まず args ですが、List() を List 生成(= List.new また、to_l を List 化とすると、 args = Y .. Y が単項(1項のリスト)の時 List(Y) .. Y が複項(2項以上リスト)の時 です。X = args の方は (c1) X が単項 x のとき x = arg (arg が List でないとき) arg.to_a (arg が List のとき) (c2) X が単項 *x または arg が List なら、arg はそのまま、     そうでないなら arg.to_l として各要素をあてはめる 左辺の最後の *x には代入されなかった残りを配列にして x にする となります。 #ここで [ruby-dev:3724] では Array#to_l を書き忘れていたけ #ど [1, 2, 3].to_l == List(1,2,3) です。 #やはり List はクラスとしてユーザーから見えてはいけない #かな。 #何度も同じ事を書いてしまっている様な気がする。(^^; |原さんの案だと、 |*x = [1, 2] #=> x = [[1, 2]] |*x = List.new(1, 2) #=> x = [1, 2] | |のように両者を区別できるようにするということだと思いますが、 そうです。 |x, y = [1, 2] #=> x = 1; y = 2 | |なのに | |*x = [1, 2] #=> x = [[1, 2]] | |というのは、やはり不自然な気もします。 |# *xの場合だけを見れば、自然に見えるんですが。 前者は多重代入扱い、後者は半ば単純代入扱いしてい ると考えればそう不自然でもないと思うのだけど。 逆に現状だと x, *y = 0, [1, 2] #=> x = 0; y = [[1, 2]] なのに *y = [1, 2] #=> y = [1, 2] という不自然さがあるわけです。