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 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: