Ruby 3.1.0 preview1 でたよ
でました。
リリースノートはこちら。
rbenv を使っている方は、
$ rbenv install 3.1.0-preview1
してもらえるとローカルにインストールすることができます。
以下、気になった機能追加や変更点など。
新しい JIT コンパイラとして実験的に YJIT が追加された
Ruby 3.1 では新しい JIT コンパイラとして YJIT が追加されます。
YJIT はデフォルトでは有効になっていないので有効にする場合は Ruby のコマンドプションに --yjit
を指定する必要があります。
YJIT を使用することで Rails のベンチが最大22%向上するらしいですね、すごい。
また現状 YJIT は macOS と Linux の x86-64 環境でのみ対応しているらしいです。
新しいデバッガとして debug gem がバンドルされる
Ruby 3.1 から新しいデバッガとして debug gem がバンドルされます。
ここで説明するよりも RubyKaigi の内容を見てもらった方がよいと思います。
byebug のように端末で詳細なデバッグができる他 VSCode や Chrome の devtools でもデバッグ操作ができます。
これはとにかく楽しみでしょうがないので早く使いたいです。
また Ruby 3.1 にバンドルされるようになるんですが Ruby 2.6 以上であれば
$ gem install debug
で debug gem を使用する事ができます。
列単位でエラー箇所を表示する error_highlight が追加
例えば次のようなコードでエラーになった時にどこでエラーになっているのか分かりづらい事があります。
ruby -e "{user:'homu'}[:ser][:name]" -e:1:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
error_highlight
は次のようにどこでエラーになっているのかを表示してくれる機能になります。
$ RBENV_VERSION=3.1.0-preview1 ruby -e "{user:'homu'}[:ser][:name]" -e:1:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError) {user:'homu'}[:ser][:name] ^^^^^^^
これは普通に便利なので早くほしい。
Hash リテラルで参照する値がキー名と同じなら省略できる
これ!前からほしかったやつ!!!! Hash リテラルを定義する時に値を省略するとキーと同じ名前の変数やメソッドを参照するようになります。
def name "homu" end age = 42 # 値を省略するとその名前の変数やメソッドを参照する # { id: 1, name: name, age: age } と同じ意味 homu = { id: 1, name:, age: } pp homu # => {:id=>1, :name=>"homu", :age=>42} # Hash リテラルだけではなくてメソッドのキーワード引数としても渡せる # pp(name: name, age: age) と同じ意味 pp(name:, age:) # => {:name=>"homu", :age=>42}
パターンマッチの ^
が式を受け取るようになった
パターンマッチの ^
で直接式をかけるようになりました。
今までは以下のように変数に代入する必要があったんですが
# 一度変数に入れてから ^ で変数を参照する必要があった range = Time.new(2010)..Time.new(2020) case data in { created_at: ^range } end
Ruby 3.1 からは以下のように直接式を書くことができます。
case data # ^ で直接式を書くことができるようになった in { created_at: ^(Time.new(2010)..Time.new(2020)) } end
これは普通に便利ですね。
1行パターンマッチが Experimental でなくなった
機能としては Ruby 3.0 から実験的に実装されていたんですが Ruby 3.1 からは実験的でなくなりました。
なので次のようなコードを書いても Experimental Warning
がでなくなります!!
# 3.0 : warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! # 3.1 : no warning user = { name: "homu", age: 14 } user => { name:, age: } p name # = "homu" p age # = 14
refine
内での include / prepend
が非推奨になり変わりに import_methods
が追加された
これは別途まとめたいと思うんですが refine
内で include / prepend
したときの挙動が意図しないことが多かったので非推奨になり、変わりに import_methods
という機能が追加されました。
今までだと例えば複数のクラスで共通のメソッドを定義したい場合に以下のように include
していました。
using Module.new { module Twice def twice self + self end end refine String do include Twice end refine Integer do include Twice end } pp "homu".twice pp 42.twice
Ruby 3.1 からは以下のように import_methods
を使うことが推奨されます。
using Module.new { module Twice def twice self + self end end refine String do import_methods Twice end refine Integer do import_methods Twice end } # 使い方は一緒 pp "homu".twice pp 42.twice
大きな違いとしては『 include
する Module
のメソッドが別のメソッド呼び出す時の挙動』が違います。
using Module.new { module Twice def twice self + self end def double twice end end refine String do import_methods Twice end refine Integer do include Twice end } # OK : Twice#double 内から Twice#twice を呼び出せる p "homu".twice # NG : Twice#double 内から Twice#twice が呼び出せない p 42.double
既存のコードが非互換になってしまうのはちょっとつらいですが使い勝手はこっちのほうが圧倒的によいので早く移行したいですねえ。
両コードをサポートする場合どうするのがよいだろうか。
と、言う感じで Ruby 3.1 でも色々と機能が追加されるので楽しみですね!