😽

[Feature #20993] class <constant-path> = <expression> という構文を追加するチケット

2024/12/31に公開

[Feature #20993] Allow class <constant-path> = <expression> syntax

  • 以下のように class <constant-path> = <expression> というシンタックスを追加する提案
  • Struct を利用する時に以下のようなコードで利用することが多いです
class MyStruct < Struct.new(:foo, :bar)
  # ...
end
MyStruct = Struct.new(:foo, :bar) do
  # ...
end
  • 前者は基本的には問題ないんですが意図しない匿名クラスが継承リストに含まれるようになります
class MyStruct < Struct.new(:foo, :bar)
  # ...
end

pp MyStruct.ancestors
# => [MyStruct, #<Class:0x0000795132908718>, Struct, Enumerable, Object, Kernel, BasicObject]
  • また、後者の場合はブロックのスコープがクラスではなくてトップレベルとして扱わる問題があります
MyStruct = Struct.new(:foo, :bar) do
  # MyStruct::BAR ではなくて Object::BAR として定義される
  BAR = 1
end
  • これらを回避する手段として以下のように記述することができます
MyStruct = Struct.new(:foo, :bar)

# Struct を定義したあとにクラスを再オープンする
class MyStruct
  BAR = 1
end

pp MyStruct.ancestors
# => [MyStruct, Struct, Enumerable, Object, Kernel, BasicObject]

pp MyStruct::BAR
# => 1
  • このチケットは上記のようなコードを以下のように記述できるようにする提案です
class MyStruct = Struct.new(:foo, :bar)
  # body
end
  • 元々は [Bug #20943] Constant defined in Data.define block から発展した話題ですね
  • なるほど〜〜〜っていう感じの構文ですね
  • クラスオブジェクトであれば Struct に限らず利用できるんですかねー
  • module <constant-path> = <expression> のように module にも対応させるとのこと
GitHubで編集を提案

Discussion