Ruby 3.3で発生する「プロを目指す人のためのRuby入門 改訂2版」との差異について

## はじめに

2023年12月25日に、Rubyの新しいバージョンであるRuby 3.3がリリースされました。
一方、2021年12月2日に出版した書籍「[プロを目指す人のためのRuby入門 改訂2版](https://gihyo.jp/book/2021/978-4-297-12437-3)」（通称・チェリー本。以下、本書）は執筆当時最新だったRuby 3.0を対象にしています。

本書は紙の本であるため、簡単に内容をアップデートすることができません。しかし、何もしないとどんどん内容が古くなってしまい、「本の通りやってみたけど、今使っているRubyとなんか動きが違う」ということになってしまいます。

そこで新しいRubyのバージョンがリリースされて、本書の説明と異なる部分が出てきたときは、毎回ネット上でその差異を説明するようにしています。その説明を読めば、動きが違う部分があってもきっと落ち着いて対処できるはず、という算段です。

というわけで、この記事ではRuby 3.3で発生する「プロを目指す人のためのRuby入門 改訂2版」との差異について説明します（第1版との差異ではないのでご注意ください）。

また、「プロを目指す人のためのRuby入門 改訂2版」を持っていない人でも役に立ちそうなRuby 3.3の新機能や変更点もあわせて紹介します！

なお、本文に出てくる章番号や項番号は、書籍の中で使われている番号です。

### 参考: もう読みましたか？Ruby 3.1、3.2との差異はこちら
Ruby 3.1と3.2で発生する差異については以下の記事にまとめてあります。

https://qiita.com/jnchito/items/bbabb21a1ce3f4799b52

https://qiita.com/jnchito/items/d4562c8116bb705517e2

上記の記事と重複する内容はこの記事では説明しません。
ですので、まだ読まれていない方は先に上の記事を読んでから、この記事に戻ってくることをお勧めします。

それでは以下が本編です。

## 本文の説明と実行結果が異なるもの

以下で説明する内容は、Ruby 3.3で実行した場合に本書（つまりRuby 3.0）で説明している内容と実行結果が異なる部分です。

### irbのプロンプト表示が少し変わった（1.6、本書全般）

Ruby 3.3ではプロンプトの`:0`が表示されなくなりました。

```
# 本書の記述
irb(main):001:0> 

# Ruby 3.3
irb(main):001> 
```

### NoMethodErrorやNameError発生時のエラーメッセージが少し変わった（本書全般）

Ruby 3.3ではNoMethodErrorが発生したときのエラーメッセージが少し変わります（"for"から後ろのメッセージがシンプルになる）。
以下に具体例をいくつか挙げます。

3.2.5項でテストが失敗した場合：

```
# 本書の記述
NoMethodError: undefined method `upcase' for nil:NilClass

# Ruby 3.3
NoMethodError: undefined method `upcase' for nil
```

3.3.2項のエラーメッセージ：

```
# 本書の記述
NoMethodError: undefined method `fizz_buzz' for #<FizzBuzzTest:0x00007fcd728d2fd8 ……省略>

# Ruby 3.3
NoMethodError: undefined method `fizz_buzz' for an instance of FizzBuzzTest
```

4.5節のエラー：

```ruby
# 本書の記述
1..5.include?(1) #=> undefined method `include?' for 5:Integer (NoMethodError)

# Ruby 3.3
1..5.include?(1) #=> undefined method `include?' for an instance of Integer (NoMethodError)
```

NameErrorも同様にメッセージが少し変わります。

2.2.8項のエラーメッセージ：

```ruby
# 本書の記述
x #=> undefined local variable or method `x' for main:Object (NameError)

# Ruby 3.3
x #=> undefined local variable or method `x' for main (NameError)
```

上に挙げた例は本書の一部です。NoMethodErrorやNameErrorは本書のあちこちに出てくるので、Ruby 3.3ではエラーメッセージの形式が変わったことを頭の片隅に置きながら読み進めるようにしてください。

### 13.6節のサンプルコードが警告ではなくエラーになる

13.6節で紹介したサンプルコードはRuby 3.3から警告ではなくエラーが発生します。

```ruby
# Ruby 3.3では警告ではなくエラー
lambda(&proc{})
#=> the lambda method requires a literal block (ArgumentError)
```

こちらに関してはrbenvなどを使ってRuby 3.0〜3.2をインストールし、そちらで警告が出ることを確認するようにしてください。

## その他、Ruby 3.3で注目したい新機能や変更点

ここから下では「プロを目指す人のためのRuby入門」を読んだ方なら知っておいて損のない、注目の新機能や変更点を紹介していきます。

### it という名前のメソッドの呼び出しで警告が出る場合がある（4.8.5項に関連）

Ruby 3.3ではブロックの内部で `it` という名前のメソッドがレシーバも引数もブロックもなしに呼ばれた場合に警告を出すようになります。

```ruby
def it = 10

# Ruby 3.3
[1, 2, 3].map { it * 10 }
#=> warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it() or self.it
#=> [100, 100, 100]
```

これはRuby 3.4で番号指定パラメータの `_1` と同じ役割を持つ `it` が導入される予定になっているためです。

```ruby
# Ruby 2.7 or higher
[1, 2, 3].map { _1 * 10 }
#=> [10, 20, 30]

# Ruby 3.4（2024年12月25日リリース予定）
[1, 2, 3].map { it * 10 }
#=> [10, 20, 30]
```

この仕様変更に関する詳しい内容は以下の記事を参照してください。

https://qiita.com/jnchito/items/d7def2e87a9c4447ab63

### 特定のライブラリをGemfileへの追加なしにrequireすると警告が出るようになった（第2章のコラム「gem化が進む標準ライブラリ」と13.9.2に関連）

Ruby 3.3では将来的にbundled gemに移行する予定がある標準ライブラリをGemfileに追加せずrequireすると、警告が出るようになりました。


たとえば以下のように bigdecimal ライブラリをrequireするRubyスクリプトがあったとします。

```ruby
require 'bigdecimal'

a = BigDecimal("0.1")
b = BigDecimal("0.2")
puts (a + b).to_f
```

bigdecimal はRuby 3.4でbundled gemに移行する予定になっています。そのため、Gemfileに"bigdecimal"を追加せずに、Bundler経由でこのスクリプトを実行すると、警告が出力されます。

```
$ bundle exec ruby sample.rb 
sample.rb:1: warning: bigdecimal was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add bigdecimal to your Gemfile or gemspec.
0.3
```

Gemfileに`gem 'bigdecimal'`を追加してから実行すると、この警告は出なくなります。

```
# Gemfileに gem 'bigdecimal' を追加してから実行すると、警告は出ない
$ bundle exec ruby sample.rb 
0.3
```

ただし、Bundlerを使用せずに実行する場合は警告は出ません。

```
# Bundlerを使用せず、直接スクリプトを実行する場合は警告が出ない
$ ruby sample.rb
0.3
```

より詳しい内容については以下の記事を参照してください。記事の中ではbundled gemについても詳しく説明しています。

https://qiita.com/jnchito/items/67969420ba0050a7e846#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92gemfile%E3%81%B8%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%81%AA%E3%81%97%E3%81%ABrequire%E3%81%99%E3%82%8B%E3%81%A8%E8%AD%A6%E5%91%8A%E3%81%8C%E5%87%BA%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F

### irbで型ベースの入力補完ができるようになった（第2章のコラム「Ruby 2.7以降で使えるirbの便利機能」と13.10節に関連）

Ruby 3.3（正確にはirb 1.9.0以降）では、実験的機能として型ベースの入力補完ができるようになりました。

この機能を使うためにはまず repl_type_completor gem をインストールします。

```
gem install repl_type_completor
```

それから `--type-completor` オプションを付けてirbを起動します。

```
irb --type-completor
```

型ベースの入力補完を有効にすると、ブロックパラメータのメソッド等も型定義に基づいて候補をリストアップしてくれるようになります。

たとえば以下の例は `n` がIntegerであると推測されるので `up` まで入力した時点で `upto` を候補として表示しています。

![Screenshot 2023-12-23 at 18.46.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7465/5e936d7d-01bc-698a-9186-6cae175c23fa.png)

Ruby 3.2では常に正規表現ベースで候補を表示するため、`upto` 以外のメソッドも候補に挙がっていました。

![Screenshot 2023-12-23 at 18.46.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7465/4cc6964c-2633-2328-9bdf-fbad7dc89023.png)

ただし、型ベースの入力補完を有効にするトレードオフとして、候補を表示するまでの時間が遅くなるようです。

より詳しい内容はirbのREADMEを参照してください。

https://github.com/ruby/irb

### 様々なパフォーマンス改善が行われた

Ruby 3.3では様々なパフォーマンス改善が行われています。
技術的に難しい内容になるためここでは詳しく説明しませんが、気になる方はリリースノートの"パフォーマンスの改善"欄を参照してください。

https://www.ruby-lang.org/ja/news/2023/12/25/ruby-3-3-0-released/

## 他にも魅力的な新機能や変更点がたくさん！！

この記事では「プロを目指す人のためのRuby入門」の読者のみなさんが興味を持ちそうな新機能や変更点をピックアップして紹介しましたが、Ruby 3.3にはこのほかにもたくさんの新機能や変更点があります。

筆者が個人的に注目している新機能や変更点については以下の記事にまとめてあるのでぜひご覧ください。

https://qiita.com/jnchito/items/67969420ba0050a7e846

より詳しい内容については以下の情報源に記載されているのでこちらも要チェックです。

https://www.ruby-lang.org/ja/news/2023/12/25/ruby-3-3-0-released/

https://github.com/ruby/ruby/blob/v3_3_0/NEWS.md

https://product.st.inc/entry/2023/12/25/160504

そして、今年も2023年のクリスマスにRuby 3.3を届けてくれたMatzさんやコミッタのみなさんに感謝したいと思います。どうもありがとうございました！
みなさんもぜひRuby 3.3の新機能を試してみてください😉

## まとめ

というわけで、この記事ではRuby 3.3で発生する「プロを目指す人のためのRuby入門 改訂2版」との差異をまとめました。

Ruby 3.2からの差分という観点では、irbの見た目やエラーメッセージの表示がわずかに変わるだけで、言語機能的な部分ではほぼ変化なし、と言ってよいと思います。

「プロを目指す人のためのRuby入門 改訂2版」とこの記事（と、[Ruby 3.1との差異](https://qiita.com/jnchito/items/bbabb21a1ce3f4799b52)、[Ruby 3.2との差異](https://qiita.com/jnchito/items/d4562c8116bb705517e2)）をあわせて読めば、Ruby 3.3でもバリバリと実践的なコードが書けるはずです。まだ「プロを目指す人のためのRuby入門 改訂2版」を購入されていない方は、この機会にぜひ購入を検討してもらえると嬉しいです。みなさん、よろしくお願いします！

### PR：「プロを目指す人のためのRuby入門 改訂2版」について

「プロを目指す人のためのRuby入門 改訂2版」は、他の言語での開発経験があり、これからRubyを始めたい人や、Rubyプログラミングの経験はある程度あるものの、まだまだ自信がない人に向けて、Rubyの言語仕様や開発の現場で役立つ知識を詳しく、ていねいに解説したRubyの入門書です。

改訂2版ではRuby 3.0に完全対応し、「パターンマッチ」の章を新たに追加するなど、第1版に比べてさらに内容が充実しています。

https://gihyo.jp/book/2021/978-4-297-12437-3

改訂2版の変更点については以下のブログ記事で詳しく説明していますので、こちらのぜひチェックしてみてください。

https://blog.jnito.com/entry/2021/12/02/072804