abstractivator 0.8.0 → 0.10.0
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/abstractivator/cons.rb +2 -1
- data/lib/abstractivator/enumerable_ext.rb +46 -0
- data/lib/abstractivator/module_ext.rb +9 -0
- data/lib/abstractivator/proc_ext.rb +9 -0
- data/lib/abstractivator/sort.rb +1 -1
- data/lib/abstractivator/value_map.rb +24 -0
- data/lib/abstractivator/version.rb +1 -1
- data/spec/lib/abstractivator/cons_spec.rb +8 -1
- data/spec/lib/abstractivator/enumerable_ext_spec.rb +56 -0
- data/spec/lib/abstractivator/module_ext_spec.rb +14 -0
- data/spec/lib/abstractivator/proc_ext_spec.rb +13 -0
- data/spec/lib/abstractivator/value_map_spec.rb +28 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 413e31fbc814244921a102a044f460d5dd92b0f0
|
4
|
+
data.tar.gz: 3e52b17c3bf512aa585312ffecb7bd47696f353f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90d0f8db5373e3ca4f99f8523f6669566288189380a6c236a52453a08a7b572bc76b7eb3fa3b2cb8449a1e6a3dec42c050df5aa411026ad7730e5e007f2859f6
|
7
|
+
data.tar.gz: b8f04a86e473dd03ccb10a280dfa93d64359b7e512fb5120e3c41a47e6f033e08aa929fada5e033826c92e4f6ea967fa5ac2672fa69d2b7c9b453182c2c22f57
|
data/lib/abstractivator/cons.rb
CHANGED
@@ -102,4 +102,50 @@ module Enumerable
|
|
102
102
|
end
|
103
103
|
sorted.map(&:first)
|
104
104
|
end
|
105
|
+
|
106
|
+
def select_map(&block)
|
107
|
+
self.map(&block).select { |x| x }
|
108
|
+
end
|
109
|
+
|
110
|
+
def single
|
111
|
+
if size != 1
|
112
|
+
raise ArgumentError, "expected a single element but was: #{inspect}"
|
113
|
+
end
|
114
|
+
self.first
|
115
|
+
end
|
116
|
+
|
117
|
+
def unique_by(&block)
|
118
|
+
self.group_by(&block).map { |_, vs| vs.first }
|
119
|
+
end
|
120
|
+
|
121
|
+
def duplicates(&block)
|
122
|
+
group_by(&block)
|
123
|
+
.select { |_, vs| vs.size > 1 }
|
124
|
+
.map { |k, _| k }
|
125
|
+
end
|
126
|
+
|
127
|
+
# Folds over a cyclic graph. 'self' is the root node set.
|
128
|
+
# Each node is visited once, in an unspecified order.
|
129
|
+
# Node identity is determined by #object_id
|
130
|
+
# @param init [Object] the initial accumulator
|
131
|
+
# @param get_children_proc [Proc] takes a node and returns its children (or neighbors)
|
132
|
+
# @yieldparam acc [Object] the accumulator
|
133
|
+
# @yieldparam node [Object] the current node
|
134
|
+
# @yieldreturn [Object] the accumulator, after visiting all nodes once
|
135
|
+
def cyclic_fold(init, get_children_proc, &block)
|
136
|
+
xs = self.dup
|
137
|
+
seen = Set.new
|
138
|
+
acc = init
|
139
|
+
while xs.any?
|
140
|
+
x = xs.shift
|
141
|
+
if seen.include?(x.object_id)
|
142
|
+
next
|
143
|
+
else
|
144
|
+
seen.add(x.object_id)
|
145
|
+
acc = block.call(acc, x)
|
146
|
+
xs.concat(get_children_proc.call(x))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
acc
|
150
|
+
end
|
105
151
|
end
|
@@ -97,6 +97,15 @@ class Proc
|
|
97
97
|
x.call(*args, &block)
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
def self.loosen_varargs!(args)
|
102
|
+
if args.size == 1 && args.first.is_a?(Array)
|
103
|
+
real_args = args.first
|
104
|
+
args.clear
|
105
|
+
args.concat(real_args)
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
end
|
100
109
|
end
|
101
110
|
|
102
111
|
class Method
|
data/lib/abstractivator/sort.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# like Enumerable#map, except if the receiver is not enumerable,
|
2
|
+
# i.e., a single value, then it transforms the single value.
|
3
|
+
|
4
|
+
module Enumerable
|
5
|
+
alias_method :value_map, :map
|
6
|
+
end
|
7
|
+
|
8
|
+
class NilClass
|
9
|
+
def value_map
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Object
|
15
|
+
def value_map
|
16
|
+
yield self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Struct
|
21
|
+
def value_map
|
22
|
+
yield self
|
23
|
+
end
|
24
|
+
end
|
@@ -161,4 +161,60 @@ describe Enumerable do
|
|
161
161
|
expect(result).to eql({ 'Object' => Object, 'Hash' => Hash, 'Array' => Array })
|
162
162
|
end
|
163
163
|
end
|
164
|
+
|
165
|
+
describe '#select_map' do
|
166
|
+
it 'maps, then rejects falsey values' do
|
167
|
+
result = [1,2,3].select_map do |x|
|
168
|
+
if x == 2
|
169
|
+
nil
|
170
|
+
else
|
171
|
+
-x
|
172
|
+
end
|
173
|
+
end
|
174
|
+
expect(result).to eql [-1, -3]
|
175
|
+
end
|
176
|
+
it 'invokes the block only once per item' do
|
177
|
+
count = 0
|
178
|
+
[1,2,3].select_map { count += 1 }
|
179
|
+
expect(count).to eql 3
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#single' do
|
184
|
+
it 'when there is exactly one value, returns the value' do
|
185
|
+
expect([34].single).to eql 34
|
186
|
+
end
|
187
|
+
it 'otherwise, raises an error' do
|
188
|
+
expect { [].single }.to raise_error ArgumentError
|
189
|
+
expect { [34, 5].single }.to raise_error ArgumentError
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#unique_by' do
|
194
|
+
it 'returns the unique set, where identity is established by the transformer block' do
|
195
|
+
expect(['a', 'aa', 'bb', 'b', 'c'].unique_by { |x| x[0] }).to eql ['a', 'bb', 'c']
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#duplicates' do
|
200
|
+
it 'returns the set of duplicate identities, where identity is established by the transformer block' do
|
201
|
+
expect(['a', 'aa', 'bb', 'b', 'c'].duplicates { |x| x[0] }).to eql ['a', 'b']
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe '#cyclic_fold' do
|
206
|
+
it 'Folds over a cyclic graph' do
|
207
|
+
a = {}
|
208
|
+
b = {}
|
209
|
+
g = {}
|
210
|
+
a.merge!(g: g)
|
211
|
+
b.merge!(g: g)
|
212
|
+
g.merge!(a: a, b: b)
|
213
|
+
|
214
|
+
result = [g].cyclic_fold([], :values.to_proc) do |acc, x|
|
215
|
+
acc + [x]
|
216
|
+
end
|
217
|
+
expect(result).to eql [g, a, b]
|
218
|
+
end
|
219
|
+
end
|
164
220
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'abstractivator/module_ext'
|
3
|
+
|
4
|
+
describe 'module extensions' do
|
5
|
+
describe '#type' do
|
6
|
+
it 'returns a predicate that evaluates whether a value is_a? <this type>' do
|
7
|
+
p = Enumerable.type?
|
8
|
+
expect(p.call([])).to be true
|
9
|
+
expect(p.call({})).to be true
|
10
|
+
expect(p.call(nil)).to be false
|
11
|
+
expect(p.call(1)).to be false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -172,6 +172,19 @@ context 'in the world of functional programming' do
|
|
172
172
|
expect(without_kws.proxy_call(1, a: 2, &block)).to eql [1, {a: 2}, nil, block]
|
173
173
|
end
|
174
174
|
end
|
175
|
+
|
176
|
+
describe 'Proc#loosen_varargs!' do
|
177
|
+
it 'allows varargs functions to receive explicit arrays' do
|
178
|
+
args = [1, 2]
|
179
|
+
expect(foo(*args)).to eql args
|
180
|
+
expect(foo(args)).to eql args
|
181
|
+
end
|
182
|
+
|
183
|
+
def foo(*args)
|
184
|
+
Proc.loosen_varargs!(args)
|
185
|
+
args
|
186
|
+
end
|
187
|
+
end
|
175
188
|
end
|
176
189
|
|
177
190
|
describe 'UnboundMethod#explicit_receiver' do
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'abstractivator/value_map'
|
3
|
+
|
4
|
+
describe '#value_map' do
|
5
|
+
|
6
|
+
Foo = Struct.new(:a)
|
7
|
+
|
8
|
+
it 'maps enumerables' do
|
9
|
+
expect([[:a, 1], [:b, 2]].value_map(&:reverse)).to eql [[1, :a], [2, :b]]
|
10
|
+
expect({a: 1, b: 2}.value_map(&:reverse)).to eql [[1, :a], [2, :b]]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'maps single values' do
|
14
|
+
expect(3.value_map(&method(:square))).to eql 9
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'structs are treated as single values' do
|
18
|
+
expect(Foo.new(42).value_map { |x| x.a }).to eql 42
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'maps nil' do
|
22
|
+
expect(nil.value_map(&method(:square))).to be nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def square(x)
|
26
|
+
x * x
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abstractivator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Winton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- lib/abstractivator/event.rb
|
127
127
|
- lib/abstractivator/fiber_defer.rb
|
128
128
|
- lib/abstractivator/lazy.rb
|
129
|
+
- lib/abstractivator/module_ext.rb
|
129
130
|
- lib/abstractivator/numbers.rb
|
130
131
|
- lib/abstractivator/proc_ext.rb
|
131
132
|
- lib/abstractivator/schedule.rb
|
@@ -137,6 +138,7 @@ files:
|
|
137
138
|
- lib/abstractivator/trees/recursive_delete.rb
|
138
139
|
- lib/abstractivator/trees/tree_compare.rb
|
139
140
|
- lib/abstractivator/trees/tree_map.rb
|
141
|
+
- lib/abstractivator/value_map.rb
|
140
142
|
- lib/abstractivator/version.rb
|
141
143
|
- lib/enumerable_ext.rb
|
142
144
|
- spec/lib/abstractivator/array_ext_spec.rb
|
@@ -148,6 +150,7 @@ files:
|
|
148
150
|
- spec/lib/abstractivator/event_spec.rb
|
149
151
|
- spec/lib/abstractivator/fiber_defer_spec.rb
|
150
152
|
- spec/lib/abstractivator/lazy_spec.rb
|
153
|
+
- spec/lib/abstractivator/module_ext_spec.rb
|
151
154
|
- spec/lib/abstractivator/numbers_spec.rb
|
152
155
|
- spec/lib/abstractivator/proc_ext_spec.rb
|
153
156
|
- spec/lib/abstractivator/schedule/em_util.rb
|
@@ -157,6 +160,7 @@ files:
|
|
157
160
|
- spec/lib/abstractivator/trees/recursive_delete_spec.rb
|
158
161
|
- spec/lib/abstractivator/trees/tree_compare_spec.rb
|
159
162
|
- spec/lib/abstractivator/trees/tree_map_spec.rb
|
163
|
+
- spec/lib/abstractivator/value_map_spec.rb
|
160
164
|
- spec/lib/enumerable_ext_spec.rb
|
161
165
|
- update_version.sh
|
162
166
|
homepage: ''
|
@@ -193,6 +197,7 @@ test_files:
|
|
193
197
|
- spec/lib/abstractivator/event_spec.rb
|
194
198
|
- spec/lib/abstractivator/fiber_defer_spec.rb
|
195
199
|
- spec/lib/abstractivator/lazy_spec.rb
|
200
|
+
- spec/lib/abstractivator/module_ext_spec.rb
|
196
201
|
- spec/lib/abstractivator/numbers_spec.rb
|
197
202
|
- spec/lib/abstractivator/proc_ext_spec.rb
|
198
203
|
- spec/lib/abstractivator/schedule/em_util.rb
|
@@ -202,5 +207,6 @@ test_files:
|
|
202
207
|
- spec/lib/abstractivator/trees/recursive_delete_spec.rb
|
203
208
|
- spec/lib/abstractivator/trees/tree_compare_spec.rb
|
204
209
|
- spec/lib/abstractivator/trees/tree_map_spec.rb
|
210
|
+
- spec/lib/abstractivator/value_map_spec.rb
|
205
211
|
- spec/lib/enumerable_ext_spec.rb
|
206
212
|
has_rdoc:
|