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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2cea52cc38ca98adfa7d74c52cf4ba4f7092199
4
- data.tar.gz: 312ae9d15598a24323ad84d5bf5ce504a15bc4a0
3
+ metadata.gz: 413e31fbc814244921a102a044f460d5dd92b0f0
4
+ data.tar.gz: 3e52b17c3bf512aa585312ffecb7bd47696f353f
5
5
  SHA512:
6
- metadata.gz: 8915f8bc9b77a6e3fba1bed0578b28d4a08e7bf99d7e96eff0698268c6e43dba869ea40a334646e38c670e094fcf42fe403f105f12016287c79c852a256ba984
7
- data.tar.gz: 9b040c5a59386fc9ff8b10e484eb9fb0ad71c354378a61afe5a815973f69fe041469d28aebbda95517fd93444b93e98b86760bfae35105b0d9d8ef9cb10b8ddc
6
+ metadata.gz: 90d0f8db5373e3ca4f99f8523f6669566288189380a6c236a52453a08a7b572bc76b7eb3fa3b2cb8449a1e6a3dec42c050df5aa411026ad7730e5e007f2859f6
7
+ data.tar.gz: b8f04a86e473dd03ccb10a280dfa93d64359b7e512fb5120e3c41a47e6f033e08aa929fada5e033826c92e4f6ea967fa5ac2672fa69d2b7c9b453182c2c22f57
@@ -1,6 +1,7 @@
1
1
  module Abstractivator
2
2
  module Cons
3
3
  Nil = Object.new
4
+ Nil.define_singleton_method(:empty?) { true }
4
5
 
5
6
  def empty_list
6
7
  Nil
@@ -55,4 +56,4 @@ module Abstractivator
55
56
 
56
57
  extend self
57
58
  end
58
- end
59
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ class Module
2
+ # useful in the following scenario:
3
+ # things.select(&:Array.type?)
4
+ # instead of:
5
+ # things.select { |x| x.is_a?(Array) }
6
+ def type?
7
+ proc { |x| x.is_a?(self) }
8
+ end
9
+ 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
@@ -3,7 +3,7 @@ module Abstractivator
3
3
  def deep_sort_hash(obj)
4
4
  case obj
5
5
  when Hash
6
- obj.sort.to_h.each_with_object({}) do |(k, v), a|
6
+ obj.sort.each_with_object({}) do |(k, v), a|
7
7
  a[k] = deep_sort_hash(v)
8
8
  end
9
9
  when Array
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Abstractivator
2
- VERSION = '0.8.0'
2
+ VERSION = '0.10.0'
3
3
  end
@@ -45,4 +45,11 @@ describe Abstractivator::Cons do
45
45
  end
46
46
  end
47
47
 
48
- end
48
+ describe '#empty?' do
49
+ it 'determines whether or not the list is empty' do
50
+ expect(enum_to_list([1]).empty?).to be false
51
+ expect(empty_list.empty?).to be true
52
+ end
53
+ end
54
+
55
+ 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.8.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: 2016-11-08 00:00:00.000000000 Z
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: