functional-ruby 0.7.4 → 0.7.5

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.
@@ -0,0 +1,752 @@
1
+ require 'spec_helper'
2
+
3
+ module Functional
4
+
5
+ describe Collection do
6
+
7
+ context '#random_sample' do
8
+
9
+ specify { Collection.random_sample(100).length == 100 }
10
+ specify { Collection.random_sample(100, :min => 10).min >= 10 }
11
+ specify { Collection.random_sample(100, :max => 10).max >= 10 }
12
+
13
+ end
14
+
15
+ context 'bisection' do
16
+
17
+ context '#bisect_left' do
18
+
19
+ it 'returns nil when the sample is nil' do
20
+ Collection.bisect_left(nil, 10).should be_nil
21
+ end
22
+
23
+ it 'returns zero when the sample is empty' do
24
+ Collection.bisect_left([], 10).should eq 0
25
+ end
26
+
27
+ it 'returns the index when the item is not in the sample' do
28
+ sample = [10, 20, 30]
29
+ Collection.bisect_left(sample, 15).should eq 1
30
+ Collection.bisect_left(sample, 25).should eq 2
31
+ end
32
+
33
+ it 'returns the index when the item is in the sample' do
34
+ sample = [10, 20, 30]
35
+ Collection.bisect_left(sample, 10).should eq 0
36
+ Collection.bisect_left(sample, 20).should eq 1
37
+ Collection.bisect_left(sample, 30).should eq 2
38
+ end
39
+
40
+ it 'returns the index when the item is not in the sample with a block' do
41
+ sample = [
42
+ {:count => 10},
43
+ {:count => 20},
44
+ {:count => 30}
45
+ ]
46
+ Collection.bisect_left(sample, 15){|x| x[:count]}.should eq 1
47
+ Collection.bisect_left(sample, 25){|x| x[:count]}.should eq 2
48
+ end
49
+
50
+ it 'returns the index when the item is in the sample with a block' do
51
+ sample = [
52
+ {:count => 10},
53
+ {:count => 20},
54
+ {:count => 30}
55
+ ]
56
+ Collection.bisect_left(sample, 10){|x| x[:count]}.should eq 0
57
+ Collection.bisect_left(sample, 20){|x| x[:count]}.should eq 1
58
+ Collection.bisect_left(sample, 30){|x| x[:count]}.should eq 2
59
+ end
60
+ end
61
+
62
+ context '#bisect_right' do
63
+
64
+ it 'returns nil when the sample is nil' do
65
+ Collection.bisect_right(nil, 10).should be_nil
66
+ end
67
+
68
+ it 'returns zero when the sample is empty' do
69
+ Collection.bisect_right([], 10).should eq 0
70
+ end
71
+
72
+ it 'returns the index when the item is not in the sample' do
73
+ sample = [10, 20, 30]
74
+ Collection.bisect_right(sample, 15).should eq 1
75
+ Collection.bisect_right(sample, 25).should eq 2
76
+ end
77
+
78
+ it 'returns the index when the item is in the sample' do
79
+ sample = [10, 20, 30]
80
+ Collection.bisect_right(sample, 10).should eq 1
81
+ Collection.bisect_right(sample, 20).should eq 2
82
+ Collection.bisect_right(sample, 30).should eq 3
83
+ end
84
+
85
+ it 'returns the index when the item is not in the sample with a block' do
86
+ sample = [
87
+ {:count => 10},
88
+ {:count => 20},
89
+ {:count => 30}
90
+ ]
91
+ Collection.bisect_right(sample, 15){|x| x[:count]}.should eq 1
92
+ Collection.bisect_right(sample, 25){|x| x[:count]}.should eq 2
93
+ end
94
+
95
+ it 'returns the index when the item is in the sample with a block' do
96
+ sample = [
97
+ {:count => 10},
98
+ {:count => 20},
99
+ {:count => 30}
100
+ ]
101
+ Collection.bisect_right(sample, 10){|x| x[:count]}.should eq 1
102
+ Collection.bisect_right(sample, 20){|x| x[:count]}.should eq 2
103
+ Collection.bisect_right(sample, 30){|x| x[:count]}.should eq 3
104
+ end
105
+ end
106
+
107
+ context '#insort_left!' do
108
+
109
+ it 'returns the item in a one-element array when the sample is nil' do
110
+ Collection.insort_left!(nil, 10).should eq [10]
111
+ end
112
+
113
+ it 'returns the item in a one-element array when the sample is empty' do
114
+ sample = []
115
+ insort = Collection.insort_left!(sample, 10)
116
+ insort.should eq [10]
117
+ sample.object_id.should eq insort.object_id
118
+ end
119
+
120
+ it 'inserts an element that is not in the sample' do
121
+ sample = [10, 20, 30]
122
+ insort = Collection.insort_left!(sample, 15)
123
+ insort.should eq [10, 15, 20, 30]
124
+ sample.object_id.should eq insort.object_id
125
+ end
126
+
127
+ it 'inserts an element that is in the sample' do
128
+ item = 'b'
129
+ sample = ['a', 'b', 'c']
130
+ insort = Collection.insort_left!(sample, item)
131
+ insort.should eq ['a', 'b', 'b', 'c']
132
+ sample.object_id.should eq insort.object_id
133
+ sample[1].object_id.should eq item.object_id
134
+ end
135
+
136
+ it 'inserts an element that is not in the sample using a block' do
137
+ sample = [
138
+ {:count => 10},
139
+ {:count => 20},
140
+ {:count => 30}
141
+ ]
142
+ insort = Collection.insort_left!(sample, {:count => 15}){|x| x[:count]}
143
+ insort.should eq [
144
+ {:count => 10},
145
+ {:count => 15},
146
+ {:count => 20},
147
+ {:count => 30}
148
+ ]
149
+ sample.object_id.should eq insort.object_id
150
+ end
151
+
152
+ it 'inserts an element that is in the sample using a block' do
153
+ item = {:letter => 'b'}
154
+ sample = [
155
+ {:letter => 'a'},
156
+ {:letter => 'b'},
157
+ {:letter => 'c'}
158
+ ]
159
+ insort = Collection.insort_left!(sample, item){|x| x[:letter]}
160
+ insort.should eq [
161
+ {:letter => 'a'},
162
+ {:letter => 'b'},
163
+ {:letter => 'b'},
164
+ {:letter => 'c'}
165
+ ]
166
+ sample.object_id.should eq insort.object_id
167
+ sample[1].object_id.should eq item.object_id
168
+ end
169
+ end
170
+
171
+ context '#insort_left' do
172
+
173
+ it 'returns the item in a one-element array when the sample is nil' do
174
+ Collection.insort_left(nil, 10).should eq [10]
175
+ end
176
+
177
+ it 'returns the item in a one-element array when the sample is empty' do
178
+ sample = []
179
+ insort = Collection.insort_left(sample, 10)
180
+ insort.should eq [10]
181
+ sample.object_id.should_not eq insort.object_id
182
+ end
183
+
184
+ it 'inserts an element that is not in the sample' do
185
+ sample = [10, 20, 30]
186
+ insort = Collection.insort_left(sample, 15)
187
+ insort.should eq [10, 15, 20, 30]
188
+ sample.object_id.should_not eq insort.object_id
189
+ end
190
+
191
+ it 'inserts an element that is in the sample' do
192
+ item = 'b'
193
+ sample = ['a', 'b', 'c']
194
+ insort = Collection.insort_left(sample, item)
195
+ insort.should eq ['a', 'b', 'b', 'c']
196
+ sample.object_id.should_not eq insort.object_id
197
+ insort[1].object_id.should eq item.object_id
198
+ end
199
+
200
+ it 'inserts an element when the sample class does not support the #dup method' do
201
+ sample = [10, 20, 30]
202
+ sample.should_receive(:respond_to?).with(:dup).and_return(false)
203
+ insort = Collection.insort_left(sample, 15)
204
+ insort.should eq [10, 15, 20, 30]
205
+ sample.object_id.should_not eq insort.object_id
206
+ end
207
+
208
+ it 'inserts an element that is not in the sample using a block' do
209
+ sample = [
210
+ {:count => 10},
211
+ {:count => 20},
212
+ {:count => 30}
213
+ ]
214
+ insort = Collection.insort_left(sample, {:count => 15}){|x| x[:count]}
215
+ insort.should eq [
216
+ {:count => 10},
217
+ {:count => 15},
218
+ {:count => 20},
219
+ {:count => 30}
220
+ ]
221
+ sample.object_id.should_not eq insort.object_id
222
+ end
223
+
224
+ it 'inserts an element that is in the sample using a block' do
225
+ item = {:letter => 'b'}
226
+ sample = [
227
+ {:letter => 'a'},
228
+ {:letter => 'b'},
229
+ {:letter => 'c'}
230
+ ]
231
+ insort = Collection.insort_left(sample, item){|x| x[:letter]}
232
+ insort.should eq [
233
+ {:letter => 'a'},
234
+ {:letter => 'b'},
235
+ {:letter => 'b'},
236
+ {:letter => 'c'}
237
+ ]
238
+ sample.object_id.should_not eq insort.object_id
239
+ insort[1].object_id.should eq item.object_id
240
+ end
241
+ end
242
+
243
+ context '#insort_right!' do
244
+
245
+ it 'returns the item in a one-element array when the sample is nil' do
246
+ Collection.insort_right!(nil, 10).should eq [10]
247
+ end
248
+
249
+ it 'returns the item in a one-element array when the sample is empty' do
250
+ sample = []
251
+ insort = Collection.insort_right!(sample, 10)
252
+ insort.should eq [10]
253
+ sample.object_id.should eq insort.object_id
254
+ end
255
+
256
+ it 'inserts an element that is not in the sample' do
257
+ sample = [10, 20, 30]
258
+ insort = Collection.insort_right!(sample, 15)
259
+ insort.should eq [10, 15, 20, 30]
260
+ sample.object_id.should eq insort.object_id
261
+ end
262
+
263
+ it 'inserts an element that is in the sample' do
264
+ item = 'b'
265
+ sample = ['a', 'b', 'c']
266
+ insort = Collection.insort_right!(sample, item)
267
+ insort.should eq ['a', 'b', 'b', 'c']
268
+ sample.object_id.should eq insort.object_id
269
+ insort[2].object_id.should eq item.object_id
270
+ end
271
+
272
+ it 'inserts an element that is not in the sample using a block' do
273
+ sample = [
274
+ {:count => 10},
275
+ {:count => 20},
276
+ {:count => 30}
277
+ ]
278
+ insort = Collection.insort_right!(sample, {:count => 15}){|x| x[:count]}
279
+ insort.should eq [
280
+ {:count => 10},
281
+ {:count => 15},
282
+ {:count => 20},
283
+ {:count => 30}
284
+ ]
285
+ sample.object_id.should eq insort.object_id
286
+ end
287
+
288
+ it 'inserts an element that is in the sample using a block' do
289
+ item = {:letter => 'b'}
290
+ sample = [
291
+ {:letter => 'a'},
292
+ {:letter => 'b'},
293
+ {:letter => 'c'}
294
+ ]
295
+ insort = Collection.insort_right!(sample, item){|x| x[:letter]}
296
+ insort.should eq [
297
+ {:letter => 'a'},
298
+ {:letter => 'b'},
299
+ {:letter => 'b'},
300
+ {:letter => 'c'}
301
+ ]
302
+ sample.object_id.should eq insort.object_id
303
+ insort[2].object_id.should eq item.object_id
304
+ end
305
+ end
306
+
307
+ context '#insort_right' do
308
+
309
+ it 'returns the item in a one-element array when the sample is nil' do
310
+ Collection.insort_right(nil, 10).should eq [10]
311
+ end
312
+
313
+ it 'returns the item in a one-element array when the sample is empty' do
314
+ sample = []
315
+ insort = Collection.insort_right(sample, 10)
316
+ insort.should eq [10]
317
+ sample.object_id.should_not eq insort.object_id
318
+ end
319
+
320
+ it 'inserts an element that is not in the sample' do
321
+ sample = [10, 20, 30]
322
+ insort = Collection.insort_right(sample, 15)
323
+ insort.should eq [10, 15, 20, 30]
324
+ sample.object_id.should_not eq insort.object_id
325
+ end
326
+
327
+ it 'inserts an element that is in the sample' do
328
+ item = 'b'
329
+ sample = ['a', 'b', 'c']
330
+ insort = Collection.insort_right(sample, item)
331
+ insort.should eq ['a', 'b', 'b', 'c']
332
+ sample.object_id.should_not eq insort.object_id
333
+ insort[2].object_id.should eq item.object_id
334
+ end
335
+
336
+ it 'inserts an element when the sample class does not support the #dup method' do
337
+ sample = [10, 20, 30]
338
+ sample.should_receive(:respond_to?).with(:dup).and_return(false)
339
+ insort = Collection.insort_right(sample, 15)
340
+ insort.should eq [10, 15, 20, 30]
341
+ sample.object_id.should_not eq insort.object_id
342
+ end
343
+
344
+ it 'inserts an element that is not in the sample using a block' do
345
+ sample = [
346
+ {:count => 10},
347
+ {:count => 20},
348
+ {:count => 30}
349
+ ]
350
+ insort = Collection.insort_right(sample, {:count => 15}){|x| x[:count]}
351
+ insort.should eq [
352
+ {:count => 10},
353
+ {:count => 15},
354
+ {:count => 20},
355
+ {:count => 30}
356
+ ]
357
+ sample.object_id.should_not eq insort.object_id
358
+ end
359
+
360
+ it 'inserts an element that is in the sample using a block' do
361
+ item = {:letter => 'b'}
362
+ sample = [
363
+ {:letter => 'a'},
364
+ {:letter => 'b'},
365
+ {:letter => 'c'}
366
+ ]
367
+ insort = Collection.insort_right(sample, item){|x| x[:letter]}
368
+ insort.should eq [
369
+ {:letter => 'a'},
370
+ {:letter => 'b'},
371
+ {:letter => 'b'},
372
+ {:letter => 'c'}
373
+ ]
374
+ sample.object_id.should_not eq insort.object_id
375
+ insort[2].object_id.should eq item.object_id
376
+ end
377
+ end
378
+ end
379
+
380
+ context '#collect' do
381
+
382
+ it 'returns an empty array when given a nil sample' do
383
+ Collection.collect(nil).should eq []
384
+ end
385
+
386
+ it 'returns an empty array when given an empty sample' do
387
+ Collection.collect([].freeze).should eq []
388
+ end
389
+
390
+ it 'returns an array when given a valid sample' do
391
+ sample = [1, 2, 3, 4, 5].freeze
392
+ collected = Collection.collect(sample)
393
+ collected.size.should eq sample.size
394
+ collected.each {|item| sample.should include(item)}
395
+ sample.each {|item| collected.should include(item)}
396
+ end
397
+
398
+ it 'returns an array when given a sample with a block' do
399
+ sample = [
400
+ {:count => 1},
401
+ {:count => 2},
402
+ {:count => 3}
403
+ ].freeze
404
+
405
+ collected = Collection.collect(sample){|item| item[:count]}
406
+ collected.size.should eq sample.size
407
+ sample.each {|item| collected.should include(item.values.first)}
408
+ end
409
+ end
410
+
411
+ context '#index_and_catalog' do
412
+
413
+ let(:sample) { [13, 18, 13, 14, 13, 16, 14, 21, 13].freeze }
414
+ let(:expected) { [ [0, 13], [1, 18], [2, 13], [3, 14], [4, 13], [5, 16], [6, 14], [7, 21], [8, 13] ].freeze }
415
+
416
+ it 'returns an empty catalog when given a nil sample' do
417
+ Collection.index_and_catalog(nil).should eq []
418
+ end
419
+
420
+ it 'returns an empty catalog when given an empty sample' do
421
+ Collection.index_and_catalog([].freeze).should eq []
422
+ end
423
+
424
+ it 'returns an catalog when given a valid sample' do
425
+ cataloged = Collection.index_and_catalog(sample)
426
+ cataloged.should eq expected
427
+ end
428
+
429
+ it 'returns an catalog when given a sample with a block' do
430
+ sample = [
431
+ {:count => 13}, {:count => 18}, {:count => 13},
432
+ {:count => 14}, {:count => 13}, {:count => 16},
433
+ {:count => 14}, {:count => 21}, {:count => 13}
434
+ ].freeze
435
+
436
+ cataloged = Collection.index_and_catalog(sample){|item| item[:count]}
437
+ cataloged.should eq expected
438
+ end
439
+ end
440
+
441
+ context '#catalog_hash' do
442
+
443
+ it 'returns an empty catalog when the hash is nil' do
444
+ Collection.catalog_hash(nil).should eq []
445
+ end
446
+
447
+ it 'returns an empty catalog when the hash is empty' do
448
+ Collection.catalog_hash({}.freeze).should eq []
449
+ end
450
+
451
+ it 'returns a catalog when given a populated hash' do
452
+ sample = {
453
+ 7 => 8,
454
+ 12 => 8,
455
+ 17 => 14,
456
+ 22 => 4,
457
+ 27 => 6,
458
+ 32 => 12,
459
+ 37 => 8,
460
+ 42 => 3,
461
+ 47 => 2
462
+ }.freeze
463
+
464
+ catalog = Collection.catalog_hash(sample)
465
+ catalog.size.should eq sample.size
466
+
467
+ catalog[0].should eq [7, 8]
468
+ catalog[1].should eq [12, 8]
469
+ catalog[2].should eq [17, 14]
470
+ catalog[3].should eq [22, 4]
471
+ catalog[4].should eq [27, 6]
472
+ catalog[5].should eq [32, 12]
473
+ catalog[6].should eq [37, 8]
474
+ catalog[7].should eq [42, 3]
475
+ catalog[8].should eq [47, 2]
476
+ end
477
+
478
+ it 'applies the supplied block to every value in the hash' do
479
+ sample = {
480
+ 7 => {:count => 8},
481
+ 12 => {:count => 8},
482
+ 17 => {:count => 14},
483
+ 22 => {:count => 4},
484
+ 27 => {:count => 6},
485
+ 32 => {:count => 12},
486
+ 37 => {:count => 8},
487
+ 42 => {:count => 3},
488
+ 47 => {:count => 2}
489
+ }.freeze
490
+
491
+ catalog = Collection.catalog_hash(sample){|item| item[:count]}
492
+ catalog.size.should eq sample.size
493
+
494
+ catalog[0].should eq [7, 8]
495
+ catalog[1].should eq [12, 8]
496
+ catalog[2].should eq [17, 14]
497
+ catalog[3].should eq [22, 4]
498
+ catalog[4].should eq [27, 6]
499
+ catalog[5].should eq [32, 12]
500
+ catalog[6].should eq [37, 8]
501
+ catalog[7].should eq [42, 3]
502
+ catalog[8].should eq [47, 2]
503
+ end
504
+ end
505
+
506
+ context '#hash_catalog' do
507
+
508
+ it 'returns an empty hash when the catalog is nil' do
509
+ Collection.hash_catalog(nil).should == {}
510
+ end
511
+
512
+ it 'returns an empty hash when the catalog is empty' do
513
+ Collection.hash_catalog({}.freeze).should == {}
514
+ end
515
+
516
+ it 'returns a hash when given a catalog hash' do
517
+ sample = [
518
+ [7, 8],
519
+ [12, 8],
520
+ [17, 14],
521
+ [22, 4],
522
+ [27, 6],
523
+ [32, 12],
524
+ [37, 8],
525
+ [42, 3],
526
+ [47, 2]
527
+ ].freeze
528
+
529
+ hash = Collection.hash_catalog(sample)
530
+ hash.size.should eq sample.size
531
+
532
+ hash[7].should eq 8
533
+ hash[12].should eq 8
534
+ hash[17].should eq 14
535
+ hash[22].should eq 4
536
+ hash[27].should eq 6
537
+ hash[32].should eq 12
538
+ hash[37].should eq 8
539
+ hash[42].should eq 3
540
+ hash[47].should eq 2
541
+ end
542
+
543
+ it 'keeps the last value when duplicate keys exist' do
544
+ sample = [
545
+ [7, 0],
546
+ [12, 1],
547
+ [12, 2],
548
+ [12, 3],
549
+ [12, 4],
550
+ [12, 5],
551
+ [12, 6],
552
+ [47, 7]
553
+ ].freeze
554
+
555
+ hash = Collection.hash_catalog(sample)
556
+ hash.size.should eq 3
557
+
558
+ hash[7].should eq 0
559
+ hash[12].should eq 6
560
+ hash[47].should eq 7
561
+ end
562
+
563
+ it 'applies the supplied block to every value in the hash' do
564
+ sample = [
565
+ [7, {:count => 8}],
566
+ [12, {:count => 8}],
567
+ [17, {:count => 14}],
568
+ [22, {:count => 4}],
569
+ [27, {:count => 6}],
570
+ [32, {:count => 12}],
571
+ [37, {:count => 8}],
572
+ [42, {:count => 3}],
573
+ [47, {:count => 2}]
574
+ ].freeze
575
+
576
+ hash = Collection.hash_catalog(sample){|item| item[:count]}
577
+ hash.size.should eq sample.size
578
+
579
+ hash[7].should eq 8
580
+ hash[12].should eq 8
581
+ hash[17].should eq 14
582
+ hash[22].should eq 4
583
+ hash[27].should eq 6
584
+ hash[32].should eq 12
585
+ hash[37].should eq 8
586
+ hash[42].should eq 3
587
+ hash[47].should eq 2
588
+ end
589
+ end
590
+
591
+ context 'predicates' do
592
+
593
+ context '#ascending?' do
594
+
595
+ it 'returns false for a nil sample' do
596
+ Collection.ascending?(nil).should be_false
597
+ end
598
+
599
+ it 'returns true for an empty sample' do
600
+ Collection.ascending?([].freeze).should be_true
601
+ end
602
+
603
+ it 'returns true for a one-element sample' do
604
+ Collection.ascending?([100].freeze).should be_true
605
+ end
606
+
607
+ it 'returns true for an ascending collection' do
608
+ Collection.ascending?([1, 2, 3, 4].freeze).should be_true
609
+ end
610
+
611
+ it 'returns false for a non-ascending collection' do
612
+ Collection.ascending?([1, 3, 2, 4].freeze).should be_false
613
+ end
614
+
615
+ it 'returns the correct value when given a block' do
616
+ sample = [
617
+ {:count => 11},
618
+ {:count => 12},
619
+ {:count => 13},
620
+ {:count => 14}
621
+ ].freeze
622
+
623
+ Collection.ascending?(sample){|item| item[:count]}.should be_true
624
+ end
625
+ end
626
+
627
+ context '#descending?' do
628
+
629
+ it 'returns false for a nil sample' do
630
+ Collection.descending?(nil).should be_false
631
+ end
632
+
633
+ it 'returns true for an empty sample' do
634
+ Collection.descending?([].freeze).should be_true
635
+ end
636
+
637
+ it 'returns true for a one-element sample' do
638
+ Collection.descending?([100].freeze).should be_true
639
+ end
640
+
641
+ it 'returns true for an descending collection' do
642
+ Collection.descending?([4, 3, 2, 1].freeze).should be_true
643
+ end
644
+
645
+ it 'returns false for a non-descending collection' do
646
+ Collection.descending?([1, 3, 2, 4].freeze).should be_false
647
+ end
648
+
649
+ it 'returns the correct value when given a block' do
650
+ sample = [
651
+ {:count => 21},
652
+ {:count => 20},
653
+ {:count => 19},
654
+ {:count => 18}
655
+ ].freeze
656
+
657
+ Collection.descending?(sample){|item| item[:count]}.should be_true
658
+ end
659
+ end
660
+ end
661
+
662
+ context 'partitioning' do
663
+
664
+ context '#slice' do
665
+
666
+ context 'function signature' do
667
+
668
+ it 'raises an exception with less than two arguments' do
669
+ lambda {
670
+ Functional.slice(1)
671
+ }.should raise_exception(ArgumentError)
672
+ end
673
+
674
+ it 'raises and exception with more than three arguments' do
675
+ lambda {
676
+ Functional.slice(1, 2, 3, 4)
677
+ }.should raise_exception(ArgumentError)
678
+ end
679
+ end
680
+
681
+ context 'with index' do
682
+
683
+ it 'returns nil if the positive index is out of range' do
684
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
685
+ Functional.slice(sample, 9).should be_nil
686
+ end
687
+
688
+ it 'returns nil if the negative index is out of range' do
689
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
690
+ Functional.slice(sample, -10).should be_nil
691
+ end
692
+
693
+ it 'returns the element at index for a non-negative index' do
694
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
695
+ Functional.slice(sample, 3).should eq 14
696
+ end
697
+
698
+ it 'returns the element counted backward from the end for a negative index' do
699
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
700
+ Functional.slice(sample, -4).should eq 16
701
+ end
702
+ end
703
+
704
+ context 'with range' do
705
+
706
+ it 'returns nil when the positive index is out of range' do
707
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
708
+ Functional.slice(sample, (9..5)).should be_nil
709
+ end
710
+
711
+ it 'returns nil when the index is negative' do
712
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
713
+ Functional.slice(sample, (-1..5)).should be_nil
714
+ end
715
+
716
+ it 'returns a subarray starting at start and continuing to end' do
717
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
718
+ Functional.slice(sample, (1..5)).should eq [13, 13, 14, 13, 16]
719
+ end
720
+
721
+ it 'returns a subarray to the end when the end is out of range' do
722
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
723
+ Functional.slice(sample, (1..100)).should eq [13, 13, 14, 13, 16, 14, 21, 13]
724
+ end
725
+ end
726
+
727
+ context 'with start index and length' do
728
+
729
+ it 'returns nil when the positive index is out of range' do
730
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
731
+ Functional.slice(sample, 9, 5).should be_nil
732
+ end
733
+
734
+ it 'returns nil when the index is negative' do
735
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
736
+ Functional.slice(sample, -1, 5).should be_nil
737
+ end
738
+
739
+ it 'returns a subarray specified by range' do
740
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
741
+ Functional.slice(sample, 2, 4).should eq [13, 14, 13, 16]
742
+ end
743
+
744
+ it 'returns a subarray to the end when length is out of range' do
745
+ sample = [18, 13, 13, 14, 13, 16, 14, 21, 13].freeze
746
+ Functional.slice(sample, 2, 100).should eq [13, 14, 13, 16, 14, 21, 13]
747
+ end
748
+ end
749
+ end
750
+ end
751
+ end
752
+ end