Class: Plumb::ArrayClass

Inherits:
Object
  • Object
show all
Includes:
Composable, CovariantFusion
Defined in:
lib/plumb/array_class.rb

Direct Known Subclasses

ConcurrentArrayClass

Defined Under Namespace

Classes: ConcurrentArrayClass

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from CovariantFusion

#fuse_with

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

#parse, #resolve

Constructor Details

#initialize(element_type: Types::Any) ⇒ ArrayClass

Returns a new instance of ArrayClass.



15
16
17
18
19
20
# File 'lib/plumb/array_class.rb', line 15

def initialize(element_type: Types::Any)
  @element_type = Composable.wrap(element_type)
  @children = [@element_type].freeze

  freeze
end

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



13
14
15
# File 'lib/plumb/array_class.rb', line 13

def children
  @children
end

Instance Method Details

#accepted_typeObject

As a consumer, an Array accepts elements relaxed to what the ELEMENT type accepts — so Array[Integer] >> Array[Integer.build(Money)] composes, mirroring HashClass#accepted_type's per-field relaxation.



40
# File 'lib/plumb/array_class.rb', line 40

def accepted_type = Plumb::Subtyping.map_children(self) { |c| Plumb::Subtyping.accepted_type(c) }

#call(result) ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/plumb/array_class.rb', line 66

def call(result)
  return result.invalid!(errors: 'is not an Array') unless ::Array === result.value

  # map_array_elements uses its own element scratch (below), so `result` is
  # untouched until here — flip it in place rather than allocating a fresh one.
  values, errors = map_array_elements(result)
  return result.valid!(values) unless errors.any?

  result.invalid!(values, errors:)
end

#concurrentObject



47
48
49
# File 'lib/plumb/array_class.rb', line 47

def concurrent
  ConcurrentArrayClass.new(element_type:)
end

#filteredObject



55
56
57
58
59
60
61
62
63
64
# File 'lib/plumb/array_class.rb', line 55

def filtered
  Constraint.new(::Array) >> Function.opaque(inspect: "Array[#{element_type}].filtered",
                                            identity: [:filtered_array, element_type]) do |result|
    arr = result.value.each.with_object([]) do |e, memo|
      r = element_type.resolve(e)
      memo << r.value if r.valid?
    end
    result.valid!(arr)
  end
end

#of(element_type) ⇒ Object Also known as: []



22
23
24
# File 'lib/plumb/array_class.rb', line 22

def of(element_type)
  self.class.new(element_type:)
end

#output_typeObject

The value you GET after re-mapping each element: the element type resolved to what it produces, so Array[String >> Integer].output_type is Array[Integer] (mirror of #accepted_type).



45
# File 'lib/plumb/array_class.rb', line 45

def output_type = Plumb::Subtyping.map_children(self) { |c| Plumb::Subtyping.resolved_output(c) }

#streamObject



51
52
53
# File 'lib/plumb/array_class.rb', line 51

def stream
  StreamClass.new(element_type:)
end

#value_preserving?Boolean

An Array re-maps each element through its element type, so it preserves the value only when that element type does (a coercing element would change the array). This lets #>> drop a redundant Array[Integer] >> Array[Numeric] and #| absorb Array[Integer] | Array[Numeric], matching the scalar case.

Returns:

  • (Boolean)


32
# File 'lib/plumb/array_class.rb', line 32

def value_preserving? = children.all? { |c| Plumb::Subtyping.value_preserving?(c) }

#with_children(children) ⇒ Object

Rebuild around new children (see Plumb::Subtyping.map_children).



35
# File 'lib/plumb/array_class.rb', line 35

def with_children(children) = of(children.first)