Rebuild A Podcast by Tatsuhiko Miyagawa. Talking about Tech, Software Development and Gadgets.

Sep 23
2014

59: Ruby 3.0 Coming Soon (Matz)

収録時間: 22:33 | Download MP3 (16.7MB)

まつもとゆきひろさんをゲストに迎えて、Ruby 3.0 などについて話しました。(9/20 RubyKaigi 2014 にて収録)

00:00

miyagawa: これ聞いてる人はわからないかもしれないですけど、この RubyKaigi 中、まつもとさんのファッションがちょっといつもと違うという。

matz: あぁ、そうなんですよ。いつからだっけ、何ヶ月か前から Vasily っていう会社のお手伝いをしているんですけども、アルバイトみたいなことで(笑)

miyagawa: アルバイト(笑)

matz: そしたら Vasily が、RubyKaigi のスポンサーであると同時に、まつもとの服もコーディネートして存在感を高めたい、というプロポーザルがあってですね。いっつもTシャツにジーンズなので「え〜」とか思ったんですけど(笑)

あ、言ってなかったけど Vasily ってのは iQON っていうファッション系のアプリを出してるところなんですよね。ユーザが99%女の子らしいんだけど(笑) そういうファッション系のところなので、そういうこだわりというか、ファッションという軸からアピールしたいっていうので。「はぁ」って言って(笑) で、用意してもらった服を着ているんですけども、毎回。

miyagawa: あれですよね、スピーカーの人が、Tシャツとかラップトップの裏にステッカー貼ったりして、そういうのでスポンサーシップを募集っていうのも、たまにやってる人いますよね。

matz: うん。今回は、ちょっといつもと違う格好をすることによってアピールしてるっていう。いまのところ成功してるみたいな気がするので(笑)

miyagawa: いや、すごい「アレ?」っていう。

matz: 「Matzの格好が違う」って(笑) 「なんかTシャツじゃない」

miyagawa: 初日なんかレザージャケットみたいなの着てたじゃないですか。

matz: そうそう。なんかジャケット着てたよね。

miyagawa: びっくりしましたけどね。

01:44

miyagawa: 昨日キーノートで。

matz: はい、がんばりました。(笑)

miyagawa: お疲れ様でした。

matz: ていうか本当につかれた。

miyagawa: お疲れ様でした(笑)

matz: 先週が、バルセロナで BaRuCo っていうカンファレンスがあって、スペインのバルセロナで出席してきてキーノートで発表したんだけど。で、帰ってきて、次の日が会議があって、1日朝から晩まで。(笑) もう死にそうになったんだけど。で、へろへろになった状態で RubyKaigi に突入っていう。

miyagawa: (笑) これも Kaigi ですけどね。

matz: まあ、Kaigi だよねえ。Kaigi.

miyagawa: 内容的には、過去10年ぐらいの RubyConf とかのキーノートの発表で (Ruby) 2.0の話。

matz: そうそう。ずっと 2.0 を、10年ぐらいかけて2.0の話をしてきたんだけど、もう出ちゃったので 2.0 は(笑) そういうのもあって、ここ何年か、3年ぐらい未来の話をあんまりしてなかったんですよね。「〜しました」とか「〜してます」とかすごい Short-sight っていうか、今やってることみたいな話しかしてなかったんだけど。キーノートの醍醐味っていうか、「未来はこんな風になる!かもよ」みたいのが、結構持ちネタなので、復活させたいなあと思って、今回はそんな感じで。

miyagawa: 久しぶりですか、そういうのやるのは。

matz: 本当に、2010年以来だから、11,12,13 ... そうね、3年、4年ぶり?

miyagawa: このタイミングで Ruby 3.0。

matz: 風船を打ち上げた感じ。花火か(笑) 花火を打ち上げた感じ。

miyagawa: いままでの実績から言うと、3.0 が出るのはもうちょっと先だけども。。

matz: うん。ただねえ、毎年1ずつバージョンが進むと、2.9 まであと7年しかないので(笑)

miyagawa: そうですよね(笑) ないですよね。2.10をやらない、って決めたんであれば。

matz: 2.10をやらないって決めてるので。まあ、7年もあれば気が変わるには十分長いんだけど(笑)

miyagawa: (笑)

matz: いまのところそう思ってるので。できれば7年以内になんとか、現実化したいなあと。

miyagawa: またそこで、2.9.1と2.9.2でメジャー(バージョンアップ)みたいに、ケチケチしはじめる、っていう未来が見える気がしますけどね(笑)

