青木です。

  In mail "[ruby-dev:23569] Re: Ruby2.0 spec summary around parameters and variables"
    matz / ruby-lang.org (Yukihiro Matsumoto) wrote:

> まつもと ゆきひろです

> |つまり、Values(1,2) == *[1,2] == *Values(1,2) なんですね。
> 
> はい。

納得しました。


> |とすると、決まっていないのは左辺と右辺がマッチしない場合ですか。
> 
> 決まっていないのは「ブロックパラメータで」左辺と右辺がマッチ
> しない場合です。

指摘いただいた点を再度反映させました。

  a, b = 1           # a=1, b=nil
  a,   = 1           # a=1
  a, * = 1           # a=1
  *a   = 1           # a=[1]
  *    = 1           # OK
  a    = 1           # a=1
  a, b = Values(1,2) # a=1, b=2
  a,   = Values(1,2) # a=1
  a, * = Values(1,2) # a=1
  *a   = Values(1,2) # a=[1,2]
  *    = Values(1,2) # OK
  a    = Values(1,2) # a=Values(1,2)

  def yieldSingle
    yield 1
  end

  yieldSingle {|a,b| }  # エラー / a=1, b=nil
  yieldSingle {|a, | }  # a=1
  yieldSingle {|a,*| }  # a=1
  yieldSingle {|*a|  }  # a=[1]
  yieldSingle {|a|   }  # a=1

  def yieldValues
    yield 1,2
  end

  yieldValues {|a,b| } # a=1, b=2
  yieldValues {|a, | } # エラー?
  yieldValues {|a,*| } # a=1
  yieldValues {|*a|  } # a=[1,2]
  yieldValues {|a|   } # エラー


> |思ったんですが、いっそ a,b=1 をエラーにしてしまったほうが
> |よくないですか。
> 
> 多重代入でも両辺の数を合わせた方が良いということでしょうか。

はい。少なくとも左辺と右辺で代入の種類を揃えるべきだと思います。
(つまり代入は lhs = rhs または mlhs = mrhs でなくてはならず、
lhs = mrhs および mlhs = rhs はエラー。)

これまで通常代入と多重代入を混用できるようにしてきたのは、
おおまかに言って、

  * 後方互換性
  * 配列とValuesの区別がなかったこと

の二つが主因だと認識しています。このうち第一点については
今回は考える必要がなく、第二点も解決されました。従って、
ここで過去の挙動にひきずられて曖昧な代入を許すのは無意味だと
思います。

もっとも、多重代入の範囲中で項数が違う場合はもう少し寛容でも
よいかと思います。例えばこういうのは許したいですし。

  car, *cdr = *list   # where list = [], [x], [x,y], ....


> あとは、ブロックの中でyieldした場合、暗黙のブロック(yieldの
> 対象)は外側のものを継承する必要がありそうです。関数(or メソッ
> ド)と考えるとちょっと気持ちが悪いのですが。

ええと、こういう話ですか。

  def m1
    lambda {
      yield
    }
  end
  block = m1 { p "method" }
  block.call { p "call" }   #=> "method"


  def m2
    lambda {|&b|
      yield
    }
  end
  block = m2 { p "method" }
  block.call { p "call" }   # これが "call" でなく "method" になる、ということ?

-------------------------------------------------------------------
青木峰郎