plumb 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +609 -57
  3. data/bench/compare_parametric_schema.rb +102 -0
  4. data/bench/compare_parametric_struct.rb +68 -0
  5. data/bench/parametric_schema.rb +229 -0
  6. data/bench/plumb_hash.rb +109 -0
  7. data/examples/concurrent_downloads.rb +3 -3
  8. data/examples/env_config.rb +2 -2
  9. data/examples/event_registry.rb +127 -0
  10. data/examples/weekdays.rb +1 -1
  11. data/lib/plumb/and.rb +4 -3
  12. data/lib/plumb/any_class.rb +4 -4
  13. data/lib/plumb/array_class.rb +8 -5
  14. data/lib/plumb/attributes.rb +268 -0
  15. data/lib/plumb/build.rb +4 -3
  16. data/lib/plumb/composable.rb +381 -0
  17. data/lib/plumb/decorator.rb +57 -0
  18. data/lib/plumb/deferred.rb +1 -1
  19. data/lib/plumb/hash_class.rb +19 -8
  20. data/lib/plumb/hash_map.rb +8 -6
  21. data/lib/plumb/interface_class.rb +6 -2
  22. data/lib/plumb/json_schema_visitor.rb +59 -32
  23. data/lib/plumb/match_class.rb +5 -4
  24. data/lib/plumb/metadata.rb +5 -1
  25. data/lib/plumb/metadata_visitor.rb +13 -42
  26. data/lib/plumb/not.rb +4 -3
  27. data/lib/plumb/or.rb +10 -4
  28. data/lib/plumb/pipeline.rb +27 -7
  29. data/lib/plumb/policy.rb +10 -3
  30. data/lib/plumb/schema.rb +11 -10
  31. data/lib/plumb/static_class.rb +4 -3
  32. data/lib/plumb/step.rb +4 -3
  33. data/lib/plumb/stream_class.rb +8 -7
  34. data/lib/plumb/tagged_hash.rb +11 -11
  35. data/lib/plumb/transform.rb +4 -3
  36. data/lib/plumb/tuple_class.rb +8 -8
  37. data/lib/plumb/type_registry.rb +5 -2
  38. data/lib/plumb/types.rb +30 -1
  39. data/lib/plumb/value_class.rb +4 -3
  40. data/lib/plumb/version.rb +1 -1
  41. data/lib/plumb/visitor_handlers.rb +6 -0
  42. data/lib/plumb.rb +11 -5
  43. metadata +10 -3
  44. data/lib/plumb/steppable.rb +0 -229
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'date'
3
4
  require 'plumb/visitor_handlers'
4
5
 
5
6
  module Plumb
@@ -23,11 +24,16 @@ module Plumb
23
24
  MAX_ITEMS = 'maxItems'
24
25
  MIN_LENGTH = 'minLength'
25
26
  MAX_LENGTH = 'maxLength'
27
+ FORMAT = 'format'
28
+ ENVELOPE = {
29
+ '$schema' => 'https://json-schema.org/draft-08/schema#'
30
+ }.freeze
26
31
 
27
- def self.call(node)
28
- {
29
- '$schema' => 'https://json-schema.org/draft-08/schema#'
30
- }.merge(new.visit(node))
32
+ def self.call(node, root: true)
33
+ data = new.visit(node)
34
+ return data unless root
35
+
36
+ ENVELOPE.merge(data)
31
37
  end
32
38
 
33
39
  private def stringify_keys(hash) = hash.transform_keys(&:to_s)
@@ -37,7 +43,7 @@ module Plumb
37
43
  end
38
44
 
39
45
  on(:pipeline) do |node, props|
40
- visit(node.type, props)
46
+ visit_children(node, props)
41
47
  end
42
48
 
43
49
  on(:step) do |node, props|
@@ -58,9 +64,12 @@ module Plumb
58
64
  )
59
65
  end
60
66
 
67
+ on(:data) do |node, props|
68
+ visit_name :hash, node._schema, props
69
+ end
70
+
61
71
  on(:and) do |node, props|
