Module: Hamster::Associable
Overview
Including Associable in your container class gives it an update_in
method.
To mix in Associable, your class must implement two methods:
fetch(index, default = (missing_default = true))put(index, item = yield(get(index)))get(key)
See Vector#fetch, Vector#put, Hash#fetch, and Hash#put for examples.
Instance Method Summary collapse
-
#dig(key, *rest) ⇒ Object
Return the value of successively indexing into a collection.
-
#update_in(*key_path) {|value| ... } ⇒ Associable
Return a new container with a deeply nested value modified to the result of the given code block.
Instance Method Details
#dig(key, *rest) ⇒ Object
Return the value of successively indexing into a collection.
If any of the keys is not present in the collection, return nil.
keys that the Hamster type doesn't understand, raises an argument error
62 63 64 65 66 67 68 69 |
# File 'lib/hamster/associable.rb', line 62 def dig(key, *rest) value = get(key) if rest.empty? || value.nil? value elsif value.respond_to?(:dig) value.dig(*rest) end end |
#update_in(*key_path) {|value| ... } ⇒ Associable
Return a new container with a deeply nested value modified to the result
of the given code block. When traversing the nested containers
non-existing keys are created with empty Hash values.
The code block receives the existing value of the deeply nested key/index
(or nil if it doesn't exist). This is useful for "transforming" the
value associated with a certain key/index.
Naturally, the original container and sub-containers are left unmodified; new data structure copies are created along the path as needed.
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/hamster/associable.rb', line 36 def update_in(*key_path, &block) if key_path.empty? raise ArgumentError, "must have at least one key in path" end key = key_path[0] if key_path.size == 1 new_value = block.call(fetch(key, nil)) else value = fetch(key, EmptyHash) new_value = value.update_in(*key_path[1..-1], &block) end put(key, new_value) end |