Try ruby

Table of Contents

謹賀新年

本年もよろしく お願いいたします。

ラクビーのトライになぞらえて、年始はTry rubyでスタートします。そして箱根の 山への駅伝に範をとって、running rubyと続く予定です。 その前に、去年からの積み残しである、型を、かたしてしまいます。

pythonの型

標準ライブラリィーに、どの程度、型が浸透しているか、表面をなぞってみた。 まずは、現役の3.12.11

te$ egrep -l '(.*:.*) -> '  *.py
_aix_support.py
_collections_abc.py
ftplib.py
optparse.py
statistics.py
textwrap.py
typing.py

こちらは、git clone した head版

ob$ egrep -l '(.*:.*) -> '  *.py
_aix_support.py
_collections_abc.py
_colorize.py
_py_warnings.py
argparse.py
doctest.py
ftplib.py
optparse.py
random.py
statistics.py
textwrap.py
token.py
turtle.py
typing.py

python vs. ruby

とかく対比されがちな両雄について、チャッピーに聞いてみた。

Q: python(3.12.3)とruby(3.4.1)での標準添付されるライブラリィーについて質問します。 1. それぞれで、方向性は有りますか? 2. 本体機能にしたもの、そこから外れて標準添付になったもの。

A: 良い切り口の質問ですね。 Python と Ruby はどちらも「 batteries included / すぐ使える 」文化を持ちますが、/標準添付ライブラリの方向性と整理の仕方はかなり違います/。

以下、/Python 3.12.3/ と Ruby 3.4.1 を念頭に説明します。


## 1. 標準添付ライブラリの「方向性」

### Python の方向性

「汎用基盤・参照実装・保守重視」

Python 標準ライブラリは、

  • OS・ネットワーク・並行処理などの/基盤機能/
  • 言語仕様を補完する/参照実装/
  • 「標準で動くこと」が重視される/保守的なAPI/

を中心に構成されています。

特徴的なのは:

  • 後方互換性を極めて重視
  • 一度入ったものは、よほどの理由がない限り消えない
  • 標準は「最低限信頼できる実装」、高機能化は PyPI に任せる

その結果:

  • stdlib は「広いが浅い」
  • 本格用途は第三者ライブラリ前提

という構造になります。


### Ruby の方向性

「実用性・表現力・言語体験の完成度」

Ruby 標準添付は、

  • Ruby らしい書き心地を完成させる
  • 「普通に書くと自然に使うもの」を最初から入れる
  • 実用寄り・DSL寄り

という傾向があります。

特徴として:

  • 言語体験を損なわないことを優先
  • 標準添付でも Gem として管理されるものが多い
  • 「標準だが交換可能」という思想

つまり:

  • stdlib は「狭めだが深い」
  • 言語機能とライブラリの境界が曖昧

## 2. 本体機能 vs 標準添付になったもの

ここが Python と Ruby で一番違う点です。


### Python:明確な線引き

Python では、/原則として/:

  • 言語コア:構文・型・VMレベル
  • 標準添付:ライブラリ(import するもの)

が明確に分かれています。

#### 本体(言語仕様・VM)

  • オブジェクトモデル
  • GC(参照カウント+世代)
  • 型システム
  • import 機構
  • GIL
  • 例外・yield・async/await

#### 標準添付ライブラリ例

  • os, sys, pathlib
  • socket, ssl, http.client
  • threading, multiprocessing
  • subprocess
  • logging
  • unittest, doctest
  • typing, dataclasses

重要なのは:

stdlib は「言語機能ではない」

という扱いです。

そのため最近は:

  • distutils → 削除
  • asyncio の整理
  • importlib の内製化
  • typing 関連は「仕様」として別管理

など、/標準添付でも再設計・削減が進む/傾向があります。


### Ruby:言語とライブラリが混ざる

Ruby では、/歴史的に/:

  • 標準添付 = 言語体験の一部
  • 「require するが、実質コア」

というものが多いです。

#### 本体に近いもの

  • Enumerable
  • Comparable
  • Kernel
  • Object, Module, Class
  • Fiber
  • Thread
  • Enumerator

これらは/構文・言語設計と不可分/です。

#### 標準添付だが Gem 化されたもの

  • json
  • psych (YAML)
  • rexml
  • net/http
  • openssl
  • rake
  • irb
  • bundler

Ruby 2.x 以降は特に:

「標準添付 = default gem」

という考え方が定着しました。

つまり:

  • 標準で入っている
  • しかし独立して更新可能
  • 必要なら外せる

という柔軟構造です。


## 3. なぜこう違うのか(思想的背景)

### Python

  • 学術・教育・基盤用途が強い
  • 複数実装(CPython / PyPy / Jython)を意識
  • 仕様と実装を分離したい
  • 保守性・再現性重視

stdlib は「参照点」