62
- left = visit(node.left)
63
- right = visit(node.right)
72
+ left, right = node.children.map { |c| visit(c) }
64
73
  type = right[TYPE] || left[TYPE]
65
74
  props = props.merge(left).merge(right)
66
75
  props = props.merge(TYPE => type) if type
@@ -69,11 +78,10 @@ module Plumb
69
78
 
70
79
  # A "default" value is usually an "or" of expected_value | (undefined >> static_value)
71
80
  on(:or) do |node, props|
72
- left = visit(node.left)
73
- right = visit(node.right)
74
- any_of = [left, right].uniq
81
+ left, right = node.children.map { |c| visit(c) }
82
+ any_of = [left, right].uniq.filter(&:any?)
75
83
  if any_of.size == 1
76
- props.merge(left)
84
+ props.merge(any_of.first)
77
85
  elsif any_of.size == 2 && (defidx = any_of.index { |p| p.key?(DEFAULT) })
78
86
  val = any_of[defidx.zero? ? 1 : 0]
79
87
  props.merge(val).merge(DEFAULT => any_of[defidx][DEFAULT])
@@ -83,22 +91,23 @@ module Plumb
83
91
  end
84
92
 
85
93
  on(:not) do |node, props|
86
- props.merge(NOT => visit(node.step))
94
+ props.merge(NOT => visit_children(node))
87
95
  end
88
96
 
89
97
  on(:value) do |node, props|
90
- props = case node.value
98
+ value = node.children.first
99
+ props = case value
91
100
  when ::String, ::Symbol, ::Numeric
92
- props.merge(CONST => node.value)
101
+ props.merge(CONST => value)
93
102
  else
94
103
  props
95
104
  end
96
105
 
97
- visit(node.value, props)
106
+ visit(value, props)
98
107
  end
99
108
 
100
109
  on(:transform) do |node, props|
101
- visit(node.target_type, props)
110
+ visit_children(node, props)
102
111
  end
103
112
 
104
113
  on(:undefined) do |_node, props|
@@ -108,18 +117,19 @@ module Plumb
108
117
  on(:static) do |node, props|
109
118
  # Set const AND default
110
119
  # to emulate static values
111
- props = case node.value
120
+ value = node.children.first
121
+ props = case value
112
122
  when ::String, ::Symbol, ::Numeric
113
- props.merge(CONST => node.value, DEFAULT => node.value)
123
+ props.merge(CONST => value, DEFAULT => value)
114
124
  else
115
125
  props
116
126
  end
117
127
 
118
- visit(node.value, props)
128
+ visit(value, props)
119
129
  end
120
130
 
121
131
  on(:policy) do |node, props|
122
- props = visit(node.step, props)
132
+ props = visit_children(node, props)
123
133
  method_name = :"visit_#{node.policy_name}_policy"
124
134
  if respond_to?(method_name)
125
135
  send(method_name, node, props)
@@ -168,20 +178,29 @@ module Plumb
168
178
 
169
179
  on(:match) do |node, props|
170
180
  # Set const if primitive
171
- props = case node.matcher
181
+ matcher = node.children.first
182
+ props = case matcher
172
183
  when ::String, ::Symbol, ::Numeric
173
- props.merge(CONST => node.matcher)
184
+ props.merge(CONST => matcher)
174
185
  else
175
186
  props
176
187
  end
177
188
 
178
- visit(node.matcher, props)
189
+ visit(matcher, props)
179
190
  end
180
191
 
181
192
  on(:boolean) do |_node, props|
182
193
  props.merge(TYPE => 'boolean')
183
194
  end
184
195
 
196
+ on(:uuid) do |_node, props|
197
+ props.merge(TYPE => 'string', FORMAT => 'uuid')
198
+ end
199
+
200
+ on(:email) do |_node, props|
201
+ props.merge(TYPE => 'string', FORMAT => 'email')
202
+ end
203
+
185
204
  on(::String) do |_node, props|
186
205
  props.merge(TYPE => 'string')
