rfunc 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +124 -0
- data/Rakefile +1 -0
- data/lib/rfunc.rb +17 -0
- data/lib/rfunc/errors.rb +9 -0
- data/lib/rfunc/option.rb +334 -0
- data/lib/rfunc/seq.rb +181 -0
- data/lib/rfunc/version.rb +3 -0
- data/rfunc.gemspec +26 -0
- data/spec/rfunc/option_spec.rb +243 -0
- data/spec/rfunc/seq_spec.rb +441 -0
- data/spec/rfunc_spec.rb +29 -0
- data/spec/spec_helper.rb +19 -0
- metadata +137 -0
@@ -0,0 +1,441 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RFunc::Seq do
|
4
|
+
|
5
|
+
let(:seq) { RFunc::Seq.new([1,2,3]) }
|
6
|
+
|
7
|
+
it "throws an exception if anything but an array is provided" do
|
8
|
+
expect { RFunc::Seq.new({}) }.to raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#empty?" do
|
12
|
+
context "when there are elements in the Seq" do
|
13
|
+
it "returns true" do
|
14
|
+
seq.empty?.should == false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context "when there are no elements in the Seq" do
|
18
|
+
it "returns false" do
|
19
|
+
RFunc::Seq.new([]).empty?.should == true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#map" do
|
25
|
+
it "allows for simplistic mapping" do
|
26
|
+
seq.map {|v| v * 2}.should == RFunc::Seq.new([2, 4, 6])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#fold" do
|
31
|
+
it "allows for simplistic folding from the left" do
|
32
|
+
seq.fold({}) {|accum, value| accum["v#{value}"] = value; accum }.to_s.should eq({"v1"=>1, "v2"=>2, "v3"=>3}.to_s)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#foldl" do
|
37
|
+
it "allows for simplistic folding from the left" do
|
38
|
+
seq.foldl({}) {|accum, value| accum["v#{value}"] = value; accum }.to_s.should eq({"v1"=>1, "v2"=>2, "v3"=>3}.to_s)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#foldr" do
|
43
|
+
it "allows for simplistic folding from the right" do
|
44
|
+
seq.foldr({}) {|accum, value| accum["v#{value}"] = value; accum }.to_s.should eq({"v3"=>3, "v2"=>2, "v1"=>1}.to_s)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#slice" do
|
49
|
+
it "returns a Seq of for the specified range" do
|
50
|
+
seq.slice(0,3).should == seq
|
51
|
+
RFunc::Seq.new([1,2,3,4,5]).slice(1,3).should == RFunc::Seq.new([2,3,4])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#head" do
|
56
|
+
context "when seq has a head" do
|
57
|
+
it "returns the first element of a list" do
|
58
|
+
seq.head.should eq(1)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
context "when seq does not have a head" do
|
62
|
+
it "throws an exception" do
|
63
|
+
expect { RFunc::Seq.new([]).head }.to raise_error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#first" do
|
69
|
+
context "when seq has a head" do
|
70
|
+
it "returns the first element of a list" do
|
71
|
+
seq.first.should eq(1)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
context "when seq does not have a head" do
|
75
|
+
it "throws an exception" do
|
76
|
+
expect { RFunc::Seq.new([]).first }.to raise_error
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#head_option" do
|
82
|
+
context "when seq has a head" do
|
83
|
+
it "returns a Some of the first element of a list" do
|
84
|
+
seq.head_option.should == RFunc::Some.new(1)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
context "when seq does not have a head" do
|
88
|
+
it "returns a None" do
|
89
|
+
RFunc::Seq.new([]).head_option.should == RFunc::None.new
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#first_option" do
|
95
|
+
context "when seq has a head" do
|
96
|
+
it "returns a Some of the first element of a list" do
|
97
|
+
seq.first_option.should == RFunc::Some.new(1)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
context "when seq does not have a head" do
|
101
|
+
it "returns a None" do
|
102
|
+
RFunc::Seq.new([]).first_option.should == RFunc::None.new
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#tail" do
|
108
|
+
context "when seq has only a single item" do
|
109
|
+
it "returns an empty seq" do
|
110
|
+
RFunc::Seq.new([1]).tail.should == RFunc::Seq.new([])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when seq is empty" do
|
115
|
+
it "returns an empty seq" do
|
116
|
+
RFunc::Seq.new([1]).tail.should == RFunc::Seq.new([])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when has more than a single member" do
|
121
|
+
it "returns an empty seq" do
|
122
|
+
seq.tail.should == RFunc::Seq.new([2,3])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#tail_option" do
|
128
|
+
context "when seq has only a single item" do
|
129
|
+
it "returns a None" do
|
130
|
+
RFunc::Seq.new([1]).tail_option.should == RFunc::None.new
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when seq is empty" do
|
135
|
+
it "returns a None" do
|
136
|
+
RFunc::Seq.new([1]).tail_option.should == RFunc::None.new
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when has more than a single member" do
|
141
|
+
it "returns a Some of the tail" do
|
142
|
+
seq.tail_option.should == RFunc::Some.new(RFunc::Seq.new([2,3]))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#last" do
|
148
|
+
context "when the array has an element" do
|
149
|
+
it "returns the final element in the array" do
|
150
|
+
seq.last.should == 3
|
151
|
+
end
|
152
|
+
end
|
153
|
+
context "when the array does not have any elements" do
|
154
|
+
it "returns nil" do
|
155
|
+
RFunc::Seq.new([]).last.should be_nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#last_option" do
|
161
|
+
context "when the array has an element" do
|
162
|
+
it "returns a Some of the final element in the array" do
|
163
|
+
seq.last_option.should == RFunc::Some.new(3)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
context "when the array does not have any elements" do
|
167
|
+
it "returns a NOne" do
|
168
|
+
RFunc::Seq.new([]).last_option.should == RFunc::None.new
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#filter" do
|
174
|
+
context "when elements exist that match the provided block" do
|
175
|
+
it "returns a seq of matching elements" do
|
176
|
+
seq.filter {|el| el < 2}.should == RFunc::Seq.new([1])
|
177
|
+
end
|
178
|
+
end
|
179
|
+
context "when elements exist that do not match the provided block" do
|
180
|
+
it "returns an empty Seq" do
|
181
|
+
seq.filter {|el| el > 50}.should == RFunc::Seq.new([])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#find" do
|
187
|
+
context "when at least one element exists that matches the provided block" do
|
188
|
+
it "returns a Some of the first matching element" do
|
189
|
+
seq.find {|el| el < 2}.should == RFunc::Some.new(1)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
context "when at least no elements exist that match the provided block" do
|
193
|
+
it "returns a None" do
|
194
|
+
seq.find {|el| el > 50}.should == RFunc::None.new
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "#reverse" do
|
200
|
+
it "returns a reversed sequence" do
|
201
|
+
seq.reverse.should == RFunc::Seq.new([3,2,1])
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#[]" do
|
206
|
+
context "when specified index is in range" do
|
207
|
+
it "returns an element at the specified index" do
|
208
|
+
seq[0].should == 1
|
209
|
+
end
|
210
|
+
end
|
211
|
+
context "when specified index is not in range" do
|
212
|
+
it "returns nil" do
|
213
|
+
seq[10].should == nil
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "#members" do
|
219
|
+
it "returns the raw ruby Array on which a Seq is built" do
|
220
|
+
seq.members.should == [1,2,3]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe "#prepend" do
|
225
|
+
it "prepends a value to a Seq" do
|
226
|
+
seq.prepend(0).should == RFunc::Seq.new([0,1,2,3])
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "#append" do
|
231
|
+
it "appends a value to a Seq" do
|
232
|
+
seq.append(4).should == RFunc::Seq.new([1,2,3,4])
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#collect" do
|
237
|
+
it "returns a Seq of members that have been operated on if the block returns a value" do
|
238
|
+
seq.collect{|v|
|
239
|
+
case v == 2
|
240
|
+
when true; v * 4
|
241
|
+
end
|
242
|
+
}.should == RFunc::Seq.new([8])
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "#join" do
|
247
|
+
it "joins the elements of the Seq together (into a String) using the supplied character" do
|
248
|
+
seq.join(",").should == "1,2,3"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "#collect_first" do
|
253
|
+
context "when an element exists for which the supplied block returns true" do
|
254
|
+
it "returns a Some of operation" do
|
255
|
+
seq.collect_first{|el|
|
256
|
+
case el == 2
|
257
|
+
when true; el * 100
|
258
|
+
end
|
259
|
+
}.should == RFunc::Some.new(200)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context "when an element does not exist for which the supplied block returns true" do
|
264
|
+
it "returns a None" do
|
265
|
+
seq.collect_first{|el|
|
266
|
+
case el == 222
|
267
|
+
when true; el * 100
|
268
|
+
end
|
269
|
+
}.should == RFunc::None.new
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
describe "#concat" do
|
275
|
+
context "when passing in a Ruby Array" do
|
276
|
+
it "returns a Seq with the specified array members concatenated" do
|
277
|
+
seq.concat([4,5,6]).should == RFunc::Seq.new([1,2,3,4,5,6])
|
278
|
+
end
|
279
|
+
end
|
280
|
+
context "when passing in a Seq" do
|
281
|
+
it "returns a Seq with the specified Seq's members concatenated" do
|
282
|
+
seq.concat(RFunc::Seq.new([9,8,7])).should == RFunc::Seq.new([1,2,3,9,8,7])
|
283
|
+
end
|
284
|
+
end
|
285
|
+
context "when an empty array is passed in" do
|
286
|
+
it "returns an unchanged Seq" do
|
287
|
+
seq.concat([]).should == seq
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "#flat_map" do
|
293
|
+
context "when the array is empty" do
|
294
|
+
it "returns an empty Seq" do
|
295
|
+
RFunc::Seq.new().flat_map {|el| [el, el + 1, el + 2] }.should == RFunc::Seq.new
|
296
|
+
end
|
297
|
+
end
|
298
|
+
context "when the array is not empty" do
|
299
|
+
it "returns a flattened Seq" do
|
300
|
+
seq.flat_map {|el| [el, el + 1, el + 2] }.should == RFunc::Seq.new([1,2,3,2,3,4,3,4,5])
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe "#flatten" do
|
306
|
+
it "returns a flattened Seq" do
|
307
|
+
RFunc::Seq.new([[1,2], [3,4]]).flatten.should == RFunc::Seq.new([1,2,3,4])
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "#for_all?" do
|
312
|
+
context "when none of the elements fail to meet the expectation" do
|
313
|
+
it "returns true" do
|
314
|
+
seq.for_all? {|el| el < 100}.should == true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
context "when at least one element fails to meet the expectation" do
|
318
|
+
it "returns false" do
|
319
|
+
seq.for_all? {|el| el < 1}.should == false
|
320
|
+
end
|
321
|
+
end
|
322
|
+
context "when the Seq is empty" do
|
323
|
+
it "returns true" do
|
324
|
+
RFunc::Seq.new([]).for_all? {|el| el < 1}.should == true
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe "#slice" do
|
330
|
+
context "when the Seq is empty" do
|
331
|
+
it "returns an empty Seq" do
|
332
|
+
RFunc::Seq.new([]).slice(0,3).should == RFunc::Seq.new
|
333
|
+
end
|
334
|
+
end
|
335
|
+
context "when the Seq is not empty" do
|
336
|
+
context "when the requested range is not available" do
|
337
|
+
it "returns an empty Seq" do
|
338
|
+
seq.slice(10, 100).should == RFunc::Seq.new
|
339
|
+
end
|
340
|
+
end
|
341
|
+
context "when the requested range is available" do
|
342
|
+
it "returns an empty Seq" do
|
343
|
+
seq.slice(1, 2).should == RFunc::Seq.new([2,3])
|
344
|
+
end
|
345
|
+
end
|
346
|
+
context "when the requested range includes a negative" do
|
347
|
+
it "returns a Seq with elements from the slice" do
|
348
|
+
seq.slice(1, -2).should == RFunc::Seq.new([])
|
349
|
+
seq.slice(-2,2).should == RFunc::Seq.new([2,3])
|
350
|
+
seq.slice(-1, -3).should == RFunc::Seq.new
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
describe "#intersect" do
|
357
|
+
it "returns a Seq of the members that are common to both sets" do
|
358
|
+
seq.intersect(RFunc::Seq.new([2,2,3])).should == RFunc::Seq.new([2,3])
|
359
|
+
end
|
360
|
+
it "can take an array as its argument" do
|
361
|
+
seq.intersect([2,2,3]).should == RFunc::Seq.new([2,3])
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
describe "<=>" do
|
366
|
+
context "when Seq members are equal" do
|
367
|
+
it "returns 0" do
|
368
|
+
(seq <=> (RFunc::Seq.new([1,2,3]))).should == 0
|
369
|
+
end
|
370
|
+
end
|
371
|
+
context "when Seq members are not equal" do
|
372
|
+
it "returns -1 if the Seq instance is less than the provided array" do
|
373
|
+
(seq <=> (RFunc::Seq.new([1,2,3,4]))).should == -1
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
describe "#to_s" do
|
379
|
+
it "returns a stringified version of the array" do
|
380
|
+
seq.to_s.should == "[1, 2, 3]"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
describe "#inspect" do
|
385
|
+
it "returns a stringified version of the array" do
|
386
|
+
seq.to_s.should == "[1, 2, 3]"
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe '#to_h' do
|
391
|
+
it "passes the call to the native ruby method" do
|
392
|
+
RFunc::Seq.new([[:foo, :bar]]).to_h.should eq({foo: :bar})
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
describe '#to_a' do
|
397
|
+
it "returns the array" do
|
398
|
+
seq.to_a.should eq([1,2,3])
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
describe '#to_ary' do
|
403
|
+
it "returns the array" do
|
404
|
+
seq.to_ary.should eq([1,2,3])
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
describe '#take_while' do
|
409
|
+
it "returns a Seq whose contents have passed the provided block's truth test until the first false" do
|
410
|
+
RFunc::Seq.new([1,2,3,4,5,6,7]).take_while{|el| el < 4}.should eq(seq)
|
411
|
+
RFunc::Seq.new([1,2,3,4,5,6,7]).take_while{|el| el > 4}.should eq(RFunc::Seq.new)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe '#take' do
|
416
|
+
it "returns a Seq whose contents represent the original array's up to n length" do
|
417
|
+
RFunc::Seq.new([1,2,3,4,5,6,7]).take(3).should eq(seq)
|
418
|
+
RFunc::Seq.new([]).take(100).should eq(RFunc::Seq.new)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
describe '#sort_by' do
|
423
|
+
it "returns an Seq sorted based on the provided block" do
|
424
|
+
seq.sort_by{|el| el * -1}.should == RFunc::Seq.new([3,2,1])
|
425
|
+
RFunc::Seq.new(["foo", "biz", "bar", "apple"]).sort_by {|el| el }.should == RFunc::Seq.new(["apple", "bar", "biz", "foo"])
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
describe '#sort' do
|
430
|
+
context "when a block is given" do
|
431
|
+
it "returns an Seq sorted based on the provided block" do
|
432
|
+
seq.sort{|a, b| a > b ? -1 : a == b ? 0 : 1 }.should == RFunc::Seq.new([3,2,1])
|
433
|
+
end
|
434
|
+
end
|
435
|
+
context "when a block is not given" do
|
436
|
+
it "returns a Seq sorted by the default Ruby method" do
|
437
|
+
seq.reverse.sort.should == RFunc::Seq.new([1,2,3])
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
data/spec/rfunc_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RFunc do
|
4
|
+
include RFunc
|
5
|
+
describe "#Seq" do
|
6
|
+
it "returns an RFunc::Seq" do
|
7
|
+
Seq([1,2,3]).class.should == RFunc::Seq
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#Option" do
|
12
|
+
it "returns the appropriate RFunc::Option" do
|
13
|
+
Option(nil).class.should == RFunc::None
|
14
|
+
Option("foo").class.should == RFunc::Some
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#Some" do
|
19
|
+
it "returns the an RFunc::Some" do
|
20
|
+
Some(1).class.should == RFunc::Some
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#None" do
|
25
|
+
it "returns the an RFunc::None" do
|
26
|
+
None().class.should == RFunc::None
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|