Ruby 3.1の構文アップデート

この記事は「ESM Advent Calendar 2021」の1日目の記事です。

adventar.org

RuboCop のバックエンドでは、Ruby を解析して AST (抽象構文木) の Ruby オブジェクトとして扱えるようにする Parser gem を使っています。Parser gem のメンテナンスは、Ruby の parse.y に入った構文のアップデートを元に行っています。本エントリでは parse.y の観察を元にして、クリスマスのリリース予定までカウントダウンとなっている Ruby 3.1 構文のアップデート (2021年12月1日時点) をまとめてみます。

所感としては、Ruby 3.1 ではいくつかの構文への省略記法を中心に導入されるといった印象です。

新構文

Hash リテラルの値省略の構文が追加される

ruby/ruby@c60dbcd で導入されました。

値を代入した変数を Hash リテラルの要素に記す際に、変数名を Hash のキーとして、値を省略できるようになります。

a = 1
b = 2

{a:, b:} #=> {:a=>1, :b=>2}

以下と同意です。

a = 1
b = 2

{a: a, b: b} #=> {:a=>1, :b=>2}

個人的には、ES6 のプロパティのショートハンドという例もあり、キーと値を "DRY" にできるので良さそうという印象を持っていますが、明示的に書くという見方の好みもありそう?といった印象です。

匿名ブロック移譲の構文が追加される

ruby/ruby@4adb012 で導入されました。

ブロック引数を移譲する際にブロック変数名を省略できるようになります。

def foo(&)
  bar(&)
end

Ruby 3.0 までは引数に何か名前が必要です。

def foo(&block)
  bar(&block)
end

個人的には、&block か &proc 以外ほとんど名前をつけることなさそうなので、そういった情報落ちがない (たぶんほとんどの場合) はこの & という象徴で十分良さそうに思っています (移譲専用というのが少し残念に思うくらい良さそう) 。

なお、匿名ブロック移譲のメソッド定義の外で bar(&) 単独で使おうとすると no anonymous block parameter エラーが発生します。

パターンマッチに pin オペレーターが追加される

ruby/ruby@2186347 と ruby/ruby@fa87f72 で導入されました。

パターンマッチの新構文となる pin オペレータをサポートするようになります。大元のサンプルから持ってくると ^ を使った式をこんな感じでパターンマッチ中で取れるようになります。

Prime.each_cons(2).lazy.find_all { _1 in [n, ^(n + 2)] }.take(3).to_a
#=> [[3, 5], [5, 7], [11, 13]]

既存構文の拡張

endless メソッド定義の本体メソッド呼び出しの括弧が省略可能になる

ruby/ruby@31794d2 で導入されました。

endless メソッド定義の本体メソッド呼び出しの括弧が省略可能になります。

def foo = puts 'Hello'

Ruby 3.0 までは引数にカッコが必須です。

def foo = puts('Hello')

1行パターンマッチのメソッド呼び出しの括弧が省略可能になる

ruby/ruby@ecb6d6a で導入されました。

1行パターンマッチのメソッド呼び出しの括弧が省略可能になります。

[1, 2] => a, b

Ruby 3.0 までは右辺にカッコが必須です。

[1, 2] => [a, b]

Arguments Forwarding のメソッド仮引数のカッコが省略可能になる

ruby/ruby@13a9597 で導入されました。

Arguments Forwarding のメソッド仮引数のカッコが省略可能になります。

def foo a, ...
end

Ruby 3.0 までは仮引数にカッコが必須です。

def foo(a, ...)
end

またデフォルト引数と Arguments Forwarding を一緒に定義できるようにもなっていました。これはカッコの有無に関わらず、Ruby 3.0 では構文エラーだったものです。

def foo(a, b = 42, ...)
end

ここで紹介した構文アップデートは Parser gem 3.0.3.1 までで対応済みで、RuboCop で使おうとすると匿名ブロック移譲でエラーになるのが現状です。修正パッチは PR 送付済みですので、クリスマスリリースには RuboCop でもひととおりの Ruby 3.1 構文は使えるようになっていると思います。

なお、Ruby 3.1 は開発版となります。ちょっと試してみようという場合、rbenv であれば以下でインストールができます。

% rbenv install 3.1.0-dev

以上、Ruby 3.1 の先行プレビュー記事でした。クリスマスリリースが楽しみですね。

「ESM Advent Calendar 2021」の 2日目は @m_pixy のエントリです。