187
206
  end
@@ -228,6 +247,14 @@ module Plumb
228
247
  props.merge(opts)
229
248
  end
230
249
 
250
+ on(::Time) do |_node, props|
251
+ props.merge(TYPE => 'string', FORMAT => 'date-time')
252
+ end
253
+
254
+ on(::Date) do |_node, props|
255
+ props.merge(TYPE => 'string', FORMAT => 'date')
256
+ end
257
+
231
258
  on(::Hash) do |_node, props|
232
259
  props.merge(TYPE => 'object')
233
260
  end
@@ -245,7 +272,7 @@ module Plumb
245
272
  {
246
273
  TYPE => 'object',
247
274
  'patternProperties' => {
248
- '.*' => visit(node.value_type)
275
+ '.*' => visit(node.children[1])
249
276
  }
250
277
  }
251
278
  end
@@ -254,27 +281,27 @@ module Plumb
254
281
  {
255
282
  TYPE => 'object',
256
283
  'patternProperties' => {
257
- '.*' => visit(node.value_type)
284
+ '.*' => visit(node.children[1])
258
285
  }
259
286
  }
260
287
  end
261
288
 
262
289
  on(:build) do |node, props|
263
- visit(node.type, props)
290
+ visit_children(node, props)
264
291
  end
265
292
 
266
293
  on(:array) do |node, _props|
267
- items = visit(node.element_type)
268
- { TYPE => 'array', ITEMS => items }
294
+ items_props = visit_children(node)
295
+ { TYPE => 'array', ITEMS => items_props }
269
296
  end
270
297
 
271
298
  on(:stream) do |node, _props|
272
- items = visit(node.element_type)
273
- { TYPE => 'array', ITEMS => items }
299
+ items_props = visit_children(node)
300
+ { TYPE => 'array', ITEMS => items_props }
274
301
  end
275
302
 
276
303
  on(:tuple) do |node, _props|
277
- items = node.types.map { |t| visit(t) }
304
+ items = node.children.map { |t| visit(t) }
278
305
  { TYPE => 'array', 'prefixItems' => items }
279
306
  end
280
307
 
@@ -286,7 +313,7 @@ module Plumb
286
313
  }
287
314
 
288
315
  key = node.key.to_s
289
- children = node.types.map { |c| visit(c) }
316
+ children = node.children.map { |c| visit(c) }
290
317
  key_enum = children.map { |c| c[PROPERTIES][key][CONST] }
291
318
  key_type = children.map { |c| c[PROPERTIES][key][TYPE] }
292
319
  required << key
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class MatchClass
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :matcher
9
+ attr_reader :children
10
10
 
11
11
  def initialize(matcher = Undefined, error: nil, label: nil)
12
- raise TypeError 'matcher must respond to #===' unless matcher.respond_to?(:===)
12
+ raise ParseError 'matcher must respond to #===' unless matcher.respond_to?(:===)
13
13
 
14
14
  @matcher = matcher
15
15
  @error = error.nil? ? build_error(matcher) : (error % matcher)
16
16
  @label = matcher.is_a?(Class) ? matcher.inspect : "Match(#{label || @matcher.inspect})"
17
+ @children = [matcher].freeze
17
18
  freeze
18
19
  end
19
20
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Plumb
4
4
  class Metadata
5
- include Steppable
5
+ include Composable
6
6
 
7
7
  attr_reader :metadata
8
8
 
@@ -11,6 +11,10 @@ module Plumb
11
11
  freeze
12
12
  end
13
13
 
14
+ def ==(other)
15
+ other.is_a?(self.class) && @metadata == other.metadata
16
+ end
17
+
14
18
  def call(result) = result
15
19
 
16
20
  private def _inspect = "Metadata[#{@metadata.inspect}]"
@@ -10,23 +10,14 @@ module Plumb
10
10
  new.visit(node)
11
11
  end
12
12
 
13
- def on_missing_handler(node, props, method_name)
13
+ def on_missing_handler(node, props, _method_name)
14
14
  return props.merge(type: node) if node.instance_of?(Class)