### Ruby

  • 開発者体験(DX)重視
  • 書いて楽しいことが最優先
  • Matz の「プログラマの幸福」
  • Ruby VM = Ruby 言語

stdlib は「言語の延長」


## 4. まとめ(短く)

観点 Python Ruby
--------- ------- --------
標準添付の思想 基盤・参照実装 実用・言語体験
本体とstdlib 明確に分離 境界が曖昧
削除・整理 あり得る Gem 化で対応
拡張の場 PyPI RubyGems
安定性 非常に高い 比較的柔軟

Q: 標準添付でも Gem として管理されるものが多い との事。 3.4/ と gems/ ですね。 何となく、3.4/ の方は、老舗で、gems/ は、新興勢力のように感じられます。 どちらに配置するとかの、基準は有るのでしょうか? それと、gems/ への 殿堂入りは、誰が決めるんでしょうか? 選定基準って 有るのかな? Ruby の default gem 戦略と、からめて説明してください。

A: とても本質的な観察です。 その 「3.4 は老舗、gems/ は新興」/ という感覚は、実装・運用の実態をかなり正確に捉えています。

以下、/Ruby 3.4 系の構成/と /default gem 戦略/を軸に、 「どこに置かれるのか」「誰が決めるのか」「どういう基準か」を整理します。


## 0. 前提:3.4/ と gems/ は何が違うのか

Ruby のインストールツリーを単純化すると:

lib/ruby/
  3.4.0/
    ├─ core / stdlib 的ライブラリ
  gems/
    3.4.0/
      └─ gems/
           ├─ json-x.y.z
           ├─ rake-x.y.z
           ├─ bundler-x.y.z

ここで:

  • 3.4/ → Ruby 本体と 同じリリースサイクルで管理されるライブラリ
  • gems/ → RubyGems によって 独立して更新される default gem

という違いがあります。


## 1. 配置基準はあるのか? →「あるが、文書化されていない」

### 大原則(Matz + core の合意)

3.4/ に置かれるもの:

Ruby 言語の「成立」に深く関与しているもの

gems/ に置かれるもの:

Ruby を「便利にするが、言語そのものではないもの」

ただしこれは/厳密なルールではなく、運用上の合意/です。


## 2. 3.4/ に残る(老舗)ライブラリの特徴

### 条件①:言語仕様・コアクラスと不可分

例:

  • enumerator
  • fiber
  • rational, complex
  • set
  • forwardable

これらは:

  • EnumerableKernel と密結合
  • 削除すると Ruby の書き味が変わる
  • 「require しないと Ruby っぽくならない」もの

→ /言語機能の延長/扱い


### 条件②:後方互換を絶対に壊せない

例:

  • pp
  • =irb=(※今は default gem 化されたが特例)
  • optparse

過去 20 年以上のスクリプトが依存しているため:

  • バージョン不整合を起こせない
  • Ruby 本体と常に一緒にテストされる必要がある

### 条件③:C 拡張が VM と強く結びつく

例:

  • =psych=(一部)
  • =openssl=(歴史的理由)
  • ripper

VM 内部 API と密接なため:

  • gem として切り離すと壊れやすい
  • ABI 問題が出やすい

## 3. gems/(default gem)に行く「新興勢力」

### default gem の定義

default gem とは:

  • Ruby を入れると最初から使える
  • しかし gem update で更新できる
  • Ruby 本体とは独立してバージョン管理される

という立場です。


### default gem に送られる条件

#### 条件①:言語仕様と直接関係しない

例:

  • json
  • net/http
  • csv
  • rexml
  • webrick

→ 便利だが「Ruby である必然性」は薄い


#### 条件②:セキュリティ更新が頻繁

例:

  • openssl
  • net/http
  • webrick

Ruby 本体リリースを待たずに:

  • CVE 対応
  • プロトコル更新

が必要


#### 条件③:開発スピードを上げたい

例:

  • bundler
  • rake
  • irb

Ruby 本体は年 1 回前後だが:

  • gem なら月単位で改善可能

## 4. 「殿堂入り」を決めるのは誰か?

### 決定主体

明確な「委員会」はありません。

実態は:

  1. ライブラリ作者
  2. Ruby core(特に Matz / naruse / hsbt あたり)
  3. Ruby committers の合意
  4. RubyKaigi 等での合意形成

という、/極めて Ruby らしい合議制/です。


### 典型的な流れ(昇格パターン)

  1. Gem として広く使われる
  2. Ruby 本体でも事実上必須になる
  3. 「標準で入ってないと困る」という空気ができる
  4. default gem として同梱
  5. lib/ruby/3.4/ ではなく gems/ に配置

core に戻ることはほぼ無い


## 5. 選定基準はあるのか?(実質的チェックリスト)

