ex_aequo_streams 0.1.0 → 0.1.1
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 +4 -4
- data/lib/ex_aequo/streams/stream/class_methods.rb +6 -10
- data/lib/ex_aequo/streams/stream/empty.rb +12 -1
- data/lib/ex_aequo/streams/stream/func_methods.rb +84 -0
- data/lib/ex_aequo/streams/stream/stream_methods.rb +60 -0
- data/lib/ex_aequo/streams/stream.rb +7 -48
- data/lib/ex_aequo/streams/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae3e6d30027b024529d7e8ca5046e188e81fd8c9803869c08324974a8303ecfe
|
4
|
+
data.tar.gz: 4ba3a1aecd827bd6bc1cd5b06b7bb50e1292041d87a0e906b9f4ca8a8a69239f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a03fba937252d9fd90d637b6aa58622fbb75640029fa9c1cbfd7c8d538aeaa09e4c3ee06551aaea500ad153760efe2142e965df00d888f4b35a4faf0e6322829
|
7
|
+
data.tar.gz: 6c88b678b4b5e9b62ec05f92a3ee4aca8c85030b53a8cda1553197ac882f53f9265071ef888839ed1a252567417ba672dbca68e009e31e5d7eeba40d3a35cd7d
|
@@ -31,23 +31,23 @@ module ExAequo
|
|
31
31
|
|
32
32
|
def interleave(*streams)
|
33
33
|
case streams
|
34
|
-
in []
|
35
|
-
empty
|
36
34
|
in [hs, *tsts]
|
37
35
|
return interleave(*tsts) if hs.empty?
|
38
36
|
cons_stream(hs.head) { interleave(*[*tsts, hs.tail]) }
|
37
|
+
else
|
38
|
+
empty
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
def interleave_n(*streams)
|
43
43
|
case streams
|
44
|
-
in []
|
45
|
-
empty
|
46
44
|
in [[s, c], *r]
|
47
45
|
return interleave_n(*r) if s.empty?
|
48
46
|
|
49
47
|
s.take_and_drop(c) => sh, sr
|
50
48
|
prefixed(*sh) { interleave_n(*[*r, [sr, c]]) }
|
49
|
+
else
|
50
|
+
empty
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -62,10 +62,10 @@ module ExAequo
|
|
62
62
|
|
63
63
|
def prefixed(value, *values, &blk)
|
64
64
|
case values
|
65
|
-
in []
|
66
|
-
new(value, &blk)
|
67
65
|
in [next_head, *next_tails]
|
68
66
|
new(value) { prefixed(next_head, *next_tails, &blk) }
|
67
|
+
else
|
68
|
+
new(value, &blk)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -85,10 +85,6 @@ module ExAequo
|
|
85
85
|
fh.close rescue nil
|
86
86
|
empty
|
87
87
|
end
|
88
|
-
|
89
|
-
def get_heads(streams)
|
90
|
-
heads = streams.map(&:head)
|
91
|
-
end
|
92
88
|
end
|
93
89
|
end
|
94
90
|
end
|
@@ -7,14 +7,25 @@ module ExAequo
|
|
7
7
|
class Empty < ExAequo::Streams::Stream
|
8
8
|
include Singleton
|
9
9
|
|
10
|
-
def
|
10
|
+
def advance(_) = self
|
11
|
+
def drop_until(*) = self
|
12
|
+
def drop_while(*) = self
|
11
13
|
def empty = self
|
14
|
+
def empty? = true
|
12
15
|
def force = []
|
16
|
+
def func_drop_until(*) = self
|
17
|
+
def func_drop_while(*) = self
|
13
18
|
def func_flat_map(_) = self
|
19
|
+
def func_take_stream(_) = self
|
14
20
|
def head = raise StopIteration, "must not access head of the empty stream"
|
15
21
|
def head_stream(_) = self
|
16
22
|
def head_tail = raise StopIteration, "must not access head of the empty stream"
|
17
23
|
def tail = self
|
24
|
+
def take_stream(_) = self
|
25
|
+
def take_until(*) = []
|
26
|
+
def take_until_stream(*) = self
|
27
|
+
def take_while(*) = []
|
28
|
+
def take_while_stream(*) = self
|
18
29
|
|
19
30
|
private
|
20
31
|
def initialize = nil
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExAequo
|
4
|
+
module Streams
|
5
|
+
class Stream
|
6
|
+
module FuncMethods
|
7
|
+
def func_drop_until(f, advance: 0)
|
8
|
+
current = self
|
9
|
+
loop do
|
10
|
+
return empty if current.empty?
|
11
|
+
return current.drop(advance) if f.(current.head)
|
12
|
+
current = current.tail
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def func_drop_while(f, advance: 0)
|
17
|
+
if f.(head)
|
18
|
+
return empty if tail.empty?
|
19
|
+
self.class.new(tail.head) { tail.tail }
|
20
|
+
.func_drop_while(f, advance:)
|
21
|
+
else
|
22
|
+
drop(advance)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def func_flat_map(f)
|
27
|
+
expanded = f.(head)
|
28
|
+
# TODO: allow expanded to ab any enumarable by defining a general tail function
|
29
|
+
raise ArgumentError, "not a stream #{expanded.inspect}" unless self.class === expanded
|
30
|
+
|
31
|
+
# p(expanded: expanded.force.inspect)
|
32
|
+
return tail.func_flat_map(f) if expanded.empty?
|
33
|
+
self.class.new(expanded.head) {
|
34
|
+
self.class.interleave(tail.func_flat_map(f), expanded.tail)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def func_map(f)
|
39
|
+
return self.class.empty if empty?
|
40
|
+
self.class.new(f.(head)) {
|
41
|
+
tail.func_map(f)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def func_take_stream(more)
|
46
|
+
return empty if more.zero?
|
47
|
+
cons_stream(head) { tail.func_take_stream(more.pred) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def func_take_until(f, more: 0)
|
51
|
+
result = []
|
52
|
+
current = self
|
53
|
+
loop do
|
54
|
+
return result if current.empty?
|
55
|
+
return result + current.take(more) if f.(current.head)
|
56
|
+
result << current.head
|
57
|
+
current = current.tail
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def func_take_until_stream(f, more: 0)
|
62
|
+
if f.(head)
|
63
|
+
func_take_stream(more)
|
64
|
+
else
|
65
|
+
cons_stream(head) {
|
66
|
+
tail.func_take_until_stream(f, more:)
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def func_take_while_stream(f, more: 0)
|
72
|
+
if f.(head)
|
73
|
+
cons_stream(head) {
|
74
|
+
tail.func_take_while_stream(f, more:)
|
75
|
+
}
|
76
|
+
else
|
77
|
+
func_take_stream(more)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExAequo
|
4
|
+
module Streams
|
5
|
+
class Stream
|
6
|
+
module StreamMethods
|
7
|
+
|
8
|
+
def append(*streams)
|
9
|
+
case streams
|
10
|
+
in [sfirst, *srest]
|
11
|
+
return sfirst.append(*srest) if empty?
|
12
|
+
self.class.new(head) { tail.append(*streams) }
|
13
|
+
else
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def drop(n)
|
19
|
+
n.times.inject(self) { |s,| s.tail }
|
20
|
+
end
|
21
|
+
|
22
|
+
def drop_until(fn_desc=nil, advance: 0, &blk)
|
23
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
24
|
+
func_drop_until(f, advance:)
|
25
|
+
end
|
26
|
+
|
27
|
+
def drop_while(fn_desc=nil, advance: 0, &blk)
|
28
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
29
|
+
func_drop_while(f, advance:)
|
30
|
+
end
|
31
|
+
|
32
|
+
def head_stream(n)
|
33
|
+
return empty if n < 1
|
34
|
+
self.class.new(head) { tail.head_stream(n.pred) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def flat_map(fn_desc=nil, &blk)
|
38
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
39
|
+
func_flat_map(f)
|
40
|
+
end
|
41
|
+
|
42
|
+
def map(fn_desc=nil, &blk)
|
43
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
44
|
+
func_map(f)
|
45
|
+
end
|
46
|
+
|
47
|
+
def take_until_stream(fn_desc=nil, more: 0, &blk)
|
48
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
49
|
+
func_take_until_stream(f, more:)
|
50
|
+
end
|
51
|
+
|
52
|
+
def take_while_stream(fn_desc=nil, more: 0, &blk)
|
53
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
54
|
+
func_take_while_stream(f, more:)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -9,69 +9,23 @@ module ExAequo
|
|
9
9
|
class Stream
|
10
10
|
|
11
11
|
extend ClassMethods
|
12
|
+
include FuncMethods
|
13
|
+
include StreamMethods
|
12
14
|
|
13
15
|
attr_reader :head
|
14
16
|
|
15
|
-
def append(*streams)
|
16
|
-
case streams
|
17
|
-
in []
|
18
|
-
self
|
19
|
-
in [sfirst, *srest]
|
20
|
-
return sfirst.append(*srest) if empty?
|
21
|
-
self.class.new(head) { tail.append(*streams) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def drop(n)
|
26
|
-
n.times.inject(self) { |s,| s.tail }
|
27
|
-
end
|
28
|
-
|
29
17
|
def empty? = false
|
30
18
|
|
31
19
|
def empty = self.class.empty
|
32
20
|
|
33
21
|
def force = take_while { true }
|
34
22
|
|
35
|
-
def head_stream(n)
|
36
|
-
return empty if n < 1
|
37
|
-
self.class.new(head) { tail.head_stream(n.pred) }
|
38
|
-
end
|
39
|
-
|
40
23
|
def head_tail = [head, tail]
|
41
24
|
|
42
|
-
def flat_map(fn_desc=nil, &blk)
|
43
|
-
f = Fn.mk_fun_or(fn_desc, &blk)
|
44
|
-
func_flat_map(f)
|
45
|
-
end
|
46
|
-
|
47
|
-
def func_flat_map(f)
|
48
|
-
expanded = f.(head)
|
49
|
-
# TODO: allow expanded to ab any enumarable by defining a general tail function
|
50
|
-
raise ArgumentError, "not a stream #{expaneded.inspect}" unless self.class === expanded
|
51
|
-
|
52
|
-
# p(expanded: expanded.force.inspect)
|
53
|
-
return tail.func_flat_map(f) if expanded.empty?
|
54
|
-
self.class.new(expanded.head) {
|
55
|
-
self.class.interleave(tail.func_flat_map(f), expanded.tail)
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def map(fn_desc=nil, &blk)
|
60
|
-
f = Fn.mk_fun_or(fn_desc, &blk)
|
61
|
-
mapf(f)
|
62
|
-
end
|
63
|
-
|
64
25
|
def nth(n)
|
65
26
|
n.times.reduce(self) {|s,| s.tail}.head
|
66
27
|
end
|
67
28
|
|
68
|
-
def mapf(f)
|
69
|
-
return self.class.empty if empty?
|
70
|
-
self.class.new(f.(head)) {
|
71
|
-
tail.mapf(f)
|
72
|
-
}
|
73
|
-
end
|
74
|
-
|
75
29
|
def split_at(n)
|
76
30
|
[head_stream(n), drop(n)]
|
77
31
|
end
|
@@ -94,6 +48,11 @@ module ExAequo
|
|
94
48
|
[take(n), drop(n)]
|
95
49
|
end
|
96
50
|
|
51
|
+
def take_until(fn_desc=nil, more: 0, &blk)
|
52
|
+
f = Fn.mk_fun_or(fn_desc, &blk)
|
53
|
+
func_take_until(f, more:)
|
54
|
+
end
|
55
|
+
|
97
56
|
def take_while(&blk)
|
98
57
|
current = self
|
99
58
|
result = []
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ex_aequo_streams
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
@@ -52,6 +52,8 @@ files:
|
|
52
52
|
- lib/ex_aequo/streams/stream.rb
|
53
53
|
- lib/ex_aequo/streams/stream/class_methods.rb
|
54
54
|
- lib/ex_aequo/streams/stream/empty.rb
|
55
|
+
- lib/ex_aequo/streams/stream/func_methods.rb
|
56
|
+
- lib/ex_aequo/streams/stream/stream_methods.rb
|
55
57
|
- lib/ex_aequo/streams/version.rb
|
56
58
|
homepage: https://codeberg.org/lab419/rb_ex_aequo_streams
|
57
59
|
licenses:
|