青木です。

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

> まつもと ゆきひろです

> |いま ruby-dev summary を書いているのですが、細部の動作に
> |確信が持てないので教えてください。現在までの情報から
> |次のような動作を予想したのですが、間違っているところは
> |あるでしょうか。
> |
> |      def m
> |        return [1, 2]
> |      end
> |
> |      a, b = m()
> |      p a  #=> [1, 2]
> |      p b  #=> nil
> 
> これは正しいです。
> 
> |      a, b = *m()
> |      p a  #=> [1, 2]
> |      p b  #=> nil
> 
> これはa=1,b=2です。なぜなら、
> 
>   * m()が配列を返す
>   * 「unary* (splat)」によってValues化される
>   * Valuesの各要素が各左辺に代入される
> 
> からです。

ああなるほど……。
つまり、Values(1,2) == *[1,2] == *Values(1,2) なんですね。

> |      def m2
> |        return 1, 2
> |      end
> |
> |# ここらへんが怪しい
> |      a, b = m()
> 
> これはm()じゃなくてm2()ですよね。

はい。

> |      p a  #=> Values(1,2)
> |      p b  #=> nil
> 
> これもa=1,b=2になります。
> 
>   * m2()がValuesを返す
>   * Valuesの各要素が各左辺に代入される
> 
> からです。
>
> |      a, b = *m2()
> |      p a  #=> 1
> |      p b  #=> 2
> 
> これは正しいです。Valuesにunary *を適用した結果もValuesだか
> らです。

とすると、決まっていないのは左辺と右辺がマッチしない場合ですか。
以下に再度まとめておきます。右辺で Values と *Array を
区別する必要はなさそうなので、Values だけにしました。

  a, b = 1           # a=1, b=nil
  a,   = 1           # ?
  a, * = 1           # ?
  *a   = 1           # ?
  *    = 1           # ?
  a    = 1           # a=1

  a, b = Values(1,2) # a=1, b=2
  a,   = Values(1,2) # ?
  a, * = Values(1,2) # a=1
  *a   = Values(1,2) # a=[1,2]
  *    = Values(1,2) # 
  a    = Values(1,2) # エラー


  def yieldSingle
    yield 1
  end

  yieldSingle {|a,b| }  # a=1, b=nil
  yieldSingle {|a, | }  # ?
  yieldSingle {|a,*| }  # ?
  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 をエラーにしてしまったほうが
よくないですか。


> |> == yield や Proc#call にブロックを渡すことを許すか

> あ、yieldは許さないでよいかなと思っています。で、
> Proc#callですが、
> 
>   def m(&block)
>     Proc.call{p "OK"}
>   end
> 
>   m{|&b| b.call}        # => "OK"
> 
> ですね。yieldがどう振る舞うかはまだ決めていません。yieldはメ
> ソッド全体で単一のスコープの方がわかりやすそうな気がしますが。

Proc.call は block.call ですよね。

なんでかわかりませんが、call 経由で呼ぶのは納得できます。
yield にブロックが渡せるのは非常に、非常に、非常に嫌です。
-------------------------------------------------------------------
青木峰郎