15
15
 
16
- puts "Missing handler for #{node.inspect} with props #{node.inspect} and method_name :#{method_name}"
17
- props
18
- end
19
-
20
- on(:undefined) do |_node, props|
21
- props
22
- end
16
+ return props unless node.respond_to?(:children)
23
17
 
24
- on(:any) do |_node, props|
25
- props
26
- end
27
-
28
- on(:pipeline) do |node, props|
29
- visit(node.type, props)
18
+ node.children.reduce(props) do |acc, child|
19
+ visit(child, acc)
20
+ end
30
21
  end
31
22
 
32
23
  on(:step) do |node, props|
@@ -42,17 +33,12 @@ module Plumb
42
33
  props.merge(match: node, type:)
43
34
  end
44
35
 
45
- on(:match) do |node, props|
46
- visit(node.matcher, props)
47
- end
48
-
49
36
  on(:hash) do |_node, props|
50
37
  props.merge(type: Hash)
51
38
  end
52
39
 
53
40
  on(:and) do |node, props|
54
- left = visit(node.left)
55
- right = visit(node.right)
41
+ left, right = node.children.map { |child| visit(child) }
56
42
  type = right[:type] || left[:type]
57
43
  props = props.merge(left).merge(right)
58
44
  props = props.merge(type:) if type
@@ -60,7 +46,7 @@ module Plumb
60
46
  end
61
47
 
62
48
  on(:or) do |node, props|
63
- child_metas = [visit(node.left), visit(node.right)]
49
+ child_metas = node.children.map { |child| visit(child) }
64
50
  types = child_metas.map { |child| child[:type] }.flatten.compact
65
51
  types = types.first if types.size == 1
66
52
  child_metas.reduce(props) do |acc, child|
@@ -68,27 +54,16 @@ module Plumb
68
54
  end.merge(type: types)
69
55
  end
70
56
 
71
- on(:value) do |node, props|
72
- visit(node.value, props)
73
- end
74
-
75
- on(:transform) do |node, props|
76
- props.merge(type: node.target_type)
77
- end
78
-
79
57
  on(:static) do |node, props|
80
- type = node.value.is_a?(Class) ? node.value : node.value.class
81
- props.merge(static: node.value, type:)
58
+ value = node.children[0]
59
+ type = value.is_a?(Class) ? value : value.class
60
+ props.merge(static: value, type:)
82
61
  end
83
62
 
84
63
  on(:policy) do |node, props|
85
- visit(node.step, props).merge(node.policy_name => node.arg)
86
- end
87
-
88
- on(:rules) do |node, props|
89
- node.rules.reduce(props) do |acc, rule|
90
- acc.merge(rule.name => rule.arg_value)
91
- end
64
+ props = visit(node.children[0], props)
65
+ props = props.merge(node.policy_name => node.arg) unless node.arg == Plumb::Undefined
66
+ props
92
67
  end
93
68
 
94
69
  on(:boolean) do |_node, props|
@@ -103,10 +78,6 @@ module Plumb
103
78
  props.merge(type: Hash)
104
79
  end
105
80
 
106
- on(:build) do |node, props|
107
- visit(node.type, props)
108
- end
109
-
110
81
  on(:array) do |_node, props|
111
82
  props.merge(type: Array)
112
83
  end
data/lib/plumb/not.rb CHANGED
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Not
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :step
9
+ attr_reader :children, :errors
10
10
 
11
11
  def initialize(step, errors: nil)
12
12
  @step = step
13
13
  @errors = errors
14
+ @children = [step].freeze
14
15
  freeze
15
16
  end
16
17
 
data/lib/plumb/or.rb CHANGED
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Or
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :left, :right
9
+ attr_reader :children
10
10
 
11
11
  def initialize(left, right)
12
12
  @left = left
13
13
  @right = right
14
+ @children = [left, right].freeze
14
15
  freeze
15
16
  end
16
17
 