matz: たしかに(笑) むかし 1.0出す前がだんだんひどくて。最初はゼロの下に数字2桁だったのね。0.95, 0.96 とか進んでたんだけど。だんだん遅くなってきて、0.99になったら、0.991とか、0.992とか。。さらには 0.9921999年何月何日とか(笑) だんだんゆっくりになるっていう。

miyagawa: でも一応今は SemVer (Semantic Versioning) 準 SemVer みたいに決めてますよね。

matz: まあ純粋な Semantic Version は Ruby みたいなプロジェクトにあんまり向かいないかなあ、っていう気がするので。みんなでちょっと話し合って、「準」Semantic Version っていう感じに。

miyagawa: そうですよね。

matz: で、期日がきたら出すっていうモデルにしてるので、ここのところは。

miyagawa: ただあれですよね、2.0 で言ってた、前のキーノートとかで言っていた2.0の機能も、2.0に辿り着く前に実装されたものもあるわけじゃないですか。1.9とかで。

matz: 1.9とか、そうだね、2.0にするって言ってたんだけど実際は1.9でやったものもたくさんありますよね。

miyagawa: そういう意味では昨日言ってた、その中で3.0になる前に2.xで誰かが実装してしまう、っていう可能性もあるわけですね。

matz: うん、十分ありえますね。言語の性質をまったく変えないですむものについては、2.いくつとかで出る可能性はありますよね。

05:16

miyagawa: 昨日発表されてたのが、JIT と...

matz: あぁ、一応リストに挙げたのは、Concurrency について考えたい、っていうのと、JITについて実現したいっていうのと、Static Typing!

miyagawa: そうですね。たぶん Concurrency については、この間出ていただいたときにちょっと話したのと、JIT についてはまた別の機会、ということで昨日はだいたいほとんどが、Static Typing とかアノテーションのほうに、使われてましたね。

matz: Concurrency は、実は僕と笹田くんでイメージがだいぶずれていて(笑)、意見の一致を見ていないので、まだ。勝手に僕がぶち上げると、笹田くんのアイデアを阻害することになるので。僕のアイデアよりも笹田くんのアイデアのほうがよいという可能性は十分にある、っていうか、どっちかっていうとそんな気がするので(笑) Concurrency、の一言しか言わなかったんですけどね。

で、JITのあたりは実装だから、言語的には何も変わらない。速くなりました、っていうぐらいだから。それは、やればいい、みたいな感じで。あと、Static Typing ね (笑)

miyagawa: そうですね。この間ゲストで出ていただいたときは話さなかったんですけど、松田さんにその後出てもらって、その時ちょっとまた、その #9999 の話をしたんですけど。

matz: はいはい。ちょっと出たみたいね。

miyagawa: あのプロポーザルも含めてですけど、そういう Static Typing したいっていう要望は結構あるんですかね。

matz: うーん、昔から時々出てくるんですよね。Static Typing。でも Ruby は Ruby だから、オプショナルにしないといけないねみたいな話をして。考えるのは私の仕事なので、毎回考えるんだけど、「うーん、やっぱダメだ」って(笑)

miyagawa: (笑) なにが気に入らないですか。

matz: 何がダメかっていうと、キーノートでも話したんだけど、Static Typing を入れたいって人はだいたい、スピードを速くしたい、っていうのと、コンパイル時のチェックをしたい、それから最後が、ドキュメントとして、「この引数、なんか名前が書いてあるんだけど、整数を渡したらいいのか文字列を渡したらいいのか」とかいうのが、型としてドキュメントの一部に含まれるので。だいたいはコメントの中に Integer って書いたりとか、あとは引数の名前を anInt とか、num とか書いてあったら、これ数字だな、っていうパターンが多いんだけど。明確に型で書いてあると、それがドキュメントとして、プログラムと統合された形でドキュメントになるのでうれしい、っていう3つメリットがあるっていう風にだいたいいわれてる。

でも、パフォーマンスについては、たとえば JavaScript の v8 であるとか、Lua の LuaJITとか、型とかなくてもめっちゃ速いんで、まあ、いらないかなぁと。(笑) そういう意味ではね。

コンパイル時のチェックと、ドキュメントというのは結構メリットがあって、リファクタリングとかしてる時に、変更し忘れのところとか、結構型でチェックできるので、それはそれでうれしい、っていうのはわかる。それからドキュメントも、だいたいコメントで書くから問題ないっていえば問題ないんだけど、統合された形で矛盾がない、「コメントのアップデート忘れました」っていうのがないのがうれしい。

miyagawa: そうですよね。

