👋

【bugs.ruby Advent Calender】Hash の省略記法の末尾の改行を無視するかどうかの話【7日目】

2024/12/07に公開

bugs.ruby Advent Calender 7日目の記事です。

これはなに

今年1年間通してみてきた bugs.ruby のチケットの中から気になったものを1つずつ取り上げていく Advent Calender です。
取り上げるチケットは基本的にこのブログで取り上げたものになります。
記事のまとめは ここを参照 してください。

Hash の省略記法の末尾の改行を無視するかどうかの話

珍しく matz が立てた issues になります。
Ruby 3.2 から以下のように Hash の値を省略して定義できるようになりました。

name = "homu"

# 値がない場合は name を参照する
# pp name: name と同じ意味
pp name:
# => {:name=>"homu"}

これを踏まえた上で次のコードをみてもらいたいんですがこれは意図する挙動になりません。

name = "homu"
age = 14

# pp name: name と pp age: age を期待するがシンタックスエラーになる
pp name:
pp age:

なぜなら構文としては name:<改行>次の行を値として参照しようとするからです。
なので上のコードは以下のように解釈されます。

name = "homu"
age = 14

# syntax error, unexpected label, expecting `do' or '{' or '('
pp name: pp age:

これはそもそも name:<改行> のような書き方は Hash の省略記法が導入される前から有効な構文として扱わているためですね。

# name: "homu" と解釈される
pp name:
   "homu"

チケットの内容としては name:<改行> のときに次の行を考慮するか無視するか、みたいな内容になっています。
ただ、単純に無視するようにした場合に既存のコードにかなり影響があるみたいでこのチケットでは特に対応されずに閉じられています。

ちなみに元々は mruby のメソッド定義の話から発展した話なんですが、例えば mruby の場合は次のようなメソッド定義をした場合に次の行を含めます。

# mruby だと def foo(arg: 123) と同等になる
def foo arg:
  123
end

しかし、CRuby の実装では次の行を無視するような実装になっているらしいです。

# CRuby は def foo(arg:) と同等になる
def foo arg:
  123
end

ここら辺の挙動の差異から発展した話みたいですねー。

関連

GitHubで編集を提案

Discussion