🍣
[Feature #21387] 各メンバーの要素にアクセスできる Data#[] を追加する提案
[Feature #21387] Proposal to add Data#[]
- 各メンバーの要素にアクセスできる
Data#[]を追加する提案 -
data.idをdata[:id]やdata["id"]のようによりHashライクにアクセスできる提案ですね - また
Hashとは異なりdata[:invalid]のときにinvalidがメンバーに存在しなければNameErrorが発生する想定です - モチベーションとしてはダックタイピング的に
#[]にアクセスできるようになると他の機能で利用しやすい、みたいな点があげられていますね - 例えば ActiveSupport の
Enumerable#pluckなど
# data_test.rb
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "activesupport", "8.0.2"
end
require "active_support/core_ext/enumerable"
StructPerson = Struct.new(:name, :age)
DataPerson = Data.define(:name, :age)
struct_people = [
StructPerson.new("Bob", 25),
]
puts "Struct:"
# #pluck では内部で obj[:name] を経由して値を取得する
puts "=> #{struct_people.pluck(:name)}"
# => ["Bob"]
data_people = [
DataPerson.new("Charlie", 35),
]
puts "Data:"
# Data でも同要に #pluck を利用したい場合は Data#[] が定義されている必要がある
puts "=> #{data_people.pluck(:name)}"
- これに関してなんですが
Dataの設計としては『可能な限りシンプルなアトミックオブジェクト』にすることで#[]を定義するとより『コンテナ』として扱われてしまう、のを危惧しているみたいですね-
Dataとしては動的よりもより静的に近づける、みたいなイメージですかね?- コメントの中では
OpenStructも引き合いに出されてますね
- コメントの中では
-
#[]以外でよりHash / Structライクにしないのか、みたいな話にも広がってくる、みたいな懸念点もあるみたい - https://bugs.ruby-lang.org/issues/21387#note-1
-
- このあたりはどこまでなにを追加するのかが難しそうですねー
Data#to_hを介せばHashに変換できるのでそれで対応できますが、とはいえ都度#to_h呼び出すのも手間ですし- そもそも
Data#[]を呼び出したいケースは限られている気もするし
- そもそも
- 個人的にはダックタイピング的な意味で
Data#[]が定義されている方が便利そうな気がしますがどうなんだろうな〜-
#digとかでも利用できれば嬉しい
-
- 最終的にはより魅力的なユースケースがない限りは
Dataの拡張はやめるべき、みたいな結論になったみたいですね - もし、今回のような拡張を行いたい場合は次のように mixin して回避するコードも提示されています
# #[] でメソッドにアクセスできるような拡張モジュール
module DynamicallyAccessibleData
def [](name)
unless members.include?(name.to_sym)
raise NameError, "no member '#{name}' in data"
end
public_send(name)
end
end
# Data で定義したクラスに対して #[] でアクセスできるようなモジュールを mixin する
Person = Data.define(:name, :age).include(DynamicallyAccessibleData)
person = Person.new(name: "Charlie", age: 35)
# DynamicallyAccessibleData を mixin しておくことで #[] が利用できるようになる
person[:name] #=> "Charlie"
person[:age] #=> 35
person[:foo] #=> NameError: no member 'foo' in data
- これだとそこそこの対応コストでいい感じに利用できそうですねー
Discussion