@@ -23,7 +24,12 @@ module Plumb
23
24
  return left_result if left_result.valid?
24
25
 
25
26
  right_result = @right.call(result)
26
- right_result.valid? ? right_result : result.invalid(errors: [left_result.errors, right_result.errors].flatten)
27
+ if right_result.valid?
28
+ right_result
29
+ else
30
+ right_result.invalid(errors: [left_result.errors,
31
+ right_result.errors].flatten)
32
+ end
27
33
  end
28
34
  end
29
35
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Pipeline
7
- include Steppable
7
+ include Composable
8
8
 
9
9
  class AroundStep
10
- include Steppable
10
+ include Composable
11
11
 
12
12
  def initialize(step, block)
13
13
  @step = step
@@ -19,11 +19,28 @@ module Plumb
19
19
  end
20
20
  end
21
21
 
22
- attr_reader :type
22
+ class << self
23
+ def around_blocks
24
+ @around_blocks ||= []
25
+ end
26
+
27
+ def around(callable = nil, &block)
28
+ around_blocks << (callable || block)
29
+ self
30
+ end
31
+
32
+ def inherited(subclass)
33
+ around_blocks.each { |block| subclass.around(block) }
34
+ super
35
+ end
36
+ end
37
+
38
+ attr_reader :children
23
39
 
24
40
  def initialize(type = Types::Any, &setup)
25
41
  @type = type
26
- @around_blocks = []
42
+ @children = [type].freeze
43
+ @around_blocks = self.class.around_blocks.dup
27
44
  return unless block_given?
28
45
 
29
46
  configure(&setup)
@@ -38,10 +55,11 @@ module Plumb
38
55
  callable ||= block
39
56
  unless is_a_step?(callable)
40
57
  raise ArgumentError,
41
- "#step expects an interface #call(Result) Result, but got #{callable.inspect}"
58
+ "#step expects an interface #call(Result) Result, but got #{callable.inspect}"
42
59
  end
43
60
 
44
- callable = @around_blocks.reduce(callable) { |cl, bl| AroundStep.new(cl, bl) } if @around_blocks.any?
61
+ callable = prepare_step(callable)
62
+ callable = @around_blocks.reverse.reduce(callable) { |cl, bl| AroundStep.new(cl, bl) } if @around_blocks.any?
45
63
  @type >>= callable
46
64
  self
47
65
  end
@@ -69,5 +87,7 @@ module Plumb
69
87
 
70
88
  true
71
89
  end
90
+
91
+ def prepare_step(callable) = callable
72
92
  end
73
93
  end
data/lib/plumb/policy.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  # Wrap a policy composition ("step") in a Policy object.
7
7
  # So that visitors such as JSONSchema and Metadata visitors
8
8
  # can define dedicated handlers for policies, if they need to.
9
9
  class Policy
10
- include Steppable
10
+ include Composable
11
11
 
12
- attr_reader :policy_name, :arg, :step
12
+ attr_reader :policy_name, :arg, :children
13
13
 
14
14
  # @param policy_name [Symbol]
15
15
  # @param arg [Object, nil] the argument to the policy, if any.
@@ -18,9 +18,16 @@ module Plumb
18
18
  @policy_name = policy_name
19
19
  @arg = arg
20
20
  @step = step
21
+ @children = [step].freeze
21
22
  freeze
22
23
  end
23
24
 
25
+ def ==(other)
26
+ other.is_a?(self.class) &&
27
+ policy_name == other.policy_name &&
28
+ arg == other.arg
29
+ end
30
+
24
31
  # The standard Step interface.
25
32
  # @param result [Result::Valid]
26
33
  # @return [Result::Valid, Result::Invalid]
data/lib/plumb/schema.rb CHANGED
@@ -5,13 +5,13 @@ require 'plumb/json_schema_visitor'
5
5
 
6
6
  module Plumb
7
7
  class Schema
8
- include Steppable
8
+ include Composable
9
9
 
10
10
  def self.wrap(sch = nil, &block)
11
11
  raise ArgumentError, 'expected a block or a schema' if sch.nil? && !block_given?
