こっそり書いてたんですが、いつの間にか見つかってしまいました。 別にいいけど。
あ、私は「blog」と「にっき」を区別しない人です。 あんなのたんなるスタイルの違いじゃないかと。
日本語で「Matzさん」と言われると恥ずかしい。 よければ「まつもとさん」でお願いします。> みなさま
callやyieldで私がなにを問題視しているのか理解できないとの指摘が多い(ような気がする)ので、 もう一度まとめてみたいと思います。分かってる人には繰り返しになりますが。
Rubyのブロックってのはもともとループの抽象化のために生まれたものですから、 以下のような性質を持ちます。
ブロックをオブジェクト化したProcオブジェクトも同じ性質を受け継いでいます。 ところが、普通の人が「手続きオブジェクト」に期待するのは、 無名の関数オブジェクトですから(私もそう期待します)、
の方が嬉しい場合が多いでしょう。後者は必須じゃないけど。
これはどういうことかっていうと、 誕生の歴史的には「オブジェクト化されたブロック」に過ぎなかったProcが、 その名前(ProcはProcedureの略だろう)と、他言語でからの類推により 無名関数として振る舞うことが期待され、期待とのズレが発生しているということなんでしょう。 lambdaなんて名前を用意している時点でこの期待は必然なんですが。
1.7ではこのズレをProcを実行する側(caller)が、 関数オブジェクト的に呼び出したい場合にはcall、 ブロック的に呼び出したい場合にはyieldで呼び出すことで対応しようと考えました。 ブロックの呼び出しにはyield文を使うわけですから、これはこれで自然かなと。
しかし、あるひとつのオブジェクトを関数的に呼んだり、ブロック的に呼んだりするもんでしょうか(いや、ない)。 とすると、ユーザにその選択を強制するのは不合理です。呼ばれ側(callee)がよしなに振る舞うべきでしょう。 コンピュータが決められることはコンピュータがやるべきです。
とうことで、新たにBlockクラスを導入して(BlockはProcのスーパークラス)、 ブロック引数で与えられるオブジェクトはBlock、 lambdaで与えられるオブジェクトはProcとするのはどうだろうか、と。 そうすると関数オブジェクトを期待する局面ではProcオブジェクトが得られ(Procの挙動は1.6までとほぼ互換)、 手続きオブジェクトを期待する局面ではBlockオブジェクトが得られてきれいにまとまるような気がしています。
問題は100%互換ではないことと、これを実現しようとするとeval.cをだいぶ修正しないといけないこと。
あと、パラメータ受渡のセマンティクスを見直すのも大変そう。でも、
lambda{|a| p a}.call(1,2) # => [1,2]
がエラーにならないこと(これもズレが原因)に不満を持っている人は多いわけで、 「親切な言語」を目指すRubyとしてはなんとか救済してあげたいんですよね。
昨年秋に発生した「テレビがテレビ台に入らない」という異状事態をやっと解消する。 テレビを買うときには高さ・幅だけでなく奥行きも確認しましょう。
今日になって出るとは。ペダルボートを漕いだ足が痛いぞ。うう。