fall 0.0.0.1 → 0.0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f15339eae553d84b9a1535bccf55158dcf4226166351045e8caae18cbdca8eea
4
- data.tar.gz: c393bd00a8f670b28976f7a23d3cea46c5984fcb85efd89895e2b7a10997dea5
3
+ metadata.gz: b82c155af7534aac00b7de737df75c664d1ea0d36040deb15b6d070814c0efd5
4
+ data.tar.gz: 047eced7160cd08676f866e75607387cc692fd817c1aeab4d0446e50fbd02432
5
5
  SHA512:
6
- metadata.gz: 66dffebddc587b01066dfca71b93c596bef8a89e39d37a86f94fb3da2454497c15b64112ebc5350a0244a8f14feb2841b25c0b31a947ec76c78320ba871db1db
7
- data.tar.gz: 565d2fa8e2d68f7e402f027064377bb86fdc26bf1464a69b412dd2f1baaae442d90ffb1fce4f36983490a200fb034cf7da7ddb95f9f9cbe751317b1445b873be
6
+ metadata.gz: f03f3f0d8b4499e57efed80f8ce29ffefca323cbae6bb9780520bdaffd97d472005f6c7d11f71dd8f18f0bd9ff59d11c1e53a55e7f733c29718c8d21a066ce74
7
+ data.tar.gz: a5dcebb13c3460e1f8062290cf79c0e5a3e193a9d3cc0a6b9d158f00b3792b55950b2a5f78d48ad8c4faa64549d685acb2acf7190527480cc0e7fbd0f1af58b0
data/exe/fall ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ root_path = File.expand_path('../', __dir__)
4
+ require File.join(root_path, 'lib', 'fall.rb')
5
+ require 'optparse'
6
+
7
+ options = {
8
+ input_delimiter: ' ',
9
+ output_delimiter: ' ',
10
+ requirements: [],
11
+ }
12
+
13
+ OptionParser.new do |opts|
14
+ opts.banner = 'Usage: fall [options]'
15
+
16
+ opts.on('-i', '--input-delimiter DELIMITER', 'Input delimiter') do |delimiter|
17
+ options[:input_delimiter] = delimiter
18
+ end
19
+
20
+ opts.on('-o', '--output-delimiter DELIMITER', 'Output delimiter') do |delimiter|
21
+ options[:output_delimiter] = delimiter
22
+ end
23
+
24
+ opts.on('-r', '--require LIB', 'Require a gem or file') do |lib|
25
+ options[:requirements] << lib
26
+ end
27
+ end.parse!
28
+
29
+ options => { input_delimiter:, output_delimiter:, requirements: }
30
+
31
+ requirements.each do |lib|
32
+ require lib
33
+ end
34
+
35
+ command = ARGV.shift
36
+ enum = ARGF.each_line
37
+ .map(&:chomp)
38
+ .map { |row| row.split(input_delimiter) }
39
+ .lazy
40
+
41
+ parser = Fall::Parser.new(command)
42
+ operations = parser.parse
43
+ pipeline = Fall::Pipeline.new(enum)
44
+
45
+ operations.each do |operation|
46
+ pipeline.add_operation(operation)
47
+ end
48
+
49
+ pipeline.to_enum
50
+ .map { _1.respond_to?(:join) ? _1.join(output_delimiter) : _1 }
51
+ .each { puts _1 }
@@ -0,0 +1,11 @@
1
+ module Fall
2
+ module Ext
3
+ module Enumerable
4
+ def window_timestamps(window_size_seconds = 3600)
5
+ group_by { |ts| (ts.to_time.to_i / window_size_seconds) * window_size_seconds }
6
+ .transform_keys { |ts| Time.at(ts) }
7
+ .map { |k, v| { k => v } }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Fall
2
+ module Ext
3
+ module Enumerator
4
+ class Lazy
5
+ def stream
6
+ self
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ module Fall
2
+ module Helpers
3
+ def deflate(...)
4
+ Zlib::Deflate.deflate(...)
5
+ end
6
+
7
+ def inflate(...)
8
+ Zlib::Inflate.inflate(...)
9
+ end
10
+
11
+ def deflate!(...)
12
+ Zlib::Deflate.deflate(...).force_encoding('ASCII-8BIT')
13
+ end
14
+
15
+ def inflate!(...)
16
+ Zlib::Inflate.inflate(...).force_encoding('ASCII-8BIT')
17
+ end
18
+
19
+ def deflate64(...)
20
+ Base64.strict_encode64(deflate(...))
21
+ end
22
+
23
+ def inflate64(foo)
24
+ inflate(Base64.strict_decode64(foo))
25
+ end
26
+
27
+ def inflate64bed(...)
28
+ Bed.infer(inflate64(...))
29
+ end
30
+
31
+ def parsedate(...)
32
+ DateTime.parse(...)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,67 @@
1
+ module Fall
2
+ class Parser
3
+ def initialize(string)
4
+ @string = string
5
+ end
6
+
7
+ def stages
8
+ @string.split('|')
9
+ .map(&:strip)
10
+ end
11
+
12
+ def parse
13
+ stages
14
+ .then { identify_streams(_1) }
15
+ .then { consolidate_streams(_1) }
16
+ .then { create_operations(_1) }
17
+ end
18
+
19
+ private
20
+
21
+ def create_operations(tuples)
22
+ result = tuples.reduce([]) do |accum, (type, stages)|
23
+ klass = operation_klass(type)
24
+ operations = stages.map { klass.from_code(_1) }
25
+ [*accum, *operations]
26
+ end
27
+
28
+ result
29
+ end
30
+
31
+ def operation_klass(type)
32
+ case type
33
+ in :record
34
+ RecordOperation
35
+ in :stream
36
+ StreamOperation
37
+ else
38
+ raise ArgumentError, 'Invalid operation type'
39
+ end
40
+
41
+ end
42
+
43
+ def identify_streams(operations)
44
+ case operations
45
+ in [/^stream/] => stream
46
+ [:stream, [stream]]
47
+ in [/^stream/ => stream, *rest]
48
+ [[:stream, [stream]], *identify_streams(rest)]
49
+ in [*pre, /^stream/ => stream]
50
+ [*identify_streams(pre), [:stream, [stream]]]
51
+ in [*pre, /^stream/ => stream, *rest]
52
+ [*identify_streams(pre), [:stream, [stream]], *identify_streams(rest)]
53
+ else
54
+ [[:record, [*operations]]]
55
+ end
56
+ end
57
+
58
+ def consolidate_streams(operations)
59
+ case operations
60
+ in [*pre, [:stream, op_1], [:stream, op_2], *post]
61
+ consolidate_streams([*pre, [:stream, [*op_1, *op_2]], *post])
62
+ else
63
+ operations
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,38 @@
1
+ module Fall
2
+ class Pipeline
3
+ def initialize(source = [].lazy)
4
+ @source = source
5
+ @currently_building_pipeline = nil
6
+ end
7
+
8
+ def add_operation(operation)
9
+ operation.add_to_pipeline(self)
10
+ end
11
+
12
+ def add_record_operation(operation)
13
+ ensure_current_stage_type(RecordOperationPipeline)
14
+ @currently_building_pipeline.add_operation(operation)
15
+ end
16
+
17
+ def add_stream_operation(operation)
18
+ ensure_current_stage_type(StreamOperationPipeline)
19
+ @currently_building_pipeline.add_operation(operation)
20
+ end
21
+
22
+ def to_enum
23
+ @currently_building_pipeline.to_enum
24
+ end
25
+
26
+ private
27
+
28
+ def ensure_current_stage_type(expected_pipeline_klass)
29
+ seal_current_stage unless @currently_building_pipeline in ^expected_pipeline_klass | nil
30
+ @currently_building_pipeline ||= expected_pipeline_klass.new(@source.to_enum)
31
+ end
32
+
33
+ def seal_current_stage
34
+ @source = @currently_building_pipeline.to_enum
35
+ @currently_building_pipeline = nil
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,90 @@
1
+ module Fall
2
+ class Record
3
+ include Fall::Helpers
4
+
5
+ attr_reader :value
6
+
7
+ alphabet = 'abcdefghijklmnopqrstuvwxyz'
8
+ alphabet.chars.each_with_index do |char, index|
9
+ define_method char do
10
+ case @value
11
+ in Enumerable
12
+ self.class.wrap(self.value[index]).value
13
+ else
14
+ self.value
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.wrap(value)
20
+ case value
21
+ in Record
22
+ value
23
+ else
24
+ new(value)
25
+ end
26
+ end
27
+
28
+ private_class_method :new
29
+
30
+ def initialize(value)
31
+ @value = value
32
+ end
33
+
34
+ def zip(other)
35
+ to_ary.zip(other.to_ary)
36
+ end
37
+
38
+ def discard?
39
+ case value
40
+ in :__discard then true
41
+ in [*, :__discard, *] then true
42
+ else false
43
+ end
44
+ end
45
+
46
+ def value
47
+ @parsed_value ||= (
48
+ case @value
49
+ in /^[1-9][0-9]*$/
50
+ @value.to_i
51
+ in /^[0-9\.]+$/
52
+ @value.to_f
53
+ in /{.*?".*?".*?}/
54
+ JSON.parse(@value)
55
+ else
56
+ @value
57
+ end
58
+ )
59
+ end
60
+
61
+ def to_ary
62
+ case value
63
+ in Array
64
+ value
65
+ else
66
+ [value]
67
+ end
68
+ end
69
+
70
+ alias to_a to_ary
71
+
72
+ private
73
+
74
+ def method_missing(method_name, *args, &block)
75
+ if @value.respond_to?(method_name)
76
+ @value.public_send(method_name, *args, &block)
77
+ else
78
+ super
79
+ end
80
+ end
81
+
82
+ def respond_to_missing?(method_name, include_private = false)
83
+ if @value.respond_to?(method_name)
84
+ true
85
+ else
86
+ super
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,50 @@
1
+ module Fall
2
+ class RecordOperation
3
+ attr_reader :func
4
+
5
+ def self.from_code(code)
6
+ func = instance_eval <<~RUBY
7
+ lambda do |record|
8
+ return record if record.discard?
9
+
10
+ result = Record.wrap(record.instance_eval { [#{code}] })
11
+
12
+ filtered = result.zip(record).reject { _1.size != 2 }.map do |result, original_record|
13
+ case result
14
+ in true then original_record
15
+ in false then :__discard
16
+ else result
17
+ end
18
+ end
19
+ Record.wrap(filtered)
20
+ end
21
+ RUBY
22
+ new(func)
23
+ end
24
+
25
+ def initialize(func)
26
+ @func = func
27
+ end
28
+
29
+ def add_to_pipeline(pipeline)
30
+ pipeline.add_record_operation(self)
31
+ end
32
+
33
+ def call(record)
34
+ @func.call(record)
35
+ end
36
+
37
+ def chain(operation)
38
+ identity = ->(i) { i }
39
+
40
+ composed = (func >> (operation.func >> identity))
41
+ self.class.new(composed)
42
+ end
43
+
44
+ alias >> chain
45
+
46
+ def to_proc
47
+ @func
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ module Fall
2
+ class RecordOperationPipeline
3
+ def initialize(source)
4
+ @source = source
5
+ @operation = RecordOperation.new(->(args) { args })
6
+ end
7
+
8
+ def add_operation(operation)
9
+ @operation = @operation.chain(operation)
10
+ end
11
+
12
+ alias add_record_operation add_operation
13
+
14
+ def to_enum(...)
15
+ @source
16
+ .lazy
17
+ .map { |value| Record.wrap(value) }
18
+ .map { |record| @operation.call(record) }
19
+ .reject(&:discard?)
20
+ .map(&:value)
21
+ .to_enum(...)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ module Fall
2
+ class StreamOperation
3
+ attr_reader :func
4
+
5
+ def self.from_code(code)
6
+ func = instance_eval <<~RUBY
7
+ proc do |stream|
8
+ #{code}
9
+ end
10
+ RUBY
11
+ new(func)
12
+ end
13
+
14
+ def initialize(func)
15
+ @func = func
16
+ end
17
+
18
+ def add_to_pipeline(pipeline)
19
+ pipeline.add_stream_operation(self)
20
+ end
21
+
22
+ def to_proc
23
+ @func
24
+ end
25
+
26
+ def call(stream)
27
+ stream.map { Record.wrap(_1) }
28
+ .then {
29
+ @func.call(_1)
30
+ }
31
+ end
32
+
33
+ def chain(operation)
34
+ identity = ->(i) { i }
35
+
36
+ composed = (func >> (operation.func >> identity))
37
+ self.class.new(composed)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ module Fall
2
+ class StreamOperationPipeline
3
+ def initialize(source)
4
+ @source = source
5
+ @operation = StreamOperation.new(->(stream) { stream })
6
+ end
7
+
8
+ def add_operation(operation)
9
+ @operation = @operation.chain(operation)
10
+ end
11
+
12
+ alias add_stream_operation add_operation
13
+
14
+ def to_enum
15
+ @operation.call(@source)
16
+ end
17
+ end
18
+ end
data/lib/fall/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fall
4
- VERSION = "0.0.0.1"
4
+ VERSION = "0.0.0.3"
5
5
  end
data/lib/fall.rb CHANGED
@@ -1,7 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "fall/version"
3
+ require 'zeitwerk'
4
+ require 'active_support/core_ext/hash'
5
+ require 'base64'
6
+ require 'zlib'
7
+ require 'date'
8
+ require '~/repos/bed/lib/bed.rb'
9
+
10
+ RubyVM::YJIT.enable rescue nil
11
+ loader = Zeitwerk::Loader.for_gem
12
+ loader.setup
4
13
 
5
14
  module Fall
6
15
  class Error < StandardError; end
7
16
  end
17
+
18
+ module Enumerable
19
+ include Fall::Ext::Enumerable
20
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fall
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.1
4
+ version: 0.0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - " David Gillis"
8
- bindir: bin
8
+ bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-06 00:00:00.000000000 Z
10
+ date: 2025-04-07 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: zeitwerk
@@ -72,8 +72,18 @@ executables: []
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
- - lib/draft.rb
75
+ - exe/fall
76
76
  - lib/fall.rb
77
+ - lib/fall/ext/enumerable.rb
78
+ - lib/fall/ext/enumerator/lazy.rb
79
+ - lib/fall/helpers.rb
80
+ - lib/fall/parser.rb
81
+ - lib/fall/pipeline.rb
82
+ - lib/fall/record.rb
83
+ - lib/fall/record_operation.rb
84
+ - lib/fall/record_operation_pipeline.rb
85
+ - lib/fall/stream_operation.rb
86
+ - lib/fall/stream_operation_pipeline.rb
77
87
  - lib/fall/version.rb
78
88
  homepage: https://github.com/gillisd/fall
79
89
  licenses:
data/lib/draft.rb DELETED
@@ -1,377 +0,0 @@
1
- require 'active_support/core_ext/hash'
2
- require 'base64'
3
- require 'zlib'
4
- require 'date'
5
- require '~/repos/bed/lib/bed.rb'
6
-
7
- options = { delimiter: ' ', code: nil }
8
-
9
- RubyVM::YJIT.enable rescue nil
10
-
11
- # OptionParser.new do |o|
12
- # o.on('-d DELIMITER', '--delimiter DELIMITER') do |d|
13
- # options[:delimiter] = d
14
- # end
15
- #
16
- # o.on('-e CODE', '--eval CODE') do |e|
17
- # options[:code] = e
18
- # end
19
- #
20
- # end.parse!
21
-
22
- def deflate(...)
23
- Zlib::Deflate.deflate(...)
24
- end
25
-
26
- def inflate(...)
27
- Zlib::Inflate.inflate(...)
28
- end
29
-
30
- def deflate!(...)
31
- Zlib::Deflate.deflate(...).force_encoding('ASCII-8BIT')
32
- end
33
-
34
- def inflate!(...)
35
- Zlib::Inflate.inflate(...).force_encoding('ASCII-8BIT')
36
- end
37
-
38
- def deflate64(...)
39
- Base64.strict_encode64(deflate(...))
40
- end
41
-
42
- def inflate64(...)
43
- inflate(Base64.decode64(...))
44
- end
45
-
46
- def inflate64bed(...)
47
- Bed.infer(inflate64(...))
48
- end
49
-
50
- module Enumerable
51
- def window_timestamps(window_size_seconds = 3600)
52
- group_by { |ts| (ts.to_time.to_i / window_size_seconds) * window_size_seconds }
53
- .transform_keys { |ts| Time.at(ts) }
54
- .map { |k, v| { k => v } }
55
- end
56
- end
57
-
58
- def parsedate(...)
59
- DateTime.parse(...)
60
- end
61
-
62
- alphabet = 'abcdefghijklmnopqrstuvwxyz'
63
- Array.class_eval do
64
- alphabet.chars.each_with_index do |char, index|
65
- define_method char do
66
- self[index]
67
- end
68
- end
69
- end
70
-
71
- Enumerator::Lazy.class_eval do
72
- define_method :stream do
73
- self
74
- end
75
- end
76
-
77
- def lines(enum = ARGF.readlines.lazy)
78
- enum
79
- end
80
-
81
- def identify_streams(operations)
82
- case operations
83
- in [/^stream/] => stream
84
- [:stream, [stream]]
85
- in [/^stream/ => stream, *rest]
86
- [[:stream, [stream]], *identify_streams(rest)]
87
- in [*pre, /^stream/ => stream]
88
- [*identify_streams(pre), [:stream, [stream]]]
89
- in [*pre, /^stream/ => stream, *rest]
90
- [*identify_streams(pre), [:stream, [stream]], *identify_streams(rest)]
91
- else
92
- [[:record, [*operations]]]
93
- end
94
- end
95
-
96
- def consolidate_streams(operations)
97
- case operations
98
- in [*pre, [:stream, op_1], [:stream, op_2], *post]
99
- consolidate_streams([*pre, [:stream, [*op_1, *op_2]], *post])
100
- else
101
- operations
102
- end
103
- end
104
-
105
- def groupup(code)
106
- code = code.split('|')
107
- .map(&:strip)
108
-
109
- consolidate_streams(identify_streams(code))
110
- end
111
-
112
- class Transformer
113
- attr_accessor :source, :func
114
-
115
- def initialize(source:, func:)
116
- @source = source
117
- @func = func
118
- end
119
-
120
- def to_enum(...)
121
- source.map { |*record| func.call(*record) }
122
- .reject do |args|
123
- case args
124
- in [*, :__discard, *] then true
125
- in :__discard then true
126
- else false
127
- end
128
- end
129
- .to_enum(...)
130
- end
131
- end
132
-
133
- class StreamOperation
134
- attr_reader :func
135
-
136
- def self.from_code(code)
137
- func = instance_eval <<~RUBY
138
- proc do |stream|
139
- #{code}
140
- end
141
- RUBY
142
- new(func)
143
- end
144
-
145
- def initialize(func)
146
- @func = func
147
- end
148
-
149
- def add_to_pipeline(pipeline)
150
- pipeline.add_stream_operation(pipeline)
151
- end
152
-
153
- def to_proc
154
- @func
155
- end
156
-
157
- def call(*args)
158
- @func.call(*args)
159
- end
160
-
161
- def chain(operation)
162
- identity = ->(i) { i }
163
-
164
- composed = (func >> (operation.func >> identity))
165
- self.class.new(composed)
166
- end
167
- end
168
-
169
- class RecordOperation
170
- attr_reader :func
171
-
172
- def self.from_code(code)
173
- func = instance_eval <<~RUBY
174
- proc do |*args|
175
-
176
- results = args.flatten(1).instance_eval { [#{code}] }
177
-
178
- foo = results.zip(args).reject { _1.size != 2 }.map do |result, arg|
179
- case result
180
- in true then arg
181
- in false then :__discard
182
- else result
183
- end
184
- end
185
- end
186
- RUBY
187
- new(func)
188
- end
189
-
190
- def initialize(func)
191
- @func = func
192
- end
193
-
194
- def add_to_pipeline(pipeline)
195
- pipeline.add_record_operation(pipeline)
196
- end
197
-
198
- def call(*args)
199
- @func.call(*args)
200
- end
201
-
202
- def chain(operation)
203
- identity = ->(i) { i }
204
-
205
- composed = (func >> (operation.func >> identity))
206
- self.class.new(composed)
207
- end
208
-
209
- alias >> chain
210
-
211
- def to_proc
212
- @func
213
- end
214
- end
215
-
216
- class RecordOperationPipeline
217
- def initialize(source)
218
- @source = source
219
- @operation = RecordOperation.new(->(*args) { args })
220
- end
221
-
222
- def add_operation(operation)
223
- @operation = @operation.chain(operation)
224
- end
225
-
226
- def to_enum(...)
227
- @source.map { |*record| @operation.call(*record) }
228
- .reject do |args|
229
- case args
230
- in [*, :__discard, *] then true
231
- in :__discard then true
232
- else false
233
- end
234
- end
235
- .to_enum(...)
236
- end
237
- end
238
-
239
- class StreamOperationPipeline
240
- def initialize(source)
241
- @source = source
242
- @operation = StreamOperation.new(->(stream) { stream })
243
- end
244
-
245
- def add_operation(operation)
246
- @operation = @operation.chain(operation)
247
- end
248
-
249
- def to_enum
250
- @operation.call(@source)
251
- end
252
- end
253
-
254
- class Pipeline
255
- def initialize(source = [].lazy)
256
- @source = source
257
- @currently_building_pipeline = nil
258
- end
259
-
260
- def add_operation(operation)
261
- operation.add_to_pipeline(self)
262
- end
263
-
264
- def add_record_operation(operation)
265
- ensure_current_stage_type(RecordOperationPipeline)
266
- @currently_building_pipeline.add_operation(operation)
267
- end
268
-
269
- def add_stream_operation(operation)
270
- ensure_current_stage_type(StreamOperationPipeline)
271
- @currently_building_pipeline.add_operation(operation)
272
- end
273
-
274
- def to_enum
275
- @currently_building_pipeline.to_enum
276
- end
277
-
278
- private
279
-
280
- def ensure_current_stage_type(expected_pipeline_klass)
281
- seal_current_stage unless @currently_building_pipeline in ^expected_pipeline_klass | nil
282
- @currently_building_pipeline ||= expected_pipeline_klass.new(@source.to_enum)
283
- end
284
-
285
- def seal_current_stage
286
- @source = @currently_building_pipeline.to_enum
287
- @currently_building_pipeline = nil
288
- end
289
- end
290
-
291
- Processor = lambda do |enum, **input_options|
292
-
293
- options.merge(input_options) => { code:, delimiter: }
294
- operations = groupup code
295
-
296
- lams = operations.map do |type, pipeline|
297
- composed = (
298
- case type
299
- in :record
300
- ops = pipeline.map do |op|
301
- proc do |errors, it|
302
- code = "[#{op}].flatten(1)"
303
- if code
304
- begin
305
- [errors, it.instance_eval(code)]
306
- rescue => e
307
- warn e
308
- errors << e.full_message
309
- [errors, it]
310
- end
311
- else
312
- [errors, it]
313
- end
314
- end
315
- end
316
- identity = ->(i) { i }
317
- composed = ops.reverse.reduce(identity) { |accum, fn| fn >> accum }
318
- composed.curry(2)[[]]
319
- in :stream
320
- ops = pipeline.map do |op|
321
- proc do |stream|
322
- begin
323
- stream = [stream] unless stream.is_a?(Enumerator)
324
- stream.instance_eval(op)
325
- rescue => e
326
- warn e
327
- end
328
- end
329
- end
330
- identity = ->(i) { i }
331
- ops.reverse.reduce(identity) { |accum, fn| fn >> accum }
332
- else
333
- raise "Unknown type: #{type}"
334
- end
335
- )
336
- [type, composed]
337
- end
338
-
339
- enum
340
- .map(&:chomp)
341
- .map { |line| line.split(options[:delimiter]) }
342
- .map { |line| line.reduce([0, {}]) { |(index, hash), field| hash[alphabet[index]] = field; [index + 1, hash] } }
343
- .map(&:last)
344
- .map do |i|
345
- Bed.infer(i)
346
- end
347
- .then { |enum|
348
- lams.reduce(enum) { |accum, (type, lam)|
349
- case type
350
- in :record
351
- accum.map(&lam).map(&:last)
352
- in :stream
353
- [[lam.call(accum.flat_map(&:last))].flatten(1)]
354
- else
355
- raise "Unknown type: #{type}"
356
- end
357
- }
358
- }
359
- .then { |obj|
360
- case obj
361
- in [Array => arr]
362
- arr
363
- in [[Enumerator::Lazy => lazy]]
364
- lazy
365
- in [Enumerator::Lazy => lazy]
366
- lazy
367
- else
368
- obj
369
- end
370
- }
371
- # .map do |record|
372
- # record.join(delimiter) if record.respond_to?(:join)
373
- # puts record
374
- # end
375
- end
376
-
377
- # process.call(options, ARGF.each_line.lazy)