matz: まあ、その残りの2つはメリットして認めるところではある、っていうんだけど。だけど、静的な型を入れると、(沈黙) イヤなんですよ。(笑)

miyagawa: (笑)

matz: ていうのは何かっていうと、Ruby ってずっと Duck Typing みたいなものを全面に押し出してプログラムしてるわけで。そうすると、「ここには整数って書いてあるけど、整数のように振る舞うものだったらだいたいOK」みたいなことって、普通の Static Typing、えっと Nominal っていうんだけど、クラスが同じかどうかで型が一致してるかどうか判定するタイプの静的型だと、「これは String によく似てるんだけど String じゃない」ものを渡そうとすると「お前は String じゃないから」って断られちゃうわけですよね。

miyagawa: はい。

matz: それは Duck Typing を壊しちゃうので、イヤなんですよ。で、Ocaml とか Go みたいな、型は一致しなくても同じ構造を持っていればいい、Structural Subtyping, Structural な型だと、そういう Duck Typing みたいなことは出来るのでうれしいんだけど、そんな言語ってあんまりないんですよね (笑)

Ruby としては、Duck Typing はすごく重要なので。Duck Typing を維持した形でないと静的型は入れられないってのがまず第一。

あと、いままでずっと20年型なしでやってきたので (笑) 型がない資産が山のようにたまっているわけですよね。そうすると、「ここだけ型を入れましょう」みたいな話をしても、型がないところに行ったら、型情報は落ちていく。ないところを通るたびに減っていくわけですよね。そうすると、少ししかないとあっという間にゼロに近づいちゃう。結局あっても嬉しくない、っていう話になりがちなんですよね。型がないところを一箇所でも通ったらもうそこはダイナミックな型にならざるを得ないから、タイプチェックとか効かないし。引数の型とか数とかのチェックもできなくなるから。

で、やるんだったら、例えば JavaScript と TypeScript みたいな関係で、TypeScript の世界では全部型がありますと。JavaScript のライブラリを見に行く時には、なんだっけ d.ts...

miyagawa: Definitely Typed.

matz: 型定義ファイルを使って、一緒にくっつけると、TypeScript の世界に型が見える。そういうやり方で、TypeScript の中では99%型がある、外の世界とは型定義ファイルによって...

miyagawa: 変換される。

matz: 変換される。そういう風な形にしてやると、TypeScript の静的な型ってそれはそれでうれしいと思うんですよ。あれ、なぜか Structural な型チェックなんだけど (笑) なんだけど、でも ... JavaScript と TypeScript は違う言語だよね。

miyagawa: まぁ、JavaScript ではないですよね。

matz: なんで、Ruby に例えば TypeScript みたいに変更を ... TypeScript の方向に進化した Ruby って、それは Ruby じゃないよね(笑) っていうのがあって。それ Ruby 3.0 って呼んじゃいけないような気がする。違う言語。 Type なんとか (笑) TypeRuby (笑)

miyagawa: TypeRuby (笑)

matz: (笑) 違う言語だと思うのね。Ruby 3.0 にはふさわしくないだろうという。そういうのがあっちゃいけないとは言わないけど。そうすると、できることっていうのは...

12:06

matz: あ、もうひとつあった。DRY原則。プログラム書く時って、コンピュータにこれこれさせたい、っていうことを書くじゃないですか。普通の手続き型とかオブジェクト指向プログラミングだったら。関数型だったらまた別なんだろうけど。

そうすると、型っていうのは、Dynamic Typing な言語に対応してる型っていうのは「この手続の中に暗黙的に表現されている型」があるわけですよね。つまり「こういう手続きをした」ということによって、型がなんとなくぼんやりと表現されているわけ。

そこに、「この変数とかこの引数に型の情報を加える」っていうのは ... なんか ... 二度手間な気がするわけですよ。私にとって。

miyagawa: 本当はしなくてもいいんじゃないか、っていう。

matz: 本当はしなくてもいいじゃん、って。「おれは、明示的ではないんだけど、なんとなくこういうデータを要求している、ってプログラムで表現しているのに、もう1回いちいち整理してここに書かなくちゃいけない」っていうのは、なんかコンパイラの都合を押し付けられている気がして (笑) 結構イヤなんですよ。

そういうのを持って、言われるたびに「まぁ、便利なことはわかるんだけど、ちょっと入れられない」っていう風に思ってたんだけど。

ひとつは Soft-typing っていう技術で、さっき言った「プログラムによってなんとなくこういうデータ型が欲しいっていう表現」というのを抽出してくるという技術があって。それがあると、とりあえず静的型のうれしさと Dynamic Typing の言語の共存ができるんじゃないかっていうのが1つ。

もう1つは、言語のサブセットみたいなもの ... 言語の世界でサブセットっていうと、よく機能縮小版みたいなイメージがあるんだけど、そっちじゃなくて。例えば Ruby なら Ruby の文法が表現しうるあらゆるプログラムのうち、ある一定の制約を満たしたものだと、型推論がうまくいく、っていう。その範囲内でプログラムを書いているうちは、型推論が効くし、静的型チェックもできるんだけど、それを逸脱したら、普通の Ruby になるので、今までどおりできる、っていう。

その言語の部分集合みたいなアイデアを組み合わせると、今の言語を壊さないで、新しいバージョンの新しい言語を提供した上に、ユーザをなんとなく誘導できる (笑)「型チェックあったほうが嬉しいじゃん、だからこの範囲でやろうよ!」っていう (笑)

miyagawa: チェックが通りやすい範囲内の文法とかで書くってことですね。

matz: そうそう。Ruby は極端な話なんでも出来るので (笑) 実行中にクラス作りました、メソッドどんどん継ぎ足しました、みたいなプログラム書いちゃうと、静的な型チェックとかできようがないので。そこのところを諦めたら、型チェックがより広い範囲でできるよ、っていう風なやり方をすれば、Ruby 3.0 っていう言語の二重構造みたいなものを維持しながら、ユーザをいい方向に誘導できるし、ユーザもコンパイラ時のチェックとか、ドキュメントみたいなメリットを享受できるんじゃないか、っていうのが今回のキーノートで提示したアイデアの基本的なところなんですよね。

miyagawa: それってでも極論をいうと、あんまりメタプログラミングをしない方がいい、っていう話になっちゃいますよね。

matz: そう。うーん、そうだね。メタプログラミングの中でも、「変える」系のメタプログラミングはあんまりしないほうがいいね、っていう話。

miyagawa: でも例えば Rails とか、ActiveRecord とか、さっき Aaron とも話してましたけど。あれってデータベースにあるカラムがメソッド名に勝手になるわけじゃないですか、ロード時に。そういうのってスタティックなチェックでは限界がありますよね。

matz: うん。そうなので、その部分については諦めるっていうのがひとつ。つまり ActiveRecord のクラスが来た時には、こいつはメタプログラミングでメソッド生やしてるから、こいつについては型チェックできない、ごめんなさい、っていうアプローチが一つ。もう一つは、スキーマってそんなに頻繁に変わらないので、コードジェネレーションで作ってやればいいんじゃないかな、っていうのがもう一つ。どっちになるか、ってのはまだわからないけど。

miyagawa: 昨日キーノートのあとの質問で、メタプログラミングはやるとしても、だいたいプログラムの実行中の一番最初のフェーズにしかやらないから、そこの実行フェーズが終わった段階でもう1回チェックをいれてやるっていうのはどうか、っていう話もありました。

matz: そうですね、田中哲さんから質問があって。それはキーノートの準備をしてる間は全然思いつかなかったアイデアなので、それもアリかもしれないし。

昨日それでご飯食べに行ってたら、田中哲さんもいて (笑) 「ちょっとプロトタイプつくってみたんだけど」とか言って (笑) それは実行中のあるタイミングでクラス中にある全部のメソッドをなめて、メソッドの表を作っておいて。今回はチェックは簡単で、存在していないメソッドを呼んでいるところはないか、っていうのをチェックする。そういうプログラムだったんだけど。「30分でできた」とかいって (笑) キーノートの燃料効果おそるべし (笑)

miyagawa: それは結局、コンパイルタイムというよりは実行時ですよね。

matz: 実行時。実行時なんだけど、網羅的にチェックする。

miyagawa: それはもし AST をとれるようになれば、実行する前にわかるようになる?

matz: えーっと。

miyagawa: あ、そうか、define_method とかしちゃってるから。

matz: そうそう、define_method とかしてても、あるタイミングで存在してる全部のクラスを見るっていう感じ、のものでした。Ruby の Instruction Sequence っていうのをなめて、中の存在してるメソッド呼び出しを全部取り出してきて、存在してるかチェックするみたいな。

miyagawa: そういうのが、「とりあえずやってみました」っていうのが Kaigi 中、カンファレンス中に起こってしまうのが面白いですね。

matz: うん。10年かかるかと思ったら、30分でプロトタイプでてきたっていう (笑)

miyagawa: (笑)

18:23