暗黙的ですが、だいたい以下です:

  • ✔ Ruby 文化に合うか
  • ✔ メンテナが継続的に存在するか
  • ✔ API が安定しているか
  • ✔ 依存関係が少ないか
  • ✔ Ruby 本体の哲学を壊さないか
  • ✔ 削除可能であるか(gem なので)

逆に:

  • ❌ 実験的すぎる
  • ❌ DSL が強すぎる
  • ❌ 巨大すぎる

ものは default gem になりません。


## 6. default gem 戦略の本質

### Ruby がやりたかったこと

「標準は欲しい。でも固定したくない」

これが default gem 戦略です。

  • Python:stdlib は凍結 → PyPI に逃がす
  • Ruby:stdlib を gem 化 → 標準のまま更新可能

つまり Ruby は:

標準添付 = 特権ではない

という思想を選びました。


## 7. あなたの感覚の答え合わせ

3.4/ は老舗、gems/ は新興

これは /ほぼ正解/で、より正確には:

  • 3.4/ → Ruby そのものを成立させる「文化財」
  • gems/ → 実用性重視の「殿堂入りだが可動式」

です。

try ruby

OpenBSDに入れてみる。ドキュメントは本体と分離されてるんで、どれ様なのが有るか 確認。これを入れておくと、irbした時、説明が出てくるぞ。

te$ doas pkg_add ruby
Ambiguous: choose package for ruby
a       0: <None>
        1: ruby-3.2.9
        2: ruby-3.3.9
        3: ruby-3.4.6
Your choice:

rdoc経由で作成されるriも確認。

te$ pkg_info -Q ri_doc
ruby32-ri_docs-3.2.9
ruby33-ri_docs-3.3.9
ruby34-ri_docs-3.4.6

3系統をサポートしてるのね。最新でいいだろう。

te$ doas pkg_add ruby-3.4.6
 :
--- +ruby-3.4.6 -------------------
If you want to use this package as your default system ruby, as root
create symbolic links like so (overwriting any previous default):

 ln -sf /usr/local/bin/ruby34 /usr/local/bin/ruby
 ln -sf /usr/local/bin/bundle34 /usr/local/bin/bundle
 ln -sf /usr/local/bin/bundler34 /usr/local/bin/bundler
 ln -sf /usr/local/bin/erb34 /usr/local/bin/erb
 ln -sf /usr/local/bin/gem34 /usr/local/bin/gem
 ln -sf /usr/local/bin/irb34 /usr/local/bin/irb
 ln -sf /usr/local/bin/racc34 /usr/local/bin/racc
 ln -sf /usr/local/bin/rake34 /usr/local/bin/rake
 ln -sf /usr/local/bin/rbs34 /usr/local/bin/rbs
 ln -sf /usr/local/bin/rdbg34 /usr/local/bin/rdbg
 ln -sf /usr/local/bin/rdoc34 /usr/local/bin/rdoc
 ln -sf /usr/local/bin/ri34 /usr/local/bin/ri
 ln -sf /usr/local/bin/syntax_suggest34 /usr/local/bin/syntax_suggest
 ln -sf /usr/local/bin/typeprof34 /usr/local/bin/typeprof

それぞれが別の名前になってるんで、主力で使うものをリンクしとくといいよと 案内が出てきた。

te$ ruby -v
ruby 3.4.6 (2025-09-16 revision dbd83256b1) +PRISM [i386-openbsd]

ちゃんとインストールされたか、確認。+PRISM って、何だ?

Prism⁠⁠:エラートレラントな⁠⁠、まったく新しいRubyパーサ

ユーザーへのご利益。

def hello(name)
  puts "Hello #{name}"

hello('Matz')

こんな、中途半端なコード。

ob$ ruby test.rb
test.rb: --> test.rb