12
12
 
13
13
  if sch
14
- raise ArgumentError, 'expected a Steppable' unless sch.is_a?(Steppable)
14
+ raise ArgumentError, 'expected a Composable' unless sch.is_a?(Composable)
15
15
 
16
16
  return sch
17
17
  end
@@ -49,8 +49,8 @@ module Plumb
49
49
  self
50
50
  end
51
51
 
52
- def json_schema
53
- JSONSchemaVisitor.call(_hash).to_h
52
+ def to_json_schema
53
+ _hash.to_json_schema(root: true)
54
54
  end
55
55
 
56
56
  def call(result)
@@ -120,7 +120,7 @@ module Plumb
120
120
  block_given? ? ArrayClass.new(element_type: Schema.new(&block)) : type
121
121
  when nil
122
122
  block_given? ? Schema.new(&block) : Types::Any
123
- when Steppable
123
+ when Composable
124
124
  type
125
125
  when Class
126
126
  if type == Array && block_given?
@@ -140,13 +140,14 @@ module Plumb
140
140
  self
141
141
  end
142
142
 
143
- def meta(md = nil)
144
- @_type = @_type.meta(md) if md
145
- self
143
+ def metadata(data = Undefined)
144
+ if data == Undefined
145
+ @_type.metadata
146
+ else
147
+ @_type = @_type.metadata(data)
148
+ end
146
149
  end
147
150
 
148
- def metadata = @_type.metadata
149
-
150
151
  def options(opts)
151
152
  @_type = @_type.options(opts)
152
153
  self
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class StaticClass
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :value
9
+ attr_reader :children
10
10
 
11
11
  def initialize(value = Undefined)
12
12
  raise ArgumentError, 'value must be frozen' unless value.frozen?
13
13
 
14
14
  @value = value
15
+ @children = [value].freeze
15
16
  freeze
16
17
  end
17
18
 
data/lib/plumb/step.rb CHANGED
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plumb/steppable'
3
+ require 'plumb/composable'
4
4
 
5
5
  module Plumb
6
6
  class Step
7
- include Steppable
7
+ include Composable
8
8
 
9
- attr_reader :_metadata
9
+ attr_reader :_metadata, :children
10
10
 
11
11
  def initialize(callable = nil, inspect = nil, &block)
12
12
  @_metadata = callable.respond_to?(:metadata) ? callable.metadata : BLANK_HASH
13
13
  @callable = callable || block
14
+ @children = [@callable].freeze
14
15
  @inspect = inspect || @callable.inspect
15
16
  freeze
16
17
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thread'
4
- require 'plumb/steppable'
4
+ require 'plumb/composable'
5
5
 
6
6
  module Plumb
7
7
  # A stream that validates each element.
@@ -15,18 +15,19 @@ module Plumb
15
15
  # result.value # => ['name', 10]
16
16
  # end
17
17
  class StreamClass
18
- include Steppable
18
+ include Composable
19
19
 
20
- attr_reader :element_type
20
+ attr_reader :children
21
21
 
22
- # @option element_type [Steppable] the type of the elements in the stream
22
+ # @option element_type [Composable] the type of the elements in the stream
23
23
  def initialize(element_type: Types::Any)
24
- @element_type = Steppable.wrap(element_type)
24
+ @element_type = Composable.wrap(element_type)
25
+ @children = [@element_type].freeze
25
26
  freeze
26
27
  end
27
28
 
28
29
  # return a new Stream definition.
29
- # @param element_type [Steppable] the type of the elements in the stream
30
+ # @param element_type [Composable] the type of the elements in the stream
30
31
  def [](element_type)
31
32
  self.class.new(element_type:)
32
33
  end
@@ -39,7 +40,7 @@ module Plumb
39
40
 
40
41
  enum = Enumerator.new do |y|
41
42
  result.value.each do |e|
42
- y << element_type.resolve(e)
43
+ y << @element_type.resolve(e)
43
44
  end
44
45
  end
45
46