【一人 bugs.ruby Advent Calendar 2020】[Feature #16986] Anonymous Struct literal【7日目】

一人 bugs.ruby Advent Calendar 2020 7日目の記事になります。

[Feature #16986] Anonymous Struct literal

このチケットは Struct を定義する新しいリテラルの提案です。
提案自体はそこまで複雑な内容ではなくて Struct.new(:a, :b).new(1, 2)${a: 1, b: 2} みたいなリテラルで定義する事ができる提案になります。

s = ${a: 1, b: 2, c: 3}
s.a  # => 1
s.b  # => 2
s.c  # => 3

ちなみに提案されるまでの経緯はこちらです。
ツイッターでまつもとさんとやり取りされているんですが読んでみるとどういう経緯で立ったのかがわかって面白いです。
今はゆってもそこまで Struct を使うことはないんですがこういうリテラルがあるといろんなところで使いそうだと思います。
例えばこんな感じに雑にダックタイピング呼び出しするメソッドに値を渡す場合とかに利用できそうだと思っています。

def print(user)
  pp "#{user.id} #{user.name}"
end

name = "homu"
age = 14
# Struct を経由してメソッド呼び出しされるようにする
print(${ name: name, age: age })

また Struct だと obj.value だけじゃなくて obj[:value] みたいに添え字アクセスもできるので Hash オブジェクトの代わりとして使用できそうですね。

# Hash の場合は typo してても気づきづらい
user = { name: "homu", age: 14 }
# no error
user[:nmae]

# Struct Anonymousだと存在しないキーにアクセスするとエラーになる
user = Struct.new(:name, :age).new("homu", 14)
# error
user[:nmae]

他には ${} だとブロックと差別化できるのでよかったりとかいろいろと夢は広がる。

# これはエラー
p { a: 1, b: 2 }

# これは OK
p ${ a: 1, b: 2 }

Struct と Anonymous Struct literal については今年の『とちぎ Ruby会議』でもお話したのでそちらのスライドも読んでみるといいと思います。