Unmatched keyword, missing `end' ?

> 1  def hello(name)
> 5  hello('Matz')

test.rb:6: syntax errors found (SyntaxError)
  4 |
  5 | hello('Matz')
> 6 |
    | ^ expected an `end` to close the `def` statement
    | ^ unexpected end-of-input, assuming it is closing the parent top level context

ちゃんと指摘してくれる。オイラーのruby 1.4.X 時代にサポートされてればなあ。 こういうつまらないエラーには、泣かされましたから。

debug

何はともあれdebuggrだな。標準添付になってるはずって事で、ドキュメント3.4の ライブラリィ一覧を調べてみたよ。目的別に整理されてて中々便利だ。 library debug

これによると、emacs用は別途、rubydb3x.el を入れろとなってた。 が、その通りにしても動作せす。

ruby/debug こちらが現代風な物らしいだよね、笹田先生(ko1)。何が現代風かと言うとvs code対応ね。 毒されているな。おまけに、

$ rdbg --open=chrome sample.rb

表示器をブラウザーに任せてしまう事もサポートされている。世はすっかりGUIで あります。ガラパゴス携帯を今だに愛用してるオイラーは、すっかり浦島太郎だな。

でもきっとガラパゴスを愛しているemacs派は希少種として、存在してるはず。 同士を探してみる。

GNU Emacs で VS Code 相当のコード・デバッグ支援機能を設定する (1) – Eglot

dape/dap-modeの2種が有るけど、dapeの方が小粒で良さそう。と思ったら、色々な 言語用を内蔵してた。TCP/IP 接続してるのね。

(rdbg
 modes (ruby-mode ruby-ts-mode)
 ensure dape-ensure-command
 command "rdbg"
 command-args ("-O" "--host" "0.0.0.0" "--port" :autoport "-c" "--" :-c)
 fn (lambda (config)
      (plist-put config 'command-args
                 (mapcar (lambda (arg)
                           (if (eq arg :-c) (plist-get config '-c) arg))
                         (plist-get config 'command-args))))
 port :autoport
 command-cwd dape-command-cwd
 :type "Ruby"
 ;; -- examples:
 ;; rails server
 ;; bundle exec ruby foo.rb
 ;; bundle exec rake test
 -c (concat "ruby " (dape-buffer-default)))

ちょいと使ってみたけど、コンソール上のemacsでは、枠が幅を効かせてしまって 不便だな。素直にrdbgするのが良さそう。

ruby 4.0.0

ruby生誕30周年で、看板が新らしくなってた。記念版は切り良い番号にしました (これで、完全にpythonの番号を出し抜きできました)。

Ruby 4.0.0 リリース

プロと読み解くRuby 4.0 NEWS

記念にコンパイルしてみる。

sakae@lu:ruby-4.0.0$ ./configure  --enable-shared
     :
    BASERUBY -v:         ruby 3.4.1 (2024-12-25 revision 48d4efcb85) \
                          +PRISM [x86_64-linux]

去年、Windows 10を捨ててLubuntuにした時、コンパイル環境のチェックを兼ねて 入れたのが残っていた。baserubyが存在すると、minirubyを作成せずに、tool/ に有るものを使って、最終的なrubyを作成するそうだ。先端を追求する人向け。

make -j2 で、4分弱でコンパイル完了。

sakae@lu:~$ ruby -v
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]

libruby.so.3.4.1とか/usr/local/share/riにも、3.4.0/ なんてのが、残って いるんだよな。make installする前に、bin/ruby -> bin/ruby34 にでもしておけば、 二重生活ができたね。

sakae@lu:~$ gdb -q ruby
 :
(gdb) b main
Breakpoint 1 at 0x1120: file ./main.c, line 53.
(gdb) r -v
Starting program: /usr/local/bin/ruby -v
 :
Breakpoint 1, main (argc=2, argv=0x7fffffffdd48) at ./main.c:53
53      {
(gdb) l
48      int wmain(void) {return main(0, NULL);}
49      #endif
50
51      int
52      main(int argc, char **argv)
53      {
54      #if defined(RUBY_DEBUG_ENV) || USE_RUBY_DEBUG_LOG
55          ruby_set_debug_option(getenv("RUBY_DEBUG"));
56      #endif
57      #ifdef HAVE_LOCALE_H

コンパイルの残骸は1.1Gになってた。tar玉を展開しただけだと150Mだ。これだけ でも有ると上記のように一応gdbできる。

残骸が肥大化してる理由は、yjit/ が rust になってるから。yjitが組み込まれた 証拠でもあります。尚、OpenBSD版でもyjitを内包してます。もう、portsに、4.0.0 が登場してるよ。

README

ギーク思考 なんて本を読んだ。

本の紹介の所に、計画よりも失敗 なんてのが挙げられている。グダグダと考えて いるより、体を動かせ、そして色々と失敗しろって理解した。

その方が得る所が大きいからね。例えば、ruby 4.0をコンパイルした。コンパイルに 当っての事前準備なんて全く眼中に無かったぞ。configureなんて失敗するのが あたり前と思っていたからね。

そしたら、既存のrubyを検出して、それをminirubyの代わりに使ってくれた。 じゃ、既存のrubyが存在しない場合は?

3秒考えて、rubyをPATHから外した。そして、rubyが居ない事を確認する為に 下記のコマンドを投入。

sakae@lu:~$ ruby -v
コマンド 'ruby' が見つかりません。次の方法でインストールできます:
sudo snap install ruby  # version 3.4.7, or
sudo apt  install ruby  # version 1:3.1
他のバージョンについては 'snap info ruby' を確認してください。

snap版でも提供されるんかって無駄知識が得られた。snap infoなんてコマンドも 知らなかったしね。こういうの、失敗してこその知見です。

それから、4.0のニュース解説を読んでいると、調整よりもカオス、忖度よりも議論 ってのがrubyには似合っているねと良く分る。


This year's Index

Home