Class: Plumb::HashMap
- Inherits:
-
Object
- Object
- Plumb::HashMap
- Includes:
- Composable, CovariantFusion
- Defined in:
- lib/plumb/hash_map.rb
Defined Under Namespace
Classes: FilteredHashMap
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
Instance Method Summary collapse
-
#accepted_type ⇒ Object
As a consumer, a HashMap accepts keys/values relaxed to what its key and value types accept (see HashClass#accepted_type).
- #call(result) ⇒ Object
- #filtered ⇒ Object
-
#initialize(key_type, value_type) ⇒ HashMap
constructor
A new instance of HashMap.
-
#output_type ⇒ Object
The value you GET after re-mapping each key/value: both resolved to what they produce (mirror of #accepted_type).
-
#subtype_of?(other) ⇒ Boolean
A HashMap is a Hash, so it is a subtype of the "any Hash" top — an empty-schema HashClass like Types::Hash — or of an open catch-all-only HashClass
Hash[_: V]when this map's value type is a subtype ofV(the catch-all's Any key admits any map key). -
#value_preserving? ⇒ Boolean
A HashMap re-maps each key and value through its key/value types, so it preserves the value only when both do (a coercing key or value would change the hash).
-
#with_children(children) ⇒ Object
Rebuild around new children (see Plumb::Subtyping.map_children).
Methods included from CovariantFusion
Methods included from Composable
#&, #/, #>>, #[], #absorb_input, #absorb_output, #as_node, #build, #check, #defer, #fusable_step?, #fuse_with, #generate, #idempotent?, included, #input_type, #invalid, #invoke, #match, #metadata, #not, #pipeline, #policy, resolve_operand, #static, #subtype_identity, #to_json_schema, #to_mermaid, #to_plumb_type, #to_s, #transform, #value, #where, #with, wrap, #|
Methods included from Callable
Constructor Details
#initialize(key_type, value_type) ⇒ HashMap
Returns a new instance of HashMap.
12 13 14 15 16 17 |
# File 'lib/plumb/hash_map.rb', line 12 def initialize(key_type, value_type) @key_type = key_type @value_type = value_type @children = [key_type, value_type].freeze freeze end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
10 11 12 |
# File 'lib/plumb/hash_map.rb', line 10 def children @children end |
Instance Method Details
#accepted_type ⇒ Object
As a consumer, a HashMap accepts keys/values relaxed to what its key and value types accept (see HashClass#accepted_type).
49 |
# File 'lib/plumb/hash_map.rb', line 49 def accepted_type = Plumb::Subtyping.map_children(self) { |c| Plumb::Subtyping.accepted_type(c) } |
#call(result) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/plumb/hash_map.rb', line 55 def call(result) return result.invalid!(errors: 'must be a Hash') unless result.value.is_a?(::Hash) errors = {} parsed = result.value.each.with_object({}) do |(key, value), memo| key_r = @key_type.resolve(key) value_r = @value_type.resolve(value) errs = [] errs << "key #{key_r.errors}" unless key_r.valid? errs << "value #{value_r.value.inspect} #{value_r.errors}" unless value_r.valid? errors[key] = errs unless errs.empty? memo[key_r.value] = value_r.value end errors.empty? ? result.valid!(parsed) : result.invalid!(errors:) end |
#filtered ⇒ Object
73 74 75 |
# File 'lib/plumb/hash_map.rb', line 73 def filtered FilteredHashMap.new(@key_type, @value_type) end |
#output_type ⇒ Object
The value you GET after re-mapping each key/value: both resolved to what they produce (mirror of #accepted_type).
53 |
# File 'lib/plumb/hash_map.rb', line 53 def output_type = Plumb::Subtyping.map_children(self) { |c| Plumb::Subtyping.resolved_output(c) } |
#subtype_of?(other) ⇒ Boolean
A HashMap is a Hash, so it is a subtype of the "any Hash" top — an
empty-schema HashClass like Types::Hash — or of an open catch-all-only
HashClass Hash[_: V] when this map's value type is a subtype of V (the
catch-all's Any key admits any map key). It is NOT a subtype of a HashClass
that requires specific keys a map doesn't guarantee. Against another HashMap
it is covariant in key and value types (handled by the default #subtype_of?).
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/plumb/hash_map.rb', line 25 def subtype_of?(other) if other.is_a?(HashClass) return true if other._schema.empty? # Maps constrain every value but do not guarantee any named key is present. return false if other.literal_fields.any? { |k, _| !k.optional? } return other._schema.all? { |_k, field| Plumb::Subtyping.subtype?(@value_type, field) } end super end |
#value_preserving? ⇒ Boolean
A HashMap re-maps each key and value through its key/value types, so it preserves the value only when both do (a coercing key or value would change the hash).
41 |
# File 'lib/plumb/hash_map.rb', line 41 def value_preserving? = children.all? { |c| Plumb::Subtyping.value_preserving?(c) } |
#with_children(children) ⇒ Object
Rebuild around new children (see Plumb::Subtyping.map_children). self.class (not HashMap) preserves FilteredHashMap's leniency.
45 |
# File 'lib/plumb/hash_map.rb', line 45 def with_children(children) = self.class.new(children[0], children[1]) |