transducers 0.4.94

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ # Copyright 2014 Cognitect. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS-IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ $LOAD_PATH << 'lib'
16
+ require 'transducers'
17
+
18
+ RSpec.configure do |config|
19
+ config.filter_run :focus
20
+ config.run_all_when_everything_filtered = true
21
+ end
@@ -0,0 +1,49 @@
1
+ # Copyright 2014 Cognitect. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS-IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+
17
+ RSpec.describe Transducers::Reducer do
18
+ Reducer = Transducers::Reducer
19
+
20
+ example do
21
+ r = Reducer.new(0, :+)
22
+ expect(r.init).to eq(0)
23
+ expect(r.complete(1)).to eq(1)
24
+ expect(r.step(3,7)).to eq(10)
25
+ end
26
+
27
+ example do
28
+ r = Reducer.new(0) {|r,i| r+i}
29
+ expect(r.init).to eq(0)
30
+ expect(r.complete(1)).to eq(1)
31
+ expect(r.step(3,7)).to eq(10)
32
+ end
33
+
34
+ example do
35
+ init = Class.new do
36
+ attr_reader :val
37
+ def initialize
38
+ @val = []
39
+ end
40
+
41
+ def foo(v)
42
+ @val << v
43
+ self
44
+ end
45
+ end.new
46
+ result = Transducers.transduce(Transducers.map {|n|n+1}, :foo, init, [1,2,3])
47
+ expect(result.val).to eq([2,3,4])
48
+ end
49
+ end
@@ -0,0 +1,286 @@
1
+ # Copyright 2014 Cognitect. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS-IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+
17
+ RSpec.describe Transducers do
18
+ alias orig_expect expect
19
+
20
+ T = Transducers
21
+
22
+ def expect(expected, &actual)
23
+ orig_expect(actual.call).to eq(expected)
24
+ end
25
+
26
+ it "creates a map transducer with a block" do
27
+ expect([2,3,4]) do
28
+ T.transduce(T.map {|n| n + 1}, :<<, [], [1,2,3])
29
+ end
30
+ end
31
+
32
+ it "creates a map transducer with a Symbol" do
33
+ expect([2,3,4]) do
34
+ T.transduce(T.map(:succ), :<<, [], [1,2,3])
35
+ end
36
+ end
37
+
38
+ it "creates a map transducer with an object that implements call" do
39
+ inc = Class.new do
40
+ def call(n) n + 1 end
41
+ end.new
42
+
43
+ expect([2,3,4]) do
44
+ T.transduce(T.map(inc), :<<, [], [1,2,3])
45
+ end
46
+ end
47
+
48
+ it "creates a filter transducer with a Symbol" do
49
+ expect([2,4]) do
50
+ T.transduce(T.filter(:even?), :<<, [], [1,2,3,4,5])
51
+ end
52
+ end
53
+
54
+ it "creates a filter transducer with a Block" do
55
+ expect([2,4]) do
56
+ T.transduce(T.filter {|x| x.even?}, :<<, [], [1,2,3,4,5])
57
+ end
58
+ end
59
+
60
+ it "creates a filter transducer with an object that implements call" do
61
+ expect([2,4]) do
62
+ even = Class.new do
63
+ def call(n) n.even? end
64
+ end.new
65
+ T.transduce(T.filter(even), :<<, [], [1,2,3,4,5])
66
+ end
67
+ end
68
+
69
+ it "creates a remove transducer with a Symbol" do
70
+ expect([1,3,5]) do
71
+ T.transduce(T.remove(:even?), :<<, [], [1,2,3,4,5])
72
+ end
73
+ end
74
+
75
+ it "creates a remove transducer with a Block" do
76
+ expect([1,3,5]) do
77
+ T.transduce(T.remove {|x| x.even?}, :<<, [], [1,2,3,4,5])
78
+ end
79
+ end
80
+
81
+ it "creates a remove transducer with an object that implements call" do
82
+ expect([1,3,5]) do
83
+ even = Class.new do
84
+ def call(n) n.even? end
85
+ end.new
86
+ T.transduce(T.remove(even), :<<, [], [1,2,3,4,5])
87
+ end
88
+ end
89
+
90
+ it "creates a take transducer" do
91
+ expect([1,2,3,4,5]) do
92
+ T.transduce(T.take(5), :<<, [], 1.upto(20))
93
+ end
94
+ end
95
+
96
+ it "creates a take_while transducer" do
97
+ expect([1,2,3,4,5]) do
98
+ T.transduce(T.take_while {|n| n < 6}, :<<, [], 1.upto(20))
99
+ end
100
+
101
+ expect([1,1,1]) do
102
+ T.transduce(T.take_while {|n| n.odd?}, :<<, [], [1,1,1,2,3])
103
+ end
104
+ end
105
+
106
+ it "creates a take_nth transducer" do
107
+ expect([3,6,9,12]) do
108
+ T.transduce(T.take_nth(3), :<<, [], 1..12)
109
+ end
110
+
111
+ expect([3,6,9,12]) do
112
+ T.transduce(T.take_nth(3), :<<, [], 1..13)
113
+ end
114
+
115
+ expect([3,6,9,12]) do
116
+ T.transduce(T.take_nth(3), :<<, [], 1..14)
117
+ end
118
+ end
119
+
120
+ it "creates a drop transducer" do
121
+ expect([16,17,18,19,20]) do
122
+ T.transduce(T.drop(15), :<<, [], 1.upto(20))
123
+ end
124
+ end
125
+
126
+ it "creates a drop_while transducer" do
127
+ expect((6..20).to_a) do
128
+ T.transduce(T.drop_while {|n| n < 6}, :<<, [], 1.upto(20))
129
+ end
130
+
131
+ expect([2,3]) do
132
+ T.transduce(T.drop_while {|n| n.odd?}, :<<, [], [1,1,1,2,3])
133
+ end
134
+ end
135
+
136
+ it "creates a replace transducer" do
137
+ expect([:zeroth, :second, :fourth, :zeroth]) do
138
+ T.transduce(T.replace([:zeroth, :first, :second, :third, :fourth]), :<<, [], [0, 2, 4, 0])
139
+ end
140
+
141
+ expect([:codes, :zero, :one, :two, :zero]) do
142
+ T.transduce(T.replace({0 => :zero, 1 => :one, 2 => :two}), :<<, [], [:codes, 0, 1, 2, 0])
143
+ end
144
+ end
145
+
146
+ it "creates a keep transducer" do
147
+ expect([false, true, false, true, false]) do
148
+ T.transduce(T.keep(:even?), :<<, [], 1..5)
149
+ end
150
+
151
+ expect([1,3,5,7,9]) do
152
+ T.transduce(T.keep {|n| n if n.odd?}, :<<, [], 0..9)
153
+ end
154
+ end
155
+
156
+ it "creates a keep_indexed transducer" do
157
+ expect([:b, :d]) do
158
+ T.transduce(T.keep_indexed {|i,v| v if i.odd?}, :<<, [], [:a, :b, :c, :d, :e])
159
+ end
160
+
161
+ expect([2,4,5]) do
162
+ T.transduce(T.keep_indexed {|i,v| i if v > 0}, :<<, [], [-9, 0, 29, -7, 45, 3, -8])
163
+ end
164
+
165
+ expect([2,4,5]) do
166
+ handler = Class.new do
167
+ def call(i,v)
168
+ i if v > 0
169
+ end
170
+ end
171
+ T.transduce(T.keep_indexed(handler.new), :<<, [], [-9, 0, 29, -7, 45, 3, -8])
172
+ end
173
+ end
174
+
175
+ it "creates a dedupe transducer" do
176
+ expect([1,2,1,3,4,1,5]) do
177
+ T.transduce(T.dedupe, :<<, [], [1,2,2,1,1,1,3,4,4,1,1,5])
178
+ end
179
+ end
180
+
181
+ it "creates a cat transducer" do
182
+ expect([1,2,3,4]) do
183
+ T.transduce(T.cat, :<<, [], [[1,2],[3,4]])
184
+ end
185
+ end
186
+
187
+ it "creates a mapcat transducer with an object" do
188
+ range_builder = Class.new do
189
+ def call(n) 0...n; end
190
+ end.new
191
+
192
+ expect([0,0,1,0,1,2]) do
193
+ T.transduce(T.mapcat(range_builder), :<<, [], [1,2,3])
194
+ end
195
+ end
196
+
197
+ it "creates a mapcat transducer with a block" do
198
+ expect([0,0,1,0,1,2]) do
199
+ T.transduce(T.mapcat {|n| 0...n}, :<<, [], [1,2,3])
200
+ end
201
+ end
202
+
203
+ it "creates a partition_by transducer" do
204
+ expect([[1,2],[3],[4,5]]) do
205
+ T.transduce(T.partition_by {|n| n == 3}, :<<, [], 1..5)
206
+ end
207
+
208
+ expect([["A"],["B","B"],["A"]]) do
209
+ T.transduce(T.partition_by {|n|n}, :<<, [], "ABBA")
210
+ end
211
+ end
212
+
213
+ it "creates a partition_all transducer" do
214
+ expect([[1,2],[3,4],[5,6]]) do
215
+ T.transduce(T.partition_all(2), :<<, [], 1..6)
216
+ end
217
+
218
+ expect([[1,2],[3,4],[5,6],[7]]) do
219
+ T.transduce(T.partition_all(2), :<<, [], 1..7)
220
+ end
221
+ end
222
+
223
+ it "creates a random_sample transducer" do
224
+ # These are admittedly just sanity checks.
225
+ expect(true) do
226
+ result = T.transduce(T.random_sample(0.5), :<<, [], 1..1000)
227
+ min, max = 400, 600
228
+ raise "Expected between #{min} and #{max}, got #{result.count}" unless
229
+ result.count.between?(min,max)
230
+ true
231
+ end
232
+
233
+ expect(true) do
234
+ result = T.transduce(T.random_sample(0.75), :<<, [], 1..1000)
235
+ min, max = 650, 850
236
+ raise "Expected between #{min} and #{max}, got #{result.count}" unless
237
+ result.count.between?(min,max)
238
+ true
239
+ end
240
+ end
241
+
242
+ it "transduces a String" do
243
+ expect("THIS") do
244
+ T.transduce(T.map {|c| c.upcase},
245
+ Transducers::Reducer.new("") {|r,i| r << i},
246
+ "this")
247
+ end
248
+ end
249
+
250
+ it "transduces a range" do
251
+ expect([2,3,4]) do
252
+ T.transduce(T.map(:succ), :<<, [], 1..3)
253
+ end
254
+ end
255
+
256
+ it "raises when no initial value method is defined on the reducer" do
257
+ orig_expect do
258
+ r = Class.new { def step(_,_) end }.new
259
+ T.transduce(T.map(:succ), r, [1,2,3])
260
+ end.to raise_error(NoMethodError)
261
+ end
262
+
263
+ it "raises when it receives a symbol but no initial value" do
264
+ orig_expect do
265
+ T.transduce(T.map(:succ), :<<, [1,2,3])
266
+ end.to raise_error(ArgumentError, "No init provided")
267
+ end
268
+
269
+ describe "composition" do
270
+ example do
271
+ expect([3,7]) do
272
+ td = T.compose(T.map {|a| [a.reduce(&:+)]}, T.cat)
273
+ T.transduce(td, :<<, [], [[1,2],[3,4]])
274
+ end
275
+ end
276
+
277
+ example do
278
+ expect(12) do
279
+ td = T.compose(T.take(5),
280
+ T.map {|n| n + 1},
281
+ T.filter(:even?))
282
+ T.transduce(td, :+, 0, 1..20)
283
+ end
284
+ end
285
+ end
286
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "transducers"
7
+ spec.version = "0.4.94"
8
+ spec.authors = ["David Chelimsky"]
9
+ spec.email = ["dchelimsky@cognitect.com"]
10
+ spec.summary = %q{Transducers for Ruby}
11
+ spec.description = %q{Transducers, composable algorithmic transformations}
12
+ spec.homepage = "https://github.com/cognitect-labs/transducers-ruby"
13
+ spec.license = "Apache License 2.0"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency "yard", "~> 0.8.7.4"
24
+ spec.add_development_dependency "redcarpet", "~> 3.1.1"
25
+ spec.add_development_dependency "yard-redcarpet-ext", "~> 0.0.3"
26
+
27
+ private_key = File.expand_path(File.join(ENV['HOME'], '.gem/transit-ruby/private-key.pem'))
28
+ public_key = File.expand_path(File.join(ENV['HOME'], '.gem/transit-ruby/public-key.pem'))
29
+
30
+ if File.exist?(private_key) && ENV['SIGN'] == 'true'
31
+ spec.signing_key = private_key
32
+ spec.cert_chain = [public_key]
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: transducers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.94
5
+ platform: ruby
6
+ authors:
7
+ - David Chelimsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.7.4
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.7.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: redcarpet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.1.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard-redcarpet-ext
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.3
97
+ description: Transducers, composable algorithmic transformations
98
+ email:
99
+ - dchelimsky@cognitect.com
100
+ executables:
101
+ - rspec-across-supported-versions
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".yardopts"
108
+ - Gemfile
109
+ - LICENSE
110
+ - README.md
111
+ - Rakefile
112
+ - benchmarks/arguments_to_filter.rb
113
+ - benchmarks/arguments_to_map.rb
114
+ - benchmarks/transducers_v_ruby_iterators.rb
115
+ - bin/rspec-across-supported-versions
116
+ - build/revision
117
+ - dev/irb_tools.rb
118
+ - lib/transducers.rb
119
+ - spec/spec_helper.rb
120
+ - spec/transducers/reducer_spec.rb
121
+ - spec/transducers_spec.rb
122
+ - transducers.gemspec
123
+ homepage: https://github.com/cognitect-labs/transducers-ruby
124
+ licenses:
125
+ - Apache License 2.0
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.3.0
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Transducers for Ruby
147
+ test_files:
148
+ - spec/spec_helper.rb
149
+ - spec/transducers/reducer_spec.rb
150
+ - spec/transducers_spec.rb
151
+ has_rdoc: