2025年5月28日に『深堀りRubyKaigi 2025 with tompng & ima1zumi』を開催しました。深堀りRubyKaigiはRubyKaigi 2022からはじめており、今回で4回目です。
イベントの内容をほぼ全文文字起こし形式でお届けします。この記事は前編です。
- 登場人物
- Excelで円周率の100桁を計算
- Rubyとの出会い
- Quineとの出会い
- IRBの開発について
- オープンソースと仕事の違い
- Relineのリアーキテクチャ
- 今後の展望
- AIとの連携
- BigDecimal
登場人物
ゲスト
- tompng/石田 智也氏
- ima1zumi/今泉 麻里
聞き手
- fujimura/藤村 大介
- mame/遠藤 侑介
Excelで円周率の100桁を計算
fujimura: 深堀りRubyKaigiは、RubyKaigiのスピーカーをお招きして、話しきれなかったこと、もっと詳しく聞いてみたいことを聞くイベントです。ホストは僕、STORES のCTOの藤村と申します。mameさんもお願いします。
mame: こんにちは、STORES でフルタイムRubyコミッターをしている遠藤と申します。よろしくお願いします。
fujimura: では早速本編に入ります。お二人いるんですけど、まずtompngさんから伺っていきます。簡単に自己紹介をお願いします。
tompng: 2024年12月にRubyコミッターになったtompngと言います。もともとIRB Relineのメンテをしていて、今ちょっとRDocとか他いくつか手を出したりしています。よろしくお願いします。
fujimura: よろしくお願いします。プログラミングはいつから始めたんですか?
tompng: 高校2年生からです。C言語をやっているクラスメイトがいて、教えてもらいながら始めました。あとは、中学の時にExcelをプログラミングするものだと思っていて、表計算で円周率の100桁を計算してました。今はBigDecimalに手を出して、すごく昔にやってたなと思ったりしてます。
fujimura: Excelで円周率を出すって、Excelの関数で出すんですか?
tompng: Excelのセルを、最初の10桁、次の10桁、その次の10桁ってして、次の計算する計算式を書いたセルをコピペして、縦にコピペすると、すごく下の方に円周率が100桁くらい出せたりする。
fujimura: なんでそれをやろうって思ったんですか?
tompng: 他にプログラミングっぽいことをする道具を知らなかったからっていうのと、数学がちょっと好きだった。
fujimura: じゃあ数学はもともとモチベーションだったんですね。
tompng: 最初は。
fujimura: その後もコンピュータ系の勉強をされてたんですか?
tompng: 大学は理学部だったので、プログラミングは趣味でずっとやってました。
fujimura: キャリアのはじめはプログラマーですか?
tompng: そうですね。
Rubyとの出会い
fujimura: Rubyはいつごろ発見されたんですか?
tompng: 10年以上くらい前に、沖縄のGeek Houseっていうシェアハウスに住んでいて、そこが毎週Rubyのミートアップの会場だったということから始めました。
ima1zumi: 最初に触ったRubyのバージョンはいくつだったか覚えてますか?1.9以降?
tompng: 多分1.9以降。1.8スタイルが残ってたり、残ってなかったりだった。
fujimura: ima1zumiさんがはじめて触ったバージョンは何でしたか?
ima1zumi: 2.6ですね。
fujimura: 遠藤さんにオチをつけてもらおうと思ってるんですけど、僕は1.8.7だったんですよ。遠藤さんは?
mame: 実はRuby歴はそんなに深くなくて、最初に触ったのは1.8だと思いますよ。
fujimura: そうなんですね。
mame: まともにRubyを触り始めたのは2002年か2004年かなので、全然ペーペーです。
fujimura: とはいえ20年前ですからね。tompngさんの話に戻ると、そこからRubyは面白くなってきた?
tompng: そうですね、だいぶ好き勝手させてくれる言語じゃないですか。
fujimura: 仕事もRuby、Railsのことが多かったですか?
tompng: Railsです。
fujimura: tompngさんがどういうRailsを書いてるのか気になる。
tompng: 今会社でやってるのは、フロントエンドも頑張る必要があって、学校の授業中に使うリアルタイムで先生と生徒で共有されているノートアプリです。Railsもだけど、JavaScriptのキャンバスもあるし、ロードせずに全部画面に配置されてほしいというところで、RailsでActiveRecordのhooksを触って、勝手に通知を飛ばしたりとか、いろいろやってます。
ima1zumi: 東京Ruby会議12で話してたような?
tompng: それです。
fujimura: 奇妙なRailsを書かないんですか?
tompng: 奇妙なことするのはライブラリに閉じ込めて、Railsのほうではなるべくそういうのはしないほうがいいですよね。
fujimura: そうですよね。
Quineとの出会い
fujimura: RubyKaigi 2024でみんな目の当たりにしたと思うんですけど、tompngさんはすごい奇妙なコードを書くじゃないですか。tompngさんの歴史の中で、いつから始まったんですか?
tompng: ちょっと変なのは昔から書き捨てたりとかはあったんじゃないかなと思うんですけど、Okinawa.rbで一時期Quineが流行ってたんですよ。そこでQuineに出会って、Quineだけじゃなくてmethod_missingで面白いことをしてました。
fujimura: 道を外したんですね。
tompng: いいじゃないですか、method_missing。
fujimura: Quineをやるにあたって、最初からすらすら書けたわけじゃないと思うんですよ。どうやってtompngさんはQuineという技術を習得していったんですか?
tompng: 本を読んで勉強するよりも、そういうテクニックを自分で見つける方が楽しいなと思って、色々と試行錯誤をしながらちょっとずつやってます。
mame: 無からQuineを書いたんですか?
tompng: 流行ってた時にこういう感じで書くんだっていうのは見て、そこからはなるべくあんまり見ないようにしてます。変化するQuineがあるじゃないですか、AからBになってBからBになって、それ以降はなるべく完成品は見るけど中身は自分で考える。
mame: なぜ?チートだから?
tompng: 一番楽しいところを自分でやりたいじゃないですか。
mame: なるほど、わかります。
fujimura: これはmameさんにもtompngさんにも聞いてみたいですけど、Quineテクニック集みたいなのは、mameさんとtompngさんで共有されているものが多いんですか?それともこの人のこの技は知らんみたいな?
mame: 基本的なところはなんとなくみんな知ってるかなって感じです。
fujimura: みんな知っている。
mame: 今年のトリックで僕が銀賞をもらったやつは前回のtompngさんの金魚のやつで使われていた、文字が1個も動かないように絵を描くっていう方法をこっそり踏まえてますね。技術はこっそりパクリあって進化していってるんだと思います。たぶん誰も気がつかない、tompngさんぐらいしか気がつかないレベルの細かいパクリなんですよ。
tompng: 使ってそうだなと思いました。
fujimura: わかるんだ。最近、Quineで新しく開拓中の技とかあるんですか?
mame: 今IOCCCが開催されているんですね。そこで作っているものがあるんですけど、それはまだちょっと言えないです。
fujimura: tompngさんも参戦中?
tompng: 参戦してみようかなと。
ima1zumi: IOCCCはC言語ですよね?
tompng: C言語でQuineどう書くんだろうってよくわからないんですよね。
mame: それはいろいろ発見していただいて。
fujimura: 教えないんだ。
参加者: 言語ごとにQuineを書く方法って変わるんですか?
mame: 結構違いますね。一番わかりやすいのはevalが使えるかどうかで大きく方向が変わりますし、Cはevalが使えないけどマクロがいい感じに使えて、C専用のハックがいろいろありますね。……いや、この話はやめましょう。
IRBの開発について
fujimura: RubyKaigiのトークの話を聞こうと思うんですけど、Rubyの様々な言語仕様をどこまでカバーするかっていうのが大変なお仕事なのかなって思ってるんですよ。ハイライトは諦めるしかないとか、補完はここまでくると無理だなみたいな、辛いあるいは諦めるしかないみたいなのってあるんですか?
tompng: ありますね。エンドレスメソッド定義の後、あのところ、=の直後に長い改行を入れたくなったりすると思うんですけど、そういうところの一段インデント深くしたいっていうのは完全に諦めているところで、やるべきかどうかもわからないんですけど。Ripperでトークンに分けた後でそこを=の中に入って、いつで終わるかっていう判定するのがちょっと難しいので無理にしないほうがいいだろうと。 一方でPrismで書き換えるって発表したんですけど、それだとできそうな気はして、頑張ってみてもいいかもな。試してみてちょっと諦めることになるかもしれない。
fujimura: まだまだ研究の余地ありっていう感じですね。
tompng: そんな感じで今まで諦めてたものとかも多分あるかな。すぐには思い出せないけど。
fujimura: すごい大変だったけどできたとか、意外とできちゃったみたいなこともあるんですか?
tompng: 大変でできた場合って本当に入れるのか悩むじゃないですか。思ったよりも簡単だったならいいけど、それをメンテするのは大変そうとか、IRBだったら別にできなくてもいいやつもあるし、そこで無理してメンテしにくくなるのも辛いなっていう。
fujimura: 現実的なユースケースがどのぐらいあるかと、そのコードを抱えるメンテナンスコストのせめぎあいが常にある?
tompng: あとはレビューに負担をかけすぎたくないな。あんまり書き換えてgitの歴史が見づらくなるのもなとかっていうのも気にするかな。
mame: git logはさすがに気にしなくていいんじゃないですか。それで進化を止めるのは本末転倒のような気がしますけどね。
オープンソースと仕事の違い
fujimura: オープンソースのライブラリを、しかも人々が使っているライブラリのメンテナンスをするときって、そういうトレードオフが常にあると思うんですけど、仕事のコードとの違いはあります?
tompng: 仕事のコードとの違い、仕事もちょっとメンテ厳しいけど入れなきゃっていうのがあったりもするっていう点では違いつつ、とはいえ長い目で見るとやっぱりそれを入れたらちょっと厳しすぎて無理だよっていうのはちゃんと弾かなきゃいけないっていう点では一緒。ちょっと基準がずれるだけで一緒なんじゃないかな。
fujimura: 仕事の方がやっぱりちょっと下がるというか、まあまあ入れるかみたいな。
tompng: そうですね。
fujimura: その判断の基準が、オープンソースのライブラリのメンテナンスをしてる人は、どのくらいまでやっていいのかのヘッドルームが高いのが面白いなと思ってましたね。
mame: IRBの開発状況はあんまり知らないんですけど、レビューが大変っていうのは誰がレビューするんですか?
tompng: Relineで差分が大きいやつは辛かった。
ima1zumi: 合計2,000行ぐらいの差分は、できるだけ丁寧にレビューしました。それはRelineにとって意味的にも大きな変更だったので。 IRB Relineチームは、作者の糸柳さんがアクティブじゃなくなってメンテナーに入った人たちなので、誰もすごく詳しいわけじゃないけど、思いを持っている人たちが集まっています。なので、最初に相互レビューを入れましょうと決めたんですよね。テストの変更だけじゃないときはレビューするようにっていう運用で回ってますね。私が止めちゃったりもするんですけど。
mame: Ruby本体よりすごいですね、ちゃんとしてる。Ruby本体は誰のレビューもなくても、mergeボタンを押すときは押すっていう感じです。
ima1zumi: その辺はちょっと仕事っぽいですね、approveもらってからやってるという。
fujimura: IRB Relineのチームってどんな分担でやってるんですか?
ima1zumi: 4人いて、tompngさん、Stanさん、はすみさんと私。基本tompngさんは両方を見てて、Stanさんが主にIRBを見て、私は主にRelineを見て、はすみさんは最近はPicoRubyが忙しそうって感じですね。
fujimura: リポジトリごとに主担当みたいな、よく見てる領域がある?
ima1zumi: そうですね。tompngさんは両方見てるからすごいなって思ってます。
tompng: みんな興味のある部分を見てるから、人それぞれでちょっとずれてる。特に担当があるわけじゃないけど、気になるところは違いますよね。
fujimura: ここは足りない人手不足だ!みたいなのはあるんですか?今のみんなでいい感じにカバレッジできている?
ima1zumi: WindowsのRelineじゃないですか。WindowsのネイティブのRelineはメンテナーでWindowsマシンを持ってる人がいないので、不具合報告をもらっても再現するのが難しいという課題がありますね。
参加者: はすみさんは持っているんじゃない?
mame: Windowsを持っていても、Windowsのテストができるかっていうと別の話なんですよね。WSLでやってるんじゃないかって話だったんですけど、僕はまさにそのパターンで、Windowsマシン使ってるけどWindows Nativeの環境をビルドしたのが何年前だろうみたいな感じですね。
ima1zumi: あと他にありますかね。
tompng: 割と片付けた気がするからそんなに思いつかないんですよね。
ima1zumi: 欲しい新機能があれば是非って感じです。
参加者: 右代入で値を返してほしい。
ima1zumi: でもそれを、値返さないためのテクニックとして使ってる人がいるんですよ。(笑)
mame: 今のIRBに足してほしいものがあります。tompngさんのeaster-egg.rbを足してください。僕が書いた、Rubyが踊るような感じのeaster-egg.rbが入ってるんですけど、どんどん増やせるような感じの書き方で、ケース分で大きく取って、間口を広く取っていますので、tompngさん用のやつもちゃんと足してもらえれば。
tompng: 考えてみようかな。
mame: 年末までによろしくお願いします。
参加者: IRBでデバッガーを起動した時にHistoryが分かれてしまう。IRB側とデバッガー側で。
ima1zumi: 確かに。裏側は同じRelineのはずなので何かできるかな。RelineのHistoryを読んでる定数が、debug.gem側にポンと置いてあったような気がする。コードを見ないと思い出せない。
tompng: それを読み出してセーブするのはIRBで、何か変なことが起きるのかな…。そういう連携のところは難しいですね。いろんな穴がありそうな気がするので、ぜひ見つけて報告してもらえると助かります。
Relineのリアーキテクチャ
fujimura: tompngさんのブログで、Relineのリアーキテクチャの話もしようかと思っていたってのを見たんですけど、どんなことをされたんですか?
tompng: 大阪Ruby会議04の話だったんですけど。いまいずみさんのKeynoteにも関連する家族絵文字をRelineに入れた時に、どうなるんでしたっけ?
ima1zumi: カーソル位置がおかしくなる。
tompng: Reline側の、それをちゃんと扱ってないっていうバグの他に、とはいえ、そうはならないような気がする挙動があって。
ima1zumi: ダイアログを出した後に表示崩れが起きやすいとかもありましたよね。
tompng: 画面を更新する時に変になるんですけど、内部でカーソルがこの位置にあるっていう状態を持てばいいところを、画面上でカーソルがここに表示されてる、あとはこの行の最大長が何かという、いろんなデータを重複して持っていて、それが食い違う問題があって。 食い違うのを全部穴を塞いで食い違わないようにすることもできますが、そうではなくて食い違うようなデータを持てないようにするほうがいいっていう、内部のデータの持ち方と状態の重複を排除すること。そこから画面に反映する時に、Reactって状態からレンダリングしてるじゃないですか。そうじゃないようなやり方をしてて、WebでいうとDOMを直接いじってるような感じですね。そういうのをやめて、ちゃんと状態からレンダリングしたら、ありとあらゆる問題が解決するっていうのをやってました。
fujimura: 段階的にやれるものなんですか?
tompng: 小さく分けようとしたんですが、でかくなっちゃったんですよね。
ima1zumi: いくつか前準備のPRはありましたけど、結局一番コアの部分は、どうしてもインスタンス変数を減らしたり、そういった処理でやってたものを別の機能にっていうのがあったので、一気に変更しました。でも全体としてはコードも減ったし、インスタンス変数も減りましたよね?
tompng: だいぶ減りましたよね。
ima1zumi: 10個ぐらい減ったような。
tompng: 内部の状態はちょっとでいいはずなのに、たくさん持ってたから。
fujimura: 今はその辺は気持ちいい状態になってる?
ima1zumi: そうですね、機能追加もしやすい状態になって健康になりました。
tompng: ima1zumiさんのRubyKaigi 2024で発表した、undo/redoを実装したやつも、それがなかったら実装したくないですよね。
ima1zumi: ですね。Relineの処理に入るところと出るところでundo/redoができるように履歴を保存するのをやったんですけど、tompngさんのリファクタリング前だと、文字入力をするとインスタンス変数のカーソルの位置が動くみたいな、そのメソッド内で完結して、だから文字を追加したり削除したりする時の操作がコード内にたくさんいろんな箇所に散らばってるし、たまに漏れてたりするみたいな状態でした。その状態でundo/redoを実装するのは複雑性が上がっちゃうし、無理でしょうってなってたと思います。
fujimura: IRBとかRelineって、テストコードがあるのは知ってるんですけど、とはいえ動かすみたいなのもあると思うんですよ。そういうデバッグって普通に起動して一生懸命動かすって感じなんですか?
tompng: 以前はそうだったと思うんですけど、レンダリングのリファクタリングをした後は、ランダムなデータをレンダリングさせて、ちゃんとレンダリングできるか、レンダリングだけテストすればいいような状態になっています。それ以外のものは画面に表示して崩れることが起きなくなったから、テストもしやすくなってるかなと。
前はだいぶ大変でした。テストの仕方もキー入力でこれを入れて消してカーソルを移動してこうしたらクラッシュするみたいな再現手順も大変だったんですけど、そういうのがなくなって、もっとわかりやすく、このメソッドにこの値を足したら思ったのと違うのが返ってくるというようなバグしか残ってない状態になった。
今後の展望
fujimura: IRBやRelineで今後やりたいこと、展望はありますか?
tompng: IRB、Relineチームで話していたことの一つは、遠隔でIRBにつなげたらいいな。それはターミナルでかもしれないし、ブラウザからかもしれないけど、やれるといいなって。
ima1zumi: 既にmameさんが作ったりしてますけど、本体組み込みの機能として提供したいねっていう話はありますね。ただどういうニーズに向けて作るかは、方針が定まってない感じですね。
fujimura: 今見えてるこれだろうみたいなニーズはあるんですか?
ima1zumi: 私が欲しいと思っている例でいうと、Dockerの中で起動してるRailsに向かって、Dockerの外からアタッチするのは不便なので、Dockerの中から違うプロセスで起動してるRailsに向かってアタッチしたいと思うことありますね。
fujimura: Dockerの中でそれはよさそう。
tompng: それがブラウザでできたら楽じゃないって思いますよね。
ima1zumi: そうなんですよ。
tompng: どっちでやるのがいいのかな。
mame: ブラウザで?
tompng: ブラウザにはソケットを開けてるわけじゃないですか。だからどこかのコンテナに入ってではなくて、ブラウザから直接、特定のパスにアクセスしたら今止まって待機中のIRBのセッションに繋がるとかでも面白いのかな。
mame: それって難しい?
ima1zumi: やればできそうな気はする。Webコンソールのリッチなバージョンみたいな。
mame: セキュリティの懸念はすごくあるので難しいですけどね。
ima1zumi: 開発環境だけかな。
mame: 開発環境だけでいいんですか、それならできそうかも。
ima1zumi: 本番環境で動くものがほしいと聞いたこともあります。何に使うかっていうと、生きてるRubyのプロセスに対してアタッチしてデバッグしたい時に、リモートからアクセスできる状態で対話式環境が欲しい時がある。
mame: それならブラウザで開いて、そこにWebコンソールが出てるのとは違う?
ima1zumi: 本番環境で動いてる本番のRailsサーバに対してアタッチしたいことがある。再現が難しい不具合を踏んでいるとか、そういう時だと生きてる状態でアタッチしたいと言っていた気がします。
fujimura: 夢がありますね。他にできるか全く想像してないけど、こんなことできたらいいな的なのはありますか?
ima1zumi: 型補完に欲しい機能があって、メソッドチェーンが続いた時に補完してほしい。今はメソッドチェーンが続くと補完できないと思うんですよ。
mame: できるんじゃないの?
tompng: 型が足りてないやつか。夢としては、型はなくてもiseqとれるから出るじゃんっていうのが。
mame: ないと思う。動的解析でも難しすぎる。
ima1zumi: 何でもメソッドチェーンで取ってほしい気持ち。
fujimura: 今はチェーンしてるとできない?
ima1zumi: 例えばRailsのインスタンスとかが続く時はできないんですよ。
tompng: メソッド名と同じインスタンス変数がある時はそれが返せるっていうことを仮定して、メソッドチェーンできてもいいかなと思ってて。そういうのはちょっとやりたいかな。
fujimura: これには勝てないみたいなのはいますか?
tompng: Pythonの標準じゃなくて、IPythonってやつが同じように型を使った補完をやっていそうで、同じようなのがあるんだって思いましたね。
ima1zumi: Juliaの対話式環境は文字を入力するとUnicodeのコードポイントやUnicodeの情報を一気に出してくれるのでいいなと思ったことがあります。
参加者: できないの?
ima1zumi: やればできるけどIRBに入れるかっていうと、I.irbrcにそういう便利メソッドは自分で定義してるので。
fujimura: なんでJuliaは出してるの?
ima1zumi: JuliaってUnicodeの演算子を使えたりして、そういうところで親和性あるのかなって。全然知らないんですけど、勝手に思ってます。
tompng: 補完の方でやりたいと思ってて忘れてたことなんですけど、今はカーソルよりも前の部分しか見ないんですけど、カーソルの後ろをちょっと見た方がいいだろうなって。1.timesって書いた時にカーソル戻ってtiの位置でmって言ったらそこからtimesって出るんですけど、その後ろにm,e,sが残っている。
mame: もう m あるじゃんって。
tompng: そうそう、後ろにあるものをそのまま使い回したい。そういうちょっと不便なところがあるから、直せたら直したいな。
AIとの連携
mame: 今思いついてしまったんだけど、GitHub Copilotとつなぐとかどうですかね?
fujimura: 僕はバイブコーダーなので、勝手に書いてくれた方がいいんですよ。IRBでもズラズラって出てほしいなって思うときはある。
ima1zumi: なるほど。
mame: t と打っただけで times どころかその先まで。
fujimura: そうそう、ブロックが終わるところまでバッて出るみたいな。
mame: 何を書かれるか、わからないってのはありますけどね。
tompng: やりたいのかな。
mame: 今パッと思いついた限りでは普通に便利そうな予感がしましたけどね。
ima1zumi: コードベースを読んでくれるから、ActiveRecordのこのモデルみたいな情報はより取りやすそうです。
fujimura: コーラーからいい感じに読んでくれたりとかできたらかっこいいですよね。
ima1zumi: 先読みというか薄字で補完が出るみたいな、一部のやつにあるじゃないですか。Redisのコンソールは打てるコマンドがうっすら出てくるんですよね、あれ便利だなと思って。
tompng: そう考えるとRelineのAPIの制限でできないことって結構あるなって。
ima1zumi: 例えばどういうことですか?
tompng: 今のもRelineに手を入れなきゃできないと思うし、Auto Indentって今カーソルがある行しかインデントしてくれないけど、ちょっと全体が崩れた時にえいっと直したいなって気がしつつその機能はない。Relineに足さないといけない。Reline と IRB をつなぐ Auto Indent の仕様が行のインデントを計算して返してくれみたいな形で、全部更新したいけど一部しか更新できない。それもAPIの制限でできないとか、できたとしても非効率だろうみたいなのがあるんですよね。
ima1zumi: 確かに IRB と Reline がどっちもRubyだからできているブロックで渡している部分って、まだまだ拡張できそうですよね。
mame: Ruby に新しい文法が入った時に、各種エディタがサポートするまでタイムラグがあるじゃないですか。あれが微妙に不満で、VS Codeのエクステンションとして IRB のAuto Indentを使えないかなと思ったことはあります。
BigDecimal
fujimura: 最後に1つお伺いしたいんですけど、イベントが始まる前にBigDecimalの話が盛り上がっていました。ちょっとお聞かせ願えないでしょうか?
tompng: BigDecimal のissueにいろいろと対応できていないものがあったのを見かけて、数学はちょっと好きだから触ってみたという感じです。まるめとか難しいですね。あとBigDecimalの使い方も難しい。RubyのIntegerは速いので、Integerで頑張るのもいいんじゃないかな。BigDecimalはどうあればいいんだろうなというところは、まだあまりつかめてないです。
fujimura: 会場の皆さんにも伺いたいんですけど、どんな時にBigDecimalを使ってますか?
参加者: 寝れなくて、円周率を計算したいなって。
fujimura: 寝れなくて円周率を計算したいがユースケース1。
ima1zumi: そちらの方も同じですか?
参加者: お金の計算。
fujimura: お金の計算、それはおっしゃるとおりですよね。
tompng: 現状だとやっぱ速度ってIntegerの方がいいですよね。
fujimura: ちょっとこの話も広げたいところなんですけども、次回是非。一旦第1部を終わろうと思います。tompngさんありがとうございました。
tompng: ありがとうございました。
第2部に続きます。