functional-ruby 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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