miyagawa: でも、どうなんですかね。アノテーションとして使いたいっていう話だと、「アノテーションしなくても Ruby はわかってますから」っていう風に持って行きたいわけですよね、まつもとさんとしては。でもそれだとプログラマ同士のコミュニケーションのツールとしてアノテーションを使いたいという要望も多分あると思っていて。

matz: さっきのドキュメントの部分だよね。

miyagawa: そうです。そうすると、たとえば git のレポジトリの diff を見た時に、「ここの引数の型が変わったんだな」っていうのがコードに表現されているからわかると思うんですけど、「Ruby の実行系は知っているからコードに書かなくていい」っていうことだと、diff を追っていった時に、変わっているんだけど「ここの型はなんで変わったのか」っていうのはコード上には残っていないよう気がするんですよ。

matz: うん。diff とかだと難しいんだけど、プログラムそのものだと、コンパイラがアクティブに情報を教えてくれたらいいんじゃないかな、と思ってるんですよ。つまり、「このプログラム書きました、解析しました、型チェックが合ってました、間違ってました」これは普通ですよね。推論した結果、「この引数はこういうメソッドを受け付けるこういう型をあなたは期待してたでしょ」っていうのを積極的に教えてくれると、情報になるんじゃないかなと。

プログラムの字面上だと、diff とかだと文字だけしかないのでその情報を取り出しにくいんだけど、プログラム全体として存在していると、その部分は教えてくれるような形ができるんじゃないかな、と思って。

一番シンプルな形だと、推論した結果をコメントで埋め込むっていうのがシンプルな結果なんだけど、本当はもうちょっとカッコいい、IDE みたいにポップアウトで出てくる、みたいなのがしたいんだけど。

miyagawa: Ruby の実行系がコンパイルした結果をファイルとかに落としておいて。

matz: そうそう、データベースか何かにとっておいて。

miyagawa: IDE で Git のある時点に戻ったら、「その時はこういう風に Ruby は考えてました」ってのがビジュアルで見れれば、ってことですよね。

matz: そういうのが理想ですね。とりあえず、フロントエンドは IDE なのか Emacs なのか vi なのかわからないから (笑) なんとも言えないんだけど、少なくともそこが提供できるような、例えばデータベースであるとか、ファイルであるとか、API であるとかがあると、そっちに聞きに行くことによって、プログラムを見て「このプログラムはこの引数にこれを期待してるんだ」ってことを、「Ruby はこれを期待してるって思ってるんだ」っていうのを教えてもらえるし。プログラムを書いている人は、私の期待と Ruby の推論があってたか、間違ってたかってのを知るっていうのがドキュメントの代わりになるんじゃないかなと。

miyagawa: ちなみに今って、Ruby の実行系にはそういうコンパイルタイムにどういう情報が得られましたっていうのをとれるインターフェースとか API とかはあるんですか?

matz: ない。今までは、他の言語もたいがいそうなんだけど、大体一方通行なんですよね。プログラム書きました、コンパイラにかけました、結果がでました。間違いがあったら、エラーメッセージが出る。けど、それ以上のことはあんまり教えてくれないんですよね。型推論とかしている言語だと、もっと情報はコンパイラが持ってるんだけど、それはユーザにあんまり教えてもらえなくて、成功した場合は。一方通行なんだけど、そろそろインタラクションしてもいいんじゃないかなあと。(笑)

miyagawa: そうですよね。Perl も昔 MAD っていうモードがあって、コンパイラがコンパイルした結果を XML で吐き出す、っていう謎機能があったんですけど。Larry Wall が作って、誰もメンテできなくなったので (笑) 最近消えちゃいましたけどね。

matz: Larry も似たようなことを考えていたのかもしれない (笑)

miyagawa: (笑) じゃあ、来年以降 RubyKaigi とかで、また 3.0 の話を。

matz: また与太話をね (笑)

miyagawa: これから何年か続いていくという。

matz: 当たるも八卦当たらぬも八卦という話が、これからできるといいなあ、と思っています。

miyagawa: やっぱりたまにこういう燃料を投下すると、コミュニティ的に「未来がこうなっていくぞ」っていう期待感とかワクワク感とかがでてくるので。

matz: そうですね。「我々は衰退してるんじゃない」っていうのを感じられるっていうのは大事なことだと思うので。そういう燃料投下がぼくの仕事ですから、コミュニティリーダーとしての (笑)

miyagawa: なるほど。そうですね、そんな感じで。ありがとうございました。

matz: ありがとうございます。というわけで、Ruby 3.0 でした。

miyagawa: 楽しみにしています。

matz: がんばります (笑)