functional-ruby 1.0.0 → 1.1.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.
@@ -24,7 +24,7 @@ module Functional
24
24
  it 'default all fields values to nil' do
25
25
  fields = [:foo, :bar, :baz]
26
26
  clazz = Record.new(*fields)
27
-
27
+
28
28
  record = clazz.new
29
29
 
30
30
  fields.each do |field|
@@ -171,5 +171,34 @@ module Functional
171
171
  }.to_not raise_error
172
172
  end
173
173
  end
174
+
175
+ context 'subclassing' do
176
+
177
+ specify 'supports all capabilities on subclasses' do
178
+ record_clazz = Functional::Record.new(:first, :middle, :last, :suffix) do
179
+ mandatory :first, :last
180
+ end
181
+
182
+ clazz = Class.new(record_clazz) do
183
+ def full_name
184
+ "#{first} #{last}"
185
+ end
186
+
187
+ def formal_name
188
+ name = [first, middle, last].select{|s| ! s.to_s.empty?}.join(' ')
189
+ suffix.to_s.empty? ? name : name + ", #{suffix}"
190
+ end
191
+ end
192
+
193
+ jerry = clazz.new(first: 'Jerry', last: "D'Antonio")
194
+ ted = clazz.new(first: 'Ted', middle: 'Theodore', last: 'Logan', suffix: 'Esq.')
195
+
196
+ expect(jerry.full_name).to eq "Jerry D'Antonio"
197
+ expect(jerry.formal_name).to eq "Jerry D'Antonio"
198
+
199
+ expect(ted.full_name).to eq "Ted Logan"
200
+ expect(ted.formal_name).to eq "Ted Theodore Logan, Esq."
201
+ end
202
+ end
174
203
  end
175
204
  end
@@ -0,0 +1,679 @@
1
+ require 'spec_helper'
2
+ require 'rspec/expectations'
3
+
4
+ RSpec::Matchers.define :be_a_different_tuple_than do |expected|
5
+ match do |actual|
6
+ actual.is_a?(Functional::Tuple) && actual.object_id != expected.object_id
7
+ end
8
+ end
9
+
10
+ module Functional
11
+
12
+ describe Tuple do
13
+
14
+ context '#initialize' do
15
+
16
+ it 'creates an empty tuple when given no arguments' do
17
+ expect(Tuple.new).to be_empty
18
+ end
19
+
20
+ it 'creates an empty tuple when given an empty array' do
21
+ expect(Tuple.new([])).to be_empty
22
+ end
23
+
24
+ it 'creates a tuple when given a single array argument' do
25
+ subject = Tuple.new([:foo, :bar, :baz])
26
+
27
+ expect(subject).to_not be_empty
28
+ expect(subject[0]).to eq :foo
29
+ expect(subject[1]).to eq :bar
30
+ expect(subject[2]).to eq :baz
31
+ end
32
+
33
+ it 'creates a tuple when given a single argument that responds to #to_a' do
34
+ clazz = Class.new {
35
+ def to_a() [:foo, :bar, :baz]; end
36
+ }.new
37
+ subject = Tuple.new(clazz)
38
+
39
+ expect(subject).to_not be_empty
40
+ expect(subject[0]).to eq :foo
41
+ expect(subject[1]).to eq :bar
42
+ expect(subject[2]).to eq :baz
43
+ end
44
+
45
+ it 'raises an exception when given a non-array argument' do
46
+ expect {
47
+ Tuple.new(:foo)
48
+ }.to raise_error(ArgumentError)
49
+ end
50
+
51
+ it 'freezes the tuple' do
52
+ expect(Tuple.new).to be_frozen
53
+ expect(Tuple.new([])).to be_frozen
54
+ expect(Tuple.new([:foo, :bar, :baz])).to be_frozen
55
+ end
56
+ end
57
+
58
+ context '#at' do
59
+
60
+ subject { Tuple.new([:foo, :bar, :baz]) }
61
+
62
+ it 'returns the nth element when given a valid non-negative index' do
63
+ expect(subject.at(0)).to eq :foo
64
+ expect(subject.at(1)).to eq :bar
65
+ expect(subject.at(2)).to eq :baz
66
+ end
67
+
68
+ it 'returns the nth element from the end when given a valid negative index' do
69
+ expect(subject.at(-1)).to eq :baz
70
+ expect(subject.at(-2)).to eq :bar
71
+ expect(subject.at(-3)).to eq :foo
72
+ end
73
+
74
+ it 'returns nil when given a non-negative out-of-bounds index' do
75
+ expect(subject.at(3)).to be_nil
76
+ end
77
+
78
+ it 'returns nil when given a negative out-of-bounds index' do
79
+ expect(subject.at(-4)).to be_nil
80
+ end
81
+
82
+ it 'is aliased as #nth' do
83
+ expect(subject.nth(0)).to eq :foo
84
+ expect(subject.nth(1)).to eq :bar
85
+ expect(subject.nth(-2)).to eq :bar
86
+ expect(subject.nth(-3)).to eq :foo
87
+ end
88
+
89
+ it 'is aliased as #[]' do
90
+ expect(subject[0]).to eq :foo
91
+ expect(subject[1]).to eq :bar
92
+ expect(subject[-2]).to eq :bar
93
+ expect(subject[-3]).to eq :foo
94
+ end
95
+ end
96
+
97
+ context '#fetch' do
98
+
99
+ subject { Tuple.new([:foo, :bar, :baz]) }
100
+
101
+ it 'returns the nth element when given a valid non-negative index' do
102
+ expect(subject.fetch(0, 42)).to eq :foo
103
+ expect(subject.fetch(1, 42)).to eq :bar
104
+ expect(subject.fetch(2, 42)).to eq :baz
105
+ end
106
+
107
+ it 'returns the nth element from the end when given a valid negative index' do
108
+ expect(subject.fetch(-1, 42)).to eq :baz
109
+ expect(subject.fetch(-2, 42)).to eq :bar
110
+ expect(subject.fetch(-3, 42)).to eq :foo
111
+ end
112
+
113
+ it 'returns the given default when given a non-negative out-of-bounds index' do
114
+ expect(subject.fetch(3, 42)).to eq 42
115
+ end
116
+
117
+ it 'returns the given default when given a negative out-of-bounds index' do
118
+ expect(subject.fetch(-4, 42)).to eq 42
119
+ end
120
+ end
121
+
122
+ context '#length' do
123
+
124
+ it 'returns 0 for an empty tuple' do
125
+ expect(Tuple.new.length).to eq 0
126
+ end
127
+
128
+ it 'returns the length of a non-empty tuple' do
129
+ expect(Tuple.new([1, 2, 3]).length).to eq 3
130
+ end
131
+
132
+ it 'is aliased a #size' do
133
+ expect(Tuple.new.size).to eq 0
134
+ expect(Tuple.new([1, 2, 3]).size).to eq 3
135
+ end
136
+ end
137
+
138
+ context '#intersect' do
139
+
140
+ it 'returns an empty tuple when self is empty' do
141
+ subject = Tuple.new
142
+ other = Tuple.new([1, 2, 3])
143
+ result = subject.intersect(other)
144
+ expect(result).to be_a_different_tuple_than(subject)
145
+ expect(result).to be_empty
146
+ end
147
+
148
+ it 'returns an empty tuple when other is empty' do
149
+ subject = Tuple.new([1, 2, 3])
150
+ other = Tuple.new
151
+ result = subject.intersect(other)
152
+ expect(result).to be_a_different_tuple_than(subject)
153
+ expect(result).to be_empty
154
+ end
155
+
156
+ it 'returns a tuple with all elements common to both tuples' do
157
+ subject = Tuple.new([1, 2, 3])
158
+ other = Tuple.new([2, 3, 4])
159
+ result = subject.intersect(other)
160
+ expect(result).to be_a_different_tuple_than(subject)
161
+ expect(result).to eq [2, 3]
162
+ end
163
+
164
+ it 'removes duplicates from self' do
165
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
166
+ other = Tuple.new([2, 3, 4])
167
+ result = subject.intersect(other)
168
+ expect(result).to be_a_different_tuple_than(subject)
169
+ expect(result).to eq [2, 3]
170
+ end
171
+
172
+ it 'removes duplicates from other' do
173
+ subject = Tuple.new([1, 2, 3])
174
+ other = Tuple.new([2, 2, 3, 3, 3, 4])
175
+ result = subject.intersect(other)
176
+ expect(result).to be_a_different_tuple_than(subject)
177
+ expect(result).to eq [2, 3]
178
+ end
179
+
180
+ it 'operates on any other that responds to #to_a' do
181
+ subject = Tuple.new([1, 2, 3])
182
+ other = Class.new {
183
+ def to_a() [2, 3, 4]; end
184
+ }.new
185
+
186
+ result = subject.intersect(other)
187
+ expect(result).to be_a_different_tuple_than(subject)
188
+ expect(result).to eq [2, 3]
189
+ end
190
+
191
+ it 'is aliased as #&' do
192
+ subject = Tuple.new([1, 2, 3])
193
+ other = Tuple.new([2, 3, 4])
194
+ result = subject & other
195
+ expect(result).to be_a_different_tuple_than(subject)
196
+ expect(result).to eq [2, 3]
197
+ end
198
+ end
199
+
200
+ context '#union' do
201
+
202
+ it 'returns a copy of self when other is empty' do
203
+ subject = Tuple.new
204
+ other = Tuple.new([1, 2, 3])
205
+ result = subject.union(other)
206
+ expect(result).to be_a_different_tuple_than(subject)
207
+ expect(result).to eq [1, 2, 3]
208
+ end
209
+
210
+ it 'returns a copy of other when self is empty' do
211
+ subject = Tuple.new([1, 2, 3])
212
+ other = Tuple.new
213
+ result = subject.union(other)
214
+ expect(result).to be_a_different_tuple_than(subject)
215
+ expect(result).to eq [1, 2, 3]
216
+ end
217
+
218
+ it 'returns a tuple with all elements from both tuples' do
219
+ subject = Tuple.new([1, 2, 3])
220
+ other = Tuple.new([1, 2, 3, 4])
221
+ result = subject.union(other)
222
+ expect(result).to be_a_different_tuple_than(subject)
223
+ expect(result).to eq [1, 2, 3, 4]
224
+ end
225
+
226
+ it 'removes duplicates from self' do
227
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
228
+ other = Tuple.new([1, 2, 3, 4])
229
+ result = subject.union(other)
230
+ expect(result).to be_a_different_tuple_than(subject)
231
+ expect(result).to eq [1, 2, 3, 4]
232
+ end
233
+
234
+ it 'removes duplicates from other' do
235
+ subject = Tuple.new([1, 2, 3, 4])
236
+ other = Tuple.new([1, 2, 2, 3, 3, 3])
237
+ result = subject.union(other)
238
+ expect(result).to be_a_different_tuple_than(subject)
239
+ expect(result).to eq [1, 2, 3, 4]
240
+ end
241
+
242
+ it 'operates on any other that responds to #to_a' do
243
+ subject = Tuple.new([1, 2, 3])
244
+ other = Class.new {
245
+ def to_a() [2, 3, 4]; end
246
+ }.new
247
+
248
+ result = subject.union(other)
249
+ expect(result).to be_a_different_tuple_than(subject)
250
+ expect(result).to eq [1, 2, 3, 4]
251
+ end
252
+
253
+ it 'is aliased as #|' do
254
+ subject = Tuple.new([1, 2, 3])
255
+ other = Tuple.new([2, 3, 4])
256
+ result = subject | other
257
+ expect(result).to be_a_different_tuple_than(subject)
258
+ expect(result).to eq [1, 2, 3, 4]
259
+ end
260
+ end
261
+
262
+ context '#concat' do
263
+
264
+ it 'returns a copy of self when other is empty' do
265
+ subject = Tuple.new
266
+ other = Tuple.new([1, 2, 3])
267
+ result = subject.concat(other)
268
+ expect(result).to be_a_different_tuple_than(subject)
269
+ expect(result).to eq [1, 2, 3]
270
+ end
271
+
272
+ it 'returns a copy of other when self is empty' do
273
+ subject = Tuple.new([1, 2, 3])
274
+ other = Tuple.new
275
+ result = subject.concat(other)
276
+ expect(result).to be_a_different_tuple_than(subject)
277
+ expect(result).to eq [1, 2, 3]
278
+ end
279
+
280
+ it 'returns a new tuple containing all of self and other in order' do
281
+ subject = Tuple.new([1, 2, 3])
282
+ other = Tuple.new([4, 5, 6])
283
+ result = subject.concat(other)
284
+ expect(result).to be_a_different_tuple_than(subject)
285
+ expect(result).to eq [1, 2, 3, 4, 5, 6]
286
+ end
287
+
288
+ it 'does not remove duplicates from self or other' do
289
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
290
+ other = Tuple.new([4, 4, 4, 5, 5, 6])
291
+ result = subject.concat(other)
292
+ expect(result).to be_a_different_tuple_than(subject)
293
+ expect(result).to eq [1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6]
294
+ end
295
+
296
+ it 'operates on any other that responds to #to_a' do
297
+ subject = Tuple.new([1, 2, 3])
298
+ other = Class.new {
299
+ def to_a() [4, 5, 6]; end
300
+ }.new
301
+
302
+ result = subject.concat(other)
303
+ expect(result).to be_a_different_tuple_than(subject)
304
+ expect(result).to eq [1, 2, 3, 4, 5, 6]
305
+ end
306
+
307
+ it 'is aliased as #+' do
308
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
309
+ other = Tuple.new([4, 4, 4, 5, 5, 6])
310
+ result = subject + other
311
+ expect(result).to be_a_different_tuple_than(subject)
312
+ expect(result).to eq [1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6]
313
+ end
314
+ end
315
+
316
+ context '#diff' do
317
+
318
+ it 'returns a copy of self when other is empty' do
319
+ subject = Tuple.new([1, 2, 3])
320
+ other = Tuple.new
321
+ result = subject.diff(other)
322
+ expect(result).to be_a_different_tuple_than(subject)
323
+ expect(result).to eq [1, 2, 3]
324
+ end
325
+
326
+ it 'returns an empty tuple when self is empty' do
327
+ subject = Tuple.new
328
+ other = Tuple.new([1, 2, 3])
329
+ result = subject.diff(other)
330
+ expect(result).to be_a_different_tuple_than(subject)
331
+ expect(result).to be_empty
332
+ end
333
+
334
+ it 'returns an empty tuple when self and other have identical elements' do
335
+ subject = Tuple.new([1, 2, 3])
336
+ other = Tuple.new([1, 2, 3])
337
+ result = subject.diff(other)
338
+ expect(result).to be_a_different_tuple_than(subject)
339
+ expect(result).to be_empty
340
+ end
341
+
342
+ it 'returns a tuple with all elements in self not also in other' do
343
+ subject = Tuple.new([1, 2, 3])
344
+ other = Tuple.new([3, 4, 5])
345
+ result = subject.diff(other)
346
+ expect(result).to be_a_different_tuple_than(subject)
347
+ expect(result).to eq [1, 2]
348
+ end
349
+
350
+ it 'removes duplicates from self when in other' do
351
+ subject = Tuple.new([1, 2, 3, 3, 3])
352
+ other = Tuple.new([3, 4, 5])
353
+ result = subject.diff(other)
354
+ expect(result).to be_a_different_tuple_than(subject)
355
+ expect(result).to eq [1, 2]
356
+ end
357
+
358
+ it 'removes duplicates from other when in self' do
359
+ subject = Tuple.new([1, 2, 3])
360
+ other = Tuple.new([3, 3, 3, 4, 5])
361
+ result = subject.diff(other)
362
+ expect(result).to be_a_different_tuple_than(subject)
363
+ expect(result).to eq [1, 2]
364
+ end
365
+
366
+ it 'operates on any other that responds to #to_a' do
367
+ subject = Tuple.new([1, 2, 3])
368
+ other = Class.new {
369
+ def to_a() [3, 4, 5]; end
370
+ }.new
371
+
372
+ result = subject.diff(other)
373
+ expect(result).to be_a_different_tuple_than(subject)
374
+ expect(result).to eq [1, 2]
375
+ end
376
+
377
+ it 'is aliased as #-' do
378
+ subject = Tuple.new([1, 2, 3])
379
+ other = Tuple.new([3, 4, 5])
380
+ result = subject - other
381
+ expect(result).to be_a_different_tuple_than(subject)
382
+ expect(result).to eq [1, 2]
383
+ end
384
+ end
385
+
386
+ context '#repeat' do
387
+
388
+ it 'returns an empty tuple when multipled by zero' do
389
+ subject = Tuple.new([1, 2, 3])
390
+ result = subject.repeat(0)
391
+ expect(result).to be_a_different_tuple_than(subject)
392
+ expect(result).to be_empty
393
+ end
394
+
395
+ it 'returns a copy of self when multipled by one' do
396
+ subject = Tuple.new([1, 2, 3])
397
+ result = subject.repeat(1)
398
+ expect(result).to be_a_different_tuple_than(subject)
399
+ expect(result).to eq [1, 2, 3]
400
+ end
401
+
402
+ it 'returns a tuple containing elements from self repeated n times' do
403
+ subject = Tuple.new([1, 2, 3])
404
+ result = subject.repeat(3)
405
+ expect(result).to be_a_different_tuple_than(subject)
406
+ expect(result).to eq [1, 2, 3, 1, 2, 3, 1, 2, 3]
407
+ end
408
+
409
+ it 'raises an exception when given a negative argument' do
410
+ subject = Tuple.new([1, 2, 3])
411
+ expect {
412
+ subject.repeat(-2)
413
+ }.to raise_error(ArgumentError)
414
+ end
415
+
416
+ it 'is aliased as #*' do
417
+ subject = Tuple.new([1, 2, 3])
418
+ result = subject * 3
419
+ expect(result).to be_a_different_tuple_than(subject)
420
+ expect(result).to eq [1, 2, 3, 1, 2, 3, 1, 2, 3]
421
+ end
422
+ end
423
+
424
+ context '#uniq' do
425
+
426
+ it 'returns a empty tuple when empty' do
427
+ subject = Tuple.new
428
+ result = subject.uniq
429
+ expect(result).to be_a_different_tuple_than(subject)
430
+ expect(result).to be_empty
431
+ end
432
+
433
+ it 'returns a copy of self when there are no duplicate elements' do
434
+ subject = Tuple.new([1, 2, 3])
435
+ result = subject.uniq
436
+ expect(result).to be_a_different_tuple_than(subject)
437
+ expect(result).to eq [1, 2, 3]
438
+ end
439
+
440
+ it 'returns a new tuple with duplicates removed' do
441
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
442
+ result = subject.uniq
443
+ expect(result).to be_a_different_tuple_than(subject)
444
+ expect(result).to eq [1, 2, 3]
445
+ end
446
+ end
447
+
448
+ context '#each' do
449
+
450
+ it 'returns an Enumerable when no block given' do
451
+ subject = Tuple.new([1, 2, 3])
452
+ expect(subject.each).to be_a Enumerable
453
+ end
454
+
455
+ it 'enumerates over each element' do
456
+ result = []
457
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
458
+ subject.each{|item| result << item }
459
+ expect(result).to eq [1, 2, 2, 3, 3, 3]
460
+ end
461
+
462
+ it 'does not call the block when empty' do
463
+ result = false
464
+ Tuple.new.each{|item| expected = true}
465
+ expect(result).to be false
466
+ end
467
+ end
468
+
469
+ context '#each_with_index' do
470
+
471
+ it 'returns an Enumerable when no block given' do
472
+ subject = Tuple.new([1, 2, 3])
473
+ expect(subject.each_with_index).to be_a Enumerable
474
+ end
475
+
476
+ it 'enumerates over each element and index pair' do
477
+ result = {}
478
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
479
+ subject.each_with_index{|item, index| result[index] = item }
480
+
481
+ expected = {
482
+ 0 => 1,
483
+ 1 => 2,
484
+ 2 => 2,
485
+ 3 => 3,
486
+ 4 => 3,
487
+ 5 => 3,
488
+ }
489
+ expect(result).to eq expected
490
+ end
491
+
492
+ it 'does not call the block when empty' do
493
+ result = false
494
+ Tuple.new.each_with_index{|item, index| expected = true}
495
+ expect(result).to be false
496
+ end
497
+ end
498
+
499
+ context '#sequence' do
500
+
501
+ it 'returns an Enumerable when no block given' do
502
+ subject = Tuple.new([1, 2, 3])
503
+ expect(subject.sequence).to be_a Enumerable
504
+ end
505
+
506
+ it 'enumerates over each element' do
507
+ result = []
508
+ subject = Tuple.new([1, 2, 2, 3, 3, 3])
509
+ subject.sequence{|item, rest| result << item }
510
+ expect(result).to eq [1, 2, 2, 3, 3, 3]
511
+ end
512
+
513
+ it 'yields rest of tuple for each element' do
514
+ result = []
515
+ subject = Tuple.new([1, 2, 3, 4])
516
+ subject.sequence{|item, rest| result = rest; break }
517
+ expect(result).to eq [2, 3, 4]
518
+ end
519
+
520
+ it 'yields rest of tuple as a tuple' do
521
+ result = []
522
+ subject = Tuple.new([1, 2, 3, 4])
523
+ subject.sequence{|item, rest| result = rest; break }
524
+ expect(result).to be_a_different_tuple_than(subject)
525
+ end
526
+
527
+ it 'yields an empty tuple for rest when on last element' do
528
+ result = nil
529
+ subject = Tuple.new([1])
530
+ subject.sequence{|item, rest| result = rest }
531
+ expect(result).to be_a_different_tuple_than(subject)
532
+ expect(result).to eq []
533
+ end
534
+
535
+ it 'does not call the block when empty' do
536
+ result = false
537
+ Tuple.new.sequence{|item, rest| expected = true}
538
+ expect(result).to be false
539
+ end
540
+ end
541
+
542
+ context '#eql?' do
543
+
544
+ it 'returns true when compared to a tuple with identical elements' do
545
+ subject = Tuple.new([1, 2, 3])
546
+ other = Tuple.new([1, 2, 3])
547
+ expect(subject.eql?(other)).to be true
548
+ end
549
+
550
+ it 'returns false when given a tuple with different elements' do
551
+ subject = Tuple.new([1, 2, 3])
552
+ other = Tuple.new([2, 3, 4])
553
+ expect(subject.eql?(other)).to be false
554
+ end
555
+
556
+ it 'operates on any other that responds to #to_a' do
557
+ subject = Tuple.new([1, 2, 3])
558
+ other = Class.new {
559
+ def to_a() [1, 2, 3]; end
560
+ }.new
561
+
562
+ expect(subject.eql?(other)).to be true
563
+ end
564
+
565
+ it 'is aliased as #==' do
566
+ subject = Tuple.new([1, 2, 3])
567
+ identical = Tuple.new([1, 2, 3])
568
+ different = Tuple.new([2, 3, 4])
569
+
570
+ expect(subject == identical).to be true
571
+ expect(subject == different).to be false
572
+ end
573
+ end
574
+
575
+ context '#empty?' do
576
+
577
+ it 'returns true when there are no elements' do
578
+ subject = Tuple.new
579
+ expect(subject.empty?).to be true
580
+ end
581
+
582
+ it 'returns false when there are one or more elements' do
583
+ subject = Tuple.new([1, 2, 3])
584
+ expect(subject.empty?).to be false
585
+ end
586
+ end
587
+
588
+ context '#first' do
589
+
590
+ it 'returns nil when empty' do
591
+ subject = Tuple.new
592
+ expect(subject.first).to be nil
593
+ end
594
+
595
+ it 'returns the first element when not empty' do
596
+ subject = Tuple.new([1, 2, 3])
597
+ expect(subject.first).to eq 1
598
+ end
599
+
600
+ it 'is aliased as #head' do
601
+ expect(Tuple.new.head).to be nil
602
+ expect(Tuple.new([1, 2, 3]).head).to eq 1
603
+ end
604
+ end
605
+
606
+ context '#rest' do
607
+
608
+ it 'returns an empty tuple when empty' do
609
+ subject = Tuple.new
610
+ expect(subject.rest).to be_a_different_tuple_than(subject)
611
+ expect(subject.rest).to be_empty
612
+ end
613
+
614
+ it 'returns an empty tuple when there is only one item' do
615
+ subject = Tuple.new([1])
616
+ expect(subject.rest).to be_a_different_tuple_than(subject)
617
+ expect(subject.rest).to be_empty
618
+ end
619
+
620
+ it 'returns a tuple with all but the first element when not empty' do
621
+ subject = Tuple.new([1, 2, 3])
622
+ expect(subject.rest).to be_a_different_tuple_than(subject)
623
+ expect(subject.rest).to eq [2, 3]
624
+ end
625
+
626
+ it 'is aliased as #tail' do
627
+ expect(Tuple.new.rest).to be_a_different_tuple_than(subject)
628
+ expect(Tuple.new.rest).to be_empty
629
+ expect(Tuple.new([1, 2, 3]).rest).to be_a_different_tuple_than(subject)
630
+ expect(Tuple.new([1, 2, 3]).rest).to eq [2, 3]
631
+ end
632
+ end
633
+
634
+ context '#to_a' do
635
+
636
+ it 'returns an empty array when empty' do
637
+ subject = Tuple.new.to_a
638
+ expect(subject).to be_a Array
639
+ expect(subject).to be_empty
640
+ end
641
+
642
+ it 'returns an array with the same elements as self' do
643
+ subject = Tuple.new([1, 2, 3]).to_a
644
+ expect(subject).to be_a Array
645
+ expect(subject).to eq [1, 2, 3]
646
+ end
647
+
648
+ it 'returns a non-frozen array' do
649
+ expect(Tuple.new.to_a).to_not be_frozen
650
+ expect(Tuple.new([1, 2, 3]).to_a).to_not be_frozen
651
+ end
652
+
653
+ it 'is aliased as #to_ary' do
654
+ subject = Tuple.new([1, 2, 3]).to_ary
655
+ expect(subject).to be_a Array
656
+ expect(subject).to eq [1, 2, 3]
657
+ end
658
+ end
659
+
660
+ context 'reflection' do
661
+
662
+ specify '#inspect begins with the class name' do
663
+ subject = Tuple.new([1, 2, 3])
664
+ expect(subject.inspect).to match(/^#<#{described_class}:\s+/)
665
+ end
666
+
667
+ specify '#inspect includes a list of all elements' do
668
+ subject = Tuple.new([1, 2, 3])
669
+ expect(subject.inspect).to match(/\s+\[1, 2, 3\]>$/)
670
+ expect(Tuple.new.inspect).to match(/\s+\[\]>$/)
671
+ end
672
+
673
+ specify '#to_s returns the same string an an array with the same elements' do
674
+ expect(Tuple.new.to_s).to eq [].to_s
675
+ expect(Tuple.new([1, 2, 3]).to_s).to eq [1, 2, 3].to_s
676
+ end
677
+ end
678
+ end
679
+ end