abstractivator 0.8.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|