昨日のエントリでもすこし触れたが、 ブロックパラメータの文法を変更したい気持ちがある。 理由は、昨日述べた通り「メソッド引数リストと同じ文法を使えない」からだ。 yaccをあきらめてパーザをもっとずっと複雑にすれば不可能ではないかもしれないけど。
jijixiさんからツッコミでは(冗談とはいえ)、 Groovyの -> を逆輸入することが提案されていたが、これはあんまりうまくない。
新しい文法への要求としては
である。Groovyの -> はyaccを使う限り、2番目の要求を満たさないと思う。
ちょっと考えて思い付くのは以下のようなものか。
Perl6風無名関数
Groovy同様 -> を使うが、こちらは
-> (x,y) { ... }
のようなもの。Perl6では
foreach ary -> (x) { print x; }
という感じで使う。
こっちの方が見栄えがよいような気がするな。 でも、この場合、-> は引数リストと本体との区切りではなく「lambdaの代わり」になっているな。 ブロックとして使う場合は
{ -> (x, y) ... }
か。なんか変だな。
新しい予約語を使う
昔々、ブロックが導入される前のRubyの文法を検討したメモには「using」という予約語を使う文法を考えていたことが示されている。これを復活させるか。
{ using x, y; ...}
あんまりパラメータらしくないな。やはりメソッド引数宣言に似た文法(つまり括弧で囲まれているということか)が良さそうだ。
lambdaを拡張
結局、メソッド引数のすべての文法が欲しくなるのは無名関数の場合であって、 インラインブロックの文法は今のままで構わないというのもひとつの見識だ。
そこで、lambdaを予約語としてしまうのはどうだろうか。
lambda(x,y) {....}
インラインブロックでたとえばオプショナル引数が指定したい場合には、
foo(args, &lambda(x=15){...})
のように指定することになるだろう。こういうケースはまれだろうから、 積極的に短くすることを支援しなくても良い。
別の記号
しかし、それでもlambdaは長い。では、別の記号を導入するか。 先ほどのPerl6における -> でも良い。Haskellではlambdaはバックスラッシュを使っていなかっただろうか。
\(x,y) { ....}
うーむ、一目で意味が分からないぞ。慣れたらなんとかなるものなのだろうか。 また、フォントによってはバックスラッシュでなく円記号に見えるのもうまくない。
と、考えを撒き散らすだけで、結論はない。
ライセンスの懸念を解消するため、 missingの下にあるerf.cとcrypt.cを4.4BSDからのものに置換。 しかし、そのままではコンパイルできず各方面に迷惑をかけてしまった。
あ、crypt.cはともかくerf.cは奥村先生に連絡を取ってpublic domainの確認を取れば良かったんでないか。 今、気がついた。どうしたもんだか。
あれ、どの論文ですか? GC のだったらもうちょっと詳しく聞きたいかも。
method{(a, b=2, *c, &d) ...} とかだと何かに衝突しますかね。
あ、普通に単項の括弧とか駄目駄目ですね。失礼しました。
マルチバイト文字必須にして、λをキーワードにするんですよ!
I like both the using and the lambda notation, but I guess the lambda notation would not be easy to distinguish from objectified blocks. Are you thinking about making passing a lambda as last argument or a block the same thing? I think it could work out then, but it seems radical.
(Sorry for the English posting.)
■>[論文]不採録■
TBSで天気予報を担当している森田正光さんが、第1回の気象予報士の試験に落ちてしまったときのことを思い出しました。
Googleで"森田正光" AND "不合格"という検索式で検索したら、東京都新島村の「島民塾」での講演の抜粋が見つかりました。
1995年10月21日(土曜日)に『森田正光の人生晴れたり曇ったり』というテーマで講演しています。
【引用ここから→】この様に私の人生は失敗から違う展開に発展し出世していきましたが、最大の失敗は気象予報士試験の失敗で、合格の記者会見になるはずが不合格の会見になり、当時テレビ局の方や回りの方はやめさせようとしましたが、私自身で会見をやることを決意し逃げなかった事と試験問題の批判などしなかった事に対してマスコミが好意的に報道してくれました。失敗したら愚痴らずに、ほとんどの事は取り返しがきくものです。そこでどんな態度をとるかがすごく重要な事です。【引用終わり】
第1回の気象予報士の試験はいつだったのか『朝日新聞』のデータベースで"森田正光"AND"気象予報士"、検索の範囲を1995年10月21日以前、として検索したら、1994年10月3日の夕刊11面に『フジ、テレ朝は「晴れ」 「気象予報士」合格発表で民放、明暗 』という見出しの記事が見つかりました。
【引用ここから→】民間で独自の天気予報ができる「気象予報士」の初の国家試験で、日本気象協会所属の天気キャスター以外で合格した民放キー局の天気番組関係者は、フジテレビとテレビ朝日の一人ずつだけだった。十二人受験のTBSは全員不合格。独自の天気予報を番組の目玉にしようとした局にとっては思惑がはずれた格好だ。合格発表は九月三十日に行われ、合格率は一八%だった。(中略)一方、「局独自の予報を出したい」と受験に積極的だったTBSは、看板キャスターの森田正光さんを含む十二人の受験者全員が不合格。【引用終わり】
"lambda"の代わりに"fun"とか。
本当に可能かどうか自信はありませんが、
|x|に追加して<|a, b=2|>とか|>*c, &d<|とか|^x^|とか。
ところで、ブロックパラメータにブロック引数が書けるということは
yieldにブロックパラメータを以下のようなプログラムも動くことになるんでしょうか。
def foo; yield { yield { |x| x } }; end
foo { yield { yield 1 } }
Kiyoshiさん:
えー、落ちても前向きに行きたいものです。基本的なアイディアからだめだと言われたわけではないので、再挑戦しようと思います。
ななしんさん:
yieldにブロックを渡せるようにするかという点は最近もruby-talkで話題になり、なかださんがパッチも作っていますが、yieldにブロックを渡せてもうれしいケースが思い付かないので、あえて追加して文法を複雑にするよりも、どうしてもやりたければブロック引数で受けてcallにブロックを渡してくれ、ということにしようと思っています。
def (引数){ブロック}
とかじゃ駄目なんでしょうか?
defってのは「define」の略で単語そのものにメソッドという意味が含まれていませんから、名前を省略したら無名関数の宣言になるってのはあんまり良くないんじゃないかと思います。その点でPerlのsub(たぶんsubroutineの略)とはちょっと事情が違いますよね。
あとたぶん、特異メソッド定義と衝突しそうな予感。
メソッドという意味が含まれてない、という点については、
def aaa;end
というお馴染みのメソッド定義も、既に違和感有ったぞと言えちゃうわけでして、
そのへんどうなんでしょう?
(それとももしかしてdef自体も改称しようとしてるのですか?)
def 値.(引数){ブロック}
と書くと今はエラーになるようですから、
特異メソッドともぶつからないかな、と
思いました(浅慮な勘違いだったらすみません)。
defを改称するつもりはありません。
確かにdefには定義という意味しかありませんが、Rubyで定義するもののうちもっとも頻繁に登場すると想定されたメソッド定義にdefという予約語を割り当てたことについては後悔していません。
ただ、guionさんの提案されたdefの使い方は「定義」ではないので、メソッドという意味を持たず、定義でさえないものに、defという予約語を使うのには賛成できません。
特異メソッドとの重複に関してですが、エラーになるからといって、現在の文法と衝突せずに定義できるとは限りません、ということで。いや、yaccを捨てれば簡単に実現できるのかもしれませんが、それは勘弁してください。
括弧があると任意の式に対して特異メソッドを定義できます。
$ ruby -vwce 'def (Object.new).foo; "foo"; end'
ruby 1.9.0 (2005-07-04) [i386-cygwin]
Syntax OK
なかださん:
その括弧の中身が、上で私が書いた「値」の部分を意味しているつもりでした。
特異メソッドなら「def 値.メソッド名」というふうにメソッド名を略せないわけですから、
区別は可能かなと思ったんですが、
そういうのはyaccの限界を越えるという奴なんでしょうか?(すみません、私は知らないんで)
まつもとさん:
結局、ブロック作るのとメソッド作るのとを、別物と見るか否かという話でしょうね。
私は、両者を根本的には同じと見なしてしまって、
かつ従来と文法(の見た目)を出来るだけ同じにしようとしたら
こんな感じになるんじゃないか、と思ったものを提案してみました。
そういえばメソッド定義式がnilを返すのには
(今および将来にとって)どんな意味があるのでしょう?
MethodかUnboundMethodか(それともProcか)の何れかが返される、
という仕様を予定してるんでしょうか?
rubyの場合、メソッド「定義」という考え方は、風前の灯火であるように感じています。
動的言語だし、1つのクラスに後付けでメソッドつけれるし、
それどころかPrototypeOOPの要素まで有る(しかも文法は概ね地続き)んで、
「定義する」というよりは「ぽっと書いてぽっと付ける」という"印象"を受けています。
Procやブロックとは、そう遠くないものとして
考えてらっしゃったのかな、と思っていました。
まつもとさんが「定義」か否かという点に
拘りを持ってらっしゃる(、のですよね?)のは
そういう意味で、少々意外でした。
yieldにブロックは無しの方向ですか。
一貫性が少し気になりますが、意味のあるコード例が思いつかなかったのでそれでいいのかも知れませんね。
guionさん:
defは「ぽっと書いて(メソッド名とセットで)ぽっと付ける」、
lambda(?)は「ぽっと書いて何にも付けない(いわば匿名関数)」という違いがあるのではないでしょうか。
MLのlet f x = xとfun x -> xの関係にあるような気がします。(だからfunを提案しました)
勘違いだったらすみません。
ななしんさん:
(rubyはという意味ではなく一般論として)
defのたぐいは「lambdaして名前付ける」の構文(?)糖
ってことにすりゃいいじゃん、と最近思っているものでして…(^^;
すくなくともrubyはOOPLなわけで、インスタンスメソッドとlambdaは環境の取り扱いが全く同一にはできませんよね(つまり変数selfに束縛されているオブジェクトがprocでは固定なのに対し、特異メソッドでない普通のメソッドでは固定できない)。
このへんがすっきり統一できないようであればdefとlambdaを同一視することには賛成できないなぁ。
mputさんが指摘しておられるようにメソッドとlambdaは同一のものではないので、単純に「lambdaして名前つける」というわけにはいかないと思います。さらに言えば、仮に「lambdaして名前つける」ものだとしたとしても、defが「名前つける」の方を表現した名称である以上、そっちを取り除いた単なるlambdaにdefという名前をつけてはいけないと思います。
なお、defが意味のある値を返さない理由は、1)現状ではdefする度にMethodオブジェクトをわざわざ作るのは効率が悪い、 2)では他に返すものがあるかと言えば思い付かないし、下手なもの(たとえばシンボル)を返して将来の可能性の芽を摘みたくない、というものです。
あと、guionさんが「定義」という言葉にいだいていらっしゃるイメージがつかめませんでした。私にとってdefineはschemeのdefineと同様、代入とさほど差がないのですが。なにかもっと固いものをイメージしていらっしゃいますか。
JavaScriptだと
この言語がどういう仕組みになってるのかまだ理解してないんですが(^^;、
(例として拝借:http://www.fobj.com/hisa/d/20050609.html#p01)
無名関数でthisが旨いこと(?)使えてるように見えます。
個人的な理想はこういう感じかな。
ruby(みたいな文法の言語)で、
{|self,a,b| self.x=a+b}
なんて(selfもまた引数の1つとして)書きたい衝動に駆られることが有ります。
あとdefという単語には拘りは無いです。
ソースの字面を従来と似せたいという点を除けば。
だから、defじゃなくfunなりmthなりでも私は構いません。
で、かつ、Procと同一(あるいは近縁)視できるのが理想、と。
defineと代入は、私にとっても「同じようなもんじゃん」です。
むしろ逆に、まつもとさんが持っているイメージのほうが
もっと固いものなのかな?と思っていました。
(で、それに話を合わせたという格好。よくある一人相撲アンチパターンですね。)
で、同じようなものなら、やっぱり
def hoge;end
と
hoge = 無名関数作るぞ;end
とがイコールだといいなぁとは思います。
前にも言いましたが、guionさんが欲しい言語の話はRubyとは独立でお願いします。
っていうか、自分で作れば良いのに。
この私の案がRubyに入り込む余地は有るのか、
無いとすればそれは技術的必然なのかそれとも"判断"なのか、
を知りたいわけです。
言語が、GNOMEの作者が言ったような意味での
"2000行で(しかもあまりヒネらずに)作れる"もの
であるならば良かったんですが、
どうもそうでないので、
実用:-)言語の中で気に入ってるものに対して
肩乗りというズルをしたくなったりします。
つまり「Ruby+何か」ということです。
10年覚悟で(いちから)作るのは、それはそれで(また別の)欲求としてアリではありますが。
というか、作る速さと、出来と、流行り度(^^;のバランスという点において
目標とすべき(もしそれが目標ならば)は、 Groovyなのかも知れない。
私の見るところ、Rubyはguionさんの趣味に完全にあわせるには距離がありすぎるようです。メソッドは(明示的にオブジェクトするまで)独立したオブジェクトじゃありませんし。schemeやpython、javascriptの方が近いんじゃないでしょうか。
nil( ){ } ?( ){ } ..( ){ }
その他、??、def?、nil? など...
※ 2005-06-07 [Ruby]ブロックターミネータ に "-;" を提案し、投稿しておきました。
↑ って書いておかないと気づかないよな