0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ruby 4 で組込みクラスになった Pathname と Set の gem は読み込めるか?

Posted at

Ruby 4.0.0 で Pathname と Set が組込みクラスになるとのこと。
参考:Ruby 4.0.0 preview3 リリース

pathname や set の gem は読み込めるのだろうか?

なお,本記事の執筆にあたって,以下の二つのバージョンの Ruby を用いた。

  • ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [arm64-darwin25]
  • ruby 4.0.0preview3 (2025-12-18 master cfa3e7cf75) +PRISM [arm64-darwin25]

これまでの pathname

pathname は,Ruby 3.4 系では標準添付ライブラリーであった。

そのため,

  • 使うには require "pathname" が必要
  • しかし,とくにインストールする必要はない

であった。

ただ,gem の形で提供されているので,Ruby に添付されているもの以外のバージョンも,インストールして使うことができる。

これまでの set

私の認識では,Ruby 3.4 系の set は

  • 標準添付ライブラリーである
  • ただし pathname などと違い,require しなくても使えるようになっている

であった。

しかし,今改めて Ruby 3.2.0 のリリースノート を見ると,

Setrequire "set" を実行しなくても使用できる組み込みのクラスとなりました。 [Feature #16989] この機能は Set を参照した時、または Enumerable#to_set を呼んだ時に有効となります。

とある。
require 不要になったのは Ruby 3.2 のときということだ。
それはいいのだが,ここで既に「組み込みのクラス」という表現が使われている。

もう一度 4.0.0-preview3 のリリースノートを見ると,こちらは

Set は autoload される標準ライブラリのクラスではなく、組み込みクラス (core class) になりました。 [Feature #21216]

となっている。

「組み込みのクラス」と「組み込みクラス (core class) 」は違うのだろうか? 用語が混乱しているのだろうか。

ともあれ,set は gem として提供されており,Ruby 3.4 系では Ruby に添付されていないバージョンの set をインストールして使うことはできる:

付属の set をそのまま使う場合
p RUBY_VERSION # => "3.4.8"
p Set::VERSION # => "1.1.2"
gem のバージョンを指定して使う場合
p RUBY_VERSION # => "3.4.8"

gem "set", "1.1.0"

p Set::VERSION # => "1.1.0"
参照しただけでバージョンが固定され,別バージョンが使用不可に
p RUBY_VERSION # => "3.4.8"

Set # とくに何もしないが,Set を参照する

gem "set", "1.1.0"
# => 'Gem::Specification#check_version_conflict': can't activate set-1.1.0, already activated set-1.1.2 (Gem::LoadError)

Ruby 4 で gem は読み込めるのか

ここからが本題だ。

組込みクラスになってしまうと,gem で提供される pathname や set は使えなくなるのではないだろうか?

Ruby 4 で実験的に導入された Ruby::Box によるネームスペースを使えばひょっとして可能なのかとも思ったが,どう試せばよいかも分からなかった。

pathname

Ruby 4.0.0-preview3 で,gem 指定した pathname の require を試みる。
なお,以下の実験で,RUBY_VERSION"4.0.0" を返しているが,使用したバージョンはプレビュー版である。

p RUBY_VERSION # => "4.0.0"
p Pathname::VERSION # => "0.4.0"

gem "pathname"
require "pathname"
# =>
# /Users/XXXXX/.rbenv/versions/4.0.0-preview3/lib/ruby/gems/4.0.0+1/gems/pathname-0.4.0/lib/pathname.rb:17: warning: already initialized constant Pathname::VERSION
# <internal:pathname_builtin>:194: warning: previous definition of VERSION was here
# /Users/XXXXX/.rbenv/versions/4.0.0-preview3/lib/ruby/gems/4.0.0+1/gems/pathname-0.4.0/lib/pathname.rb:36: warning: already initialized constant Pathname::SEPARATOR_LIST
# <internal:pathname_builtin>:312: warning: previous definition of SEPARATOR_LIST was here
# /Users/XXXXX/.rbenv/versions/4.0.0-preview3/lib/ruby/gems/4.0.0+1/gems/pathname-0.4.0/lib/pathname.rb:37: warning: already initialized constant Pathname::SEPARATOR_PAT
# <internal:pathname_builtin>:313: warning: previous definition of SEPARATOR_PAT was here
# /Users/XXXXX/.rbenv/versions/4.0.0-preview3/lib/ruby/gems/4.0.0+1/gems/pathname-0.4.0/lib/pathname.rb:43: warning: already initialized constant Pathname::ABSOLUTE_PATH
# <internal:pathname_builtin>:323: warning: previous definition of ABSOLUTE_PATH was here

p Pathname::VERSION # => "0.4.0"

これによると,

  • gem "pathname" までは問題ない
  • そのあと require すると Pathname::VERSION などの定数が既に定義されている,と警告が出る
  • require の前後で Pathname::VERSION の値は変わらない

のようだ。
警告であってエラーではなく,鬱陶しいだけで動作には問題ないのかもしれない。

Gemfile と Bundler を使っている場合,警告は Bundler.require の時点で出る。

なお,gem "pathname" せずに require "pathname" すると何も起こらない。

以上の実験では,pathname のバージョンを指定していなかった。
バージョンを指定するとどうか。
先ほどの検証コードで

gem "pathname"

gem "pathname", "0.3.0"

に変えてみた(pathname 0.3.0 はインストールしておく)。

すると,

  • require 前の Pathname::VERSION"0.4.0"
  • require 後の Pathname::VERSION"0.3.0"
  • 警告は同様のものが出たが,警告が出るライブラリー箇所は pathname 0.4.0 のファイルから 0.3.0 のファイルに変わった(まあ当然)

という点が違っていた。

Bundler を使った場合(Gemfile に gem "pathname", "0.3.0" を記述)も同様であった。

set

set も同じようにやってみようとしたが,Ruby 4.0.0-preview3 では Set::VERSION が定義されていないらしく,バージョンを確かめることすらできなかった:

p RUBY_VERSION # => "4.0.0"
p Set::VERSION
# => uninitialized constant Set::VERSION (NameError)

これは,gem メソッドで set gem のバージョンを指定して require しても変わらない:

p RUBY_VERSION # => "4.0.0"

gem "set", "1.1.0"
require "set"

p Set::VERSION
# => uninitialized constant Set::VERSION (NameError)

上記コードで,require ではエラーも警告も出ない。
ここが pathname と大きく違うところ。

Bundler を使った場合も同様だった。

set gem では,バージョン 1.1.0 でも 1.1.2 でも,Set::VERSION は定義されている。

この定数が参照できない,ということは,Ruby 4.0.0-preview3 では Bundler を使っても gem 版の set ライブラリーは使えない,ということなのかもしれない。

まとめ

Ruby 4.0.0 の,あくまでプレビュー版についてだが,以下のようにまとめられるかと思う。

pathname

  • require 無しで使える
  • gem のバージョンを指定して require することもできる
  • その場合,Pathname クラスの定数の上書きに関する警告が出る

別バージョンの pathname を require しても,Pathname クラスが入れ換わるわけではなく,上書きされるだけだと思う。
だから,組込みのほうに仮に xxx というメソッドがあったとして,その xxx を持たないバージョンを require したとしても,xxx が消えたりはしないのではないかと思う。
そうだとすれば,これが問題を引き起こすこともありうるのではないか。

set

  • gem 版には存在する Set::VERSION 定数が存在しない
  • require 無しで使える
  • set gem を require することはできないぽい(require でエラーは出ないが,gem 版が読み込まれたようには見えない)
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?