長い時間が過ぎた後でも Ruby がいまだに我が家のように感じられる理由
(caio.ca)- Ruby は最速でも最も流行している言語でもないが、15年以上にわたってさまざまな言語を渡り歩いた後でも、仕事を楽しみたいときに再び選ばれる言語であり続けている
- refinements、Forwardable、SimpleDelegator、
Object#then、Kernel#tap、番号付きパラメータは、小さな文法上の利便性と読みやすい流れを提供する - 標準ライブラリの
Thread::Queue、json、csvと RuboCop、Ruby LSP は、小さな gem や複雑な設定なしでも実用的な開発環境を維持できるようにしてくれる - Ruby 3.x の YJIT と 4.x の ZJIT は CPU 集約型処理の差を縮めつつあり、単純な Fibonacci 比較では Ruby with ZJIT が Go の 2〜3 倍以内だった
- Rust・Go・Python のほうが適している領域もあるが、Web アプリ、バックグラウンド処理、社内ツールでは 開発者の幸福 と高速な反復速度が Ruby の強みであり続けている
Ruby が快適に感じられる言語的な理由
- Ruby は 最速でも最も流行している言語でもない が、15年以上にわたって複数の言語を行き来した後でも、実際に仕事を楽しみたいときにまた選びたくなる言語であり続けている
- refinements は限定されたスコープでのみクラスを開けるようにし、名前空間全体を汚染せずにファイルやブロック内へ小さな文法上の利便性を追加できる
- テストヘルパーや大規模コードベースの内部 DSL によく合う
using QuotingRefinementを呼び出した場所でのみ"hello".quoteのようなメソッドを使える
- 標準ライブラリの Forwardable と
SimpleDelegatorは、ラッパーメソッドを手書きしたり追加の gem を持ち込んだりせずに、きれいな委譲を可能にしてくれる- すでに Rails を使っているなら Active Support の
delegateのほうが便利かもしれないが、コア Ruby の版は一般的なスクリプトを軽量に保ってくれる
- すでに Rails を使っているなら Active Support の
Object#thenとKernel#tapは、中間変数を作らずに処理を上から下へ読めるチェーンとしてつなげられるようにしてくれるUser.new(params).tap { ... }.then { ... }.saveのように、生成、ログ出力、正規化、保存の流れを連続して書ける
- Ruby 2.7 以降の 番号付きパラメータ は、短いコールバックでノイズを減らしてくれる
items.map { _1.price * 1.1 }のようにブロック引数を明示しなくてよい
- fiber scheduler は、イベントループを接続したときに逐次コードのように見える並行コードを書けるようにしてくれる
Fiber.schedule do ... endの形で、ほかの fiber と協調するコードを表現する
ツール、性能、エコシステムの現在地
- Shopify の Ruby LSP は最小限の設定でエディタ統合を提供し、段階的な型適用のための Steep や RBS ともうまく連携する
- RuboCop は、ほかのエコシステムで見られるような儀式的な手順なしにスタイルの一貫性を保てるようにしてくれる
- 標準ライブラリは、よくある作業のために複数の小さな gem を追加しなくてよいという静かな強みを保っている
- キューが必要なら
Thread::Queueを使える - JSON や CSV の解析は
jsonとcsvライブラリが、大がかりな手順なしで大半の実運用ケースを処理してくれる
- キューが必要なら
- Ruby 3.x の YJIT に続いて、4.x 系列には ZJIT が入ってきている
- ZJIT は同じ基盤の上でより積極的に動作する JIT で、よりホットな実行経路を効果的にコンパイルする
- 初期の数値では、CPU 集約型処理で Ruby と大きな差を見せていた言語との開きが意味のあるレベルで縮まっている
- CRuby ZJIT は Ruby のメインリポジトリで開発されている
- 同じマシンで再帰的 Fibonacci 実装を比較した単純なベンチマークでは、Ruby with ZJIT は Go の 2〜3 倍以内で、そのケースでは最適化された Rust とも大きく離れておらず、Python with pypy は後れを取った
- マイクロベンチマークには限界があるが、JIT が最適化する時間を得られる温まったコード経路では、実アプリケーションもより大きな恩恵を受けられる可能性がある
- Rust と比べると、Ruby は ビジネスロジックの反復速度 に強みがある
- Rust では、ランタイムでは明白なことでも borrow checker と格闘する時間が生じることがある
- Go は並行性の基本要素が優れているが、最近まで generics がなく、やや硬直したエラー処理のために単純なスクリプトが必要以上に重くなることがある
- Python は最も近い精神的ないとこだが、とくにクラスやデコレータの周辺で、同じ高水準のアイデアを表現するのにより多くのボイラープレートを必要とする
- モデルにコードを入れるとき、トークン効率 も Ruby の実際の利点として働く
do/endや中括弧でブロックを表現でき、可読性が許すならメソッド呼び出しに括弧がほとんど不要である- ハッシュとキーワード引数が第一級の機能として簡潔であり、構造的ノイズの多い言語よりも同じコンテキストウィンドウに多くの実ロジックを入れられる
- Ruby のメタプログラミングユーティリティは、小さく読みやすい API を作るのに向いている
define_method、class_eval、missing method のインターセプトのような機能によって、コード生成段階なしで表現力のある API を作れるdry-rbやaasmのようなライブラリはこの機能を節度を持って使い、すっきりしたステートマシンと検証レイヤーを提供する
- コミュニティツールとデプロイの流れも成熟してきた
- byebug と
pryは、ほかで使ってきた多くのデバッガよりも柔軟に感じられる - バックグラウンドジョブでは
solid_queueとgood_jobがシンプルで、実装全体をひと午後で理解できるほど手が届きやすい - Kamal は多くの人にとって古い capistrano 式の手順を置き換えており、実際に小さなチームを運営する人たちが作ったツールのように感じられる
- byebug と
- これは Ruby があらゆる作業で Rust や Go に勝つという意味ではなく、Rust や Go のほうが適した領域もある
- Web アプリケーション、バックグラウンド処理、社内ツールという広い中間領域では、Ruby は過剰な儀式や頻繁なコンテキストスイッチなしに 開発者の幸福 を提供し続けている
- 小さな利便性と言語全体の感触は、10年以上経っても真っ先に手が伸びる要素であり続けており、新しい JIT の取り組みと着実な言語改善がその理由をさらに強めている
1件のコメント
Lobste.rs の意見
「no ceremony RuboCop」という表現にはあまり同意できない
RuboCop には、どの cop を選んで調整するか、最近のアップデートで追加された新しい cop を有効にするかどうかを議論する手間がかなりある
StandardRB のほうがずっと儀式性のないアプローチに近いが、結局それも 1 つ選ばなければならない
lint が言語に組み込まれている言語は、Ruby よりはるかに煩雑さが少なく、些細なスタイル論争も少ない
制約はむしろ自由を与えてくれる
lint の設定自体に基本的に反対で、こういう判断は コミュニティのデフォルト に任せたい
一方では、RuboCop のデフォルトは十分良いので、コーディングスタイルをさらに細分化するより従って一緒に進化させるべきだと思う
他方では、時々あまりに主張が強すぎて、standard.rb のようなものが必要にも見える
Ruby を学んだり戻ってきたりする人が快適にコードを書けるように、大量の gem と向き合わなくても済むという観点で書いた
Go が登場したとき、1つの公式フォーマットシステムを提供したのは本当にうまいやり方だと思った
脳はパターンマッチングの機械だから、慣れればそのまま流せるが、選択肢があると不快感を覚え、みんながあちこちに引っ張られてしまう
問題は、RuboCop も Standard も Ruby においてそうした権威を持てないことだ
その権威は コアチーム から来るべきだが、Ruby の哲学に反するので起こらない可能性が高い
私のプロジェクトでは RuboCop の cop をすべて無効にして、一部だけ有効にしている
シングルクォートが最高 😀
別の記事でもこの点が指摘されているようだ: https://caio.ca/blog/coding/my-complicated-relationship - “The Wild West of Code Formatting”
「単純な組み込みソリューションではない。設定可能な cop が何百もあり、どのルールを有効にするかという終わりのない議論につながる」という話だった
おおむね同意するが、refinements が最初の例なのは少し残念
好きな理由は分かるが、ソーセージがどう作られるかは知らないほうがいい類いに近い
意味論があまりに厄介で、導入から10年経った今でも MRI で厄介なバグが見つかり続けている
たとえば直近2週間の間にも https://bugs.ruby-lang.org/issues/22071 と https://bugs.ruby-lang.org/issues/22058 があった
パフォーマンス面でも多くの最適化を難しくしており、今は boxes でも似たことがまた起きている
実装レベルでもまだ隠れたバグが多いだろうし、ライブラリ側でも同じだと思う
今はもう Ruby をあまり使っていないが、これがどう定着するのか気になる
面白そうではある
この記事は、私の「Returning to Rails」記事[1]での体験ともかなり重なる
確証バイアスかもしれないが、Rails コードの美しさを再発見したり改めて認めたりする人が増えているように見える
ただ、音楽や芸術の好みが10代後半から20代で固まる現象も思い出す
Rails の「黄金時代」に Ruby と出会った人たちが、Rails 3 と Capistrano があった時代を バラ色のメガネ で振り返っているだけではないかとも思う
当時は Ruby の “shop” に深く浸かっていて、周囲も Rails 開発者ばかりだったので、どこにでも Ruby があるように感じていた
ただ、lobste.rs のスレッド[2]で Ruby は実際には昔からかなりニッチな言語だったという見方を見て、そういう影響もあったのかもしれないと思った
それでも Ruby は今でも家のように感じられるし、自分の頭の働き方そのままで動くように思える
翻訳の過程がほとんどなく、驚かされることもなく、形式ばった論文を書くより友人と会話している感覚だ
こんなにしっくりくる言語はまだ見つかっていないし、これが全部「最近の若いやつは」的な思考のせいだけだとも思わない
とにかく、これだけ長く生き残っているのはうれしい
それと、「tap / new」チェーンを教えてくれてありがとう
あの構造はとても美しくて便利で、思わず立ち止まったし、きっと使ってみると思う
PS - 話題と直接関係ないが、ホームページの AI アバター が少し不気味だ
「この記事はボットが書いたのか?」という不気味の谷っぽい感覚を強く与える
あれを見るたびに、自分が本当に人間と話しているのか一瞬考えてしまう
[1]=https://www.markround.com/blog/2026/03/05/returning-to-rails-in-2026/
[2]=https://lobste.rs/s/jreqtw/returning_rails_2026
実際の写真を公開したくないだけで、そのアバターは実際に知っている人なら分かる程度には似ている
Ruby 3.4 では
itブロック引数 が追加され、例の_1の代わりに使えるhttps://rubyreferences.github.io/rubychanges/3.4.html/…
itに触れるのを忘れていた比較的新しい機能だからか、イテレータで
itと打つ習慣がどうしても手に馴染まないRuby でコードを書くのは本当に好きだったが、テスト負担 が重くなりすぎた
言語にある程度の型安全性を足せば助けになると思ったのだが、
#{last_job}でコードベースに Sorbet を入れた結果、コードを書く勢いと楽しさが完全に死んでしまった不人気な意見かもしれないが、Sorbet のようなものが存在するという事実自体が、Ruby に対する悪い臭いにより近いと思う
Ruby 自体は強力で楽しい言語だが、人々が本来想定されていなかった仕事に使い始め、その過程で言語のアンチ機能を補うためにツールを継ぎ足し始めた
今ではすべての行が退屈な苦役のように感じられ、実際にコードを書く時間より、各種ビルド・テスト・lint ツールを待つ時間のほうがずっと長かった
そこに過度に設計されたビルドとデプロイの過程まで加わって、基本的なことですら時間がかかり、作業が苦痛になった
2012年ごろの Ruby の世界がとても恋しい
振り返れば本当に良い時代だった
「本来想定されていなかった仕事」と言ったのは大きな Rails アプリケーションのことだと理解した
10年ぶりに Ruby に戻ってきたが、「AI」時代には、目の前を流れていくコードを実際に理解し、LLM を操ったり止めたりできるという点が役に立つ
もっと冗長な言語では、これはより難しい
Ruby が恋しいし、さらに言えば日常的なプロダクションでそういう言語が可能だという事実自体が恋しい
それは希望であり、いや 希望そのもの だった
少なくとも私にとっては長い間そうだった
AI が雑に作った文章のように読める
最近のほかのブログ記事も似た感じだ
どんな手がかりでそう思ったのか?
このサイトで AI 生成の低品質記事を指摘するのは良いことだが、誤検知を避けるためにも、なぜそう思うのかを具体的に言う必要がある
なぜそう思ったのか?
こうした警告自体は良いが、理由も一緒に示してくれるほうがずっと望ましい
キャリア初期に Ruby で働いていた記憶は良いものだ
Ruby には本当に気持ちの良い何かがある
ただ、おそらく去年、最近の Ruby を少し使ったとき、Web ベースの 標準ライブラリ文書 をたどるのが難しいと感じた
私だけだろうか? ruby-lang.org の文書の代替はあるだろうか?
[1] https://rubyapi.org
[2] https://devdocs.io/ruby/
この記事は少し変に感じる
Ruby でプロジェクトを1つ、SDKを1つ書く機会があったが、もう二度と Ruby を使いたいとはまったく思わなかった