Feature #22012
closedData class should respond to #dig
Description
Datas cousin, Struct already responds to #dig. Data objects can show up in deeply nested objects as well, and the semantics of this should be nearly identical to Struct#dig
Updated by zverok (Victor Shepelev) 23 days ago
This was a conscious design decision on Data implementaion, that underlines its nature.
Struct has a two-fold nature: it is both "a mutable structured object" and "a container" (has #[], #each, includes Enumerable).
Data is a base for composite value objects; so in designing it, the focus was on other composite value objects in Ruby, like Time. We don't have Time.now.dig(:year) and things like that, making a distinction between "navigable containers" and "atomic value objects". If Data-based class used in some context as a base of a container-like object, the implementation of #dig is relatively trivial:
class Locations < Data.define(:work, :home, :shelter)
def dig(first, *rest)
return unless members.include?(first)
send(first).then { rest.empty? ? it : it.dig(*rest) }
end
end
Updated by matz (Yukihiro Matsumoto) 3 days ago
- Status changed from Open to Closed
Thank you for the proposal, and thank you @zverok (Victor Shepelev) for the detailed explanation.
I agree with @zverok (Victor Shepelev). The absence of #dig on Data is intentional. Data is designed as a base for composite value objects, not as a navigable container. This is the same reason it does not have #[], #each, or Enumerable.
The dig family (Hash#dig, Array#dig, Struct#dig) is built for objects that expose #[] for element access. Data deliberately does not provide #[], so adding #dig alone would be inconsistent with the rest of the language.
I would also like to keep Data's API small. When a Data-based class is used in a container-like role, defining #dig yourself is straightforward, as @zverok (Victor Shepelev) showed.
So I will decline this one. Thank you again for thinking it through.
Matz