Skip to content

Commit 19f767b

Browse files
author
Ary Borenszweig
committedDec 20, 2016
Array/Enumerable/Iterator reuse flag
1 parent 7f0182c commit 19f767b

File tree

7 files changed

+621
-88
lines changed

7 files changed

+621
-88
lines changed
 

‎spec/std/array_spec.cr

+158
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,18 @@ describe "Array" do
14841484
sums.should eq([9, 9, 9, 9, 9, 9])
14851485
end
14861486

1487+
it "yields with reuse = true" do
1488+
sums = [] of Int32
1489+
object_ids = Set(UInt64).new
1490+
[1, 2, 3].each_permutation(3, reuse: true) do |perm|
1491+
object_ids << perm.object_id
1492+
perm.map! &.+(1)
1493+
sums << perm.sum
1494+
end.should eq([1, 2, 3])
1495+
sums.should eq([9, 9, 9, 9, 9, 9])
1496+
object_ids.size.should eq(1)
1497+
end
1498+
14871499
assert { expect_raises(ArgumentError, "size must be positive") { [1].each_permutation(-1) { } } }
14881500

14891501
it "returns iterator" do
@@ -1511,6 +1523,20 @@ describe "Array" do
15111523
iter.rewind
15121524
iter.next.should eq(perms[0])
15131525
end
1526+
1527+
it "returns iterator with reuse = true" do
1528+
a = [1, 2, 3]
1529+
object_ids = Set(UInt64).new
1530+
perms = a.permutations
1531+
iter = a.each_permutation(reuse: true)
1532+
perms.each do |perm|
1533+
b = iter.next.as(Array)
1534+
object_ids << b.object_id
1535+
b.should eq(perm)
1536+
end
1537+
iter.next.should be_a(Iterator::Stop)
1538+
object_ids.size.should eq(1)
1539+
end
15141540
end
15151541

15161542
describe "combinations" do
@@ -1542,6 +1568,27 @@ describe "Array" do
15421568
sums.should eq([9])
15431569
end
15441570

1571+
it "does with reuse = true" do
1572+
sums = [] of Int32
1573+
object_ids = Set(UInt64).new
1574+
[1, 2, 3].each_combination(2, reuse: true) do |comb|
1575+
sums << comb.sum
1576+
object_ids << comb.object_id
1577+
end
1578+
sums.should eq([3, 4, 5])
1579+
object_ids.size.should eq(1)
1580+
end
1581+
1582+
it "does with reuse = array" do
1583+
sums = [] of Int32
1584+
reuse = [] of Int32
1585+
[1, 2, 3].each_combination(2, reuse: reuse) do |comb|
1586+
sums << comb.sum
1587+
comb.should be(reuse)
1588+
end
1589+
sums.should eq([3, 4, 5])
1590+
end
1591+
15451592
assert { expect_raises(ArgumentError, "size must be positive") { [1].each_combination(-1) { } } }
15461593

15471594
it "returns iterator" do
@@ -1556,6 +1603,33 @@ describe "Array" do
15561603
iter.rewind
15571604
iter.next.should eq(combs[0])
15581605
end
1606+
1607+
it "returns iterator with reuse = true" do
1608+
a = [1, 2, 3, 4]
1609+
combs = a.combinations(2)
1610+
object_ids = Set(UInt64).new
1611+
iter = a.each_combination(2, reuse: true)
1612+
combs.each do |comb|
1613+
b = iter.next
1614+
object_ids << b.object_id
1615+
b.should eq(comb)
1616+
end
1617+
iter.next.should be_a(Iterator::Stop)
1618+
object_ids.size.should eq(1)
1619+
end
1620+
1621+
it "returns iterator with reuse = array" do
1622+
a = [1, 2, 3, 4]
1623+
reuse = [] of Int32
1624+
combs = a.combinations(2)
1625+
iter = a.each_combination(2, reuse: reuse)
1626+
combs.each do |comb|
1627+
b = iter.next
1628+
b.should be(reuse)
1629+
b.should eq(comb)
1630+
end
1631+
iter.next.should be_a(Iterator::Stop)
1632+
end
15591633
end
15601634

15611635
describe "repeated_combinations" do
@@ -1587,6 +1661,29 @@ describe "Array" do
15871661

15881662
assert { expect_raises(ArgumentError, "size must be positive") { [1].each_repeated_combination(-1) { } } }
15891663

1664+
it "yields with reuse = true" do
1665+
sums = [] of Int32
1666+
object_ids = Set(UInt64).new
1667+
[1, 2, 3].each_repeated_combination(3, reuse: true) do |comb|
1668+
object_ids << comb.object_id
1669+
comb.map! &.+(1)
1670+
sums << comb.sum
1671+
end.should eq([1, 2, 3])
1672+
sums.should eq([6, 7, 8, 8, 9, 10, 9, 10, 11, 12])
1673+
object_ids.size.should eq(1)
1674+
end
1675+
1676+
it "yields with reuse = array" do
1677+
sums = [] of Int32
1678+
reuse = [] of Int32
1679+
[1, 2, 3].each_repeated_combination(3, reuse: reuse) do |comb|
1680+
comb.should be(reuse)
1681+
comb.map! &.+(1)
1682+
sums << comb.sum
1683+
end.should eq([1, 2, 3])
1684+
sums.should eq([6, 7, 8, 8, 9, 10, 9, 10, 11, 12])
1685+
end
1686+
15901687
it "returns iterator" do
15911688
a = [1, 2, 3, 4]
15921689
combs = a.repeated_combinations(2)
@@ -1599,6 +1696,33 @@ describe "Array" do
15991696
iter.rewind
16001697
iter.next.should eq(combs[0])
16011698
end
1699+
1700+
it "returns iterator with reuse = true" do
1701+
a = [1, 2, 3, 4]
1702+
object_ids = Set(UInt64).new
1703+
combs = a.repeated_combinations(2)
1704+
iter = a.each_repeated_combination(2, reuse: true)
1705+
combs.each do |comb|
1706+
b = iter.next
1707+
object_ids << b.object_id
1708+
b.should eq(comb)
1709+
end
1710+
iter.next.should be_a(Iterator::Stop)
1711+
object_ids.size.should eq(1)
1712+
end
1713+
1714+
it "returns iterator with reuse = array" do
1715+
a = [1, 2, 3, 4]
1716+
reuse = [] of Int32
1717+
combs = a.repeated_combinations(2)
1718+
iter = a.each_repeated_combination(2, reuse: reuse)
1719+
combs.each do |comb|
1720+
b = iter.next
1721+
b.should be(reuse)
1722+
b.should eq(comb)
1723+
end
1724+
iter.next.should be_a(Iterator::Stop)
1725+
end
16021726
end
16031727

16041728
describe "repeated_permutations" do
@@ -1628,6 +1752,29 @@ describe "Array" do
16281752
sums.should eq([6, 7, 8, 7, 8, 9, 8, 9, 10, 7, 8, 9, 8, 9, 10, 9, 10, 11, 8, 9, 10, 9, 10, 11, 10, 11, 12])
16291753
end
16301754

1755+
it "yields with reuse = true" do
1756+
sums = [] of Int32
1757+
object_ids = Set(UInt64).new
1758+
[1, 2, 3].each_repeated_permutation(3, reuse: true) do |a|
1759+
object_ids << a.object_id
1760+
a.map! &.+(1)
1761+
sums << a.sum
1762+
end.should eq([1, 2, 3])
1763+
sums.should eq([6, 7, 8, 7, 8, 9, 8, 9, 10, 7, 8, 9, 8, 9, 10, 9, 10, 11, 8, 9, 10, 9, 10, 11, 10, 11, 12])
1764+
object_ids.size.should eq(1)
1765+
end
1766+
1767+
it "yields with reuse = array" do
1768+
sums = [] of Int32
1769+
reuse = [] of Int32
1770+
[1, 2, 3].each_repeated_permutation(3, reuse: reuse) do |a|
1771+
a.should be(reuse)
1772+
a.map! &.+(1)
1773+
sums << a.sum
1774+
end.should eq([1, 2, 3])
1775+
sums.should eq([6, 7, 8, 7, 8, 9, 8, 9, 10, 7, 8, 9, 8, 9, 10, 9, 10, 11, 8, 9, 10, 9, 10, 11, 10, 11, 12])
1776+
end
1777+
16311778
assert { expect_raises(ArgumentError, "size must be positive") { [1].each_repeated_permutation(-1) { } } }
16321779
end
16331780

@@ -1656,6 +1803,17 @@ describe "Array" do
16561803
res.should eq([[1, 3, 5], [1, 3, 6], [2, 3, 5], [2, 3, 6]])
16571804
end
16581805

1806+
it "more arrays, reuse = true" do
1807+
res = [] of Array(Int32)
1808+
object_ids = Set(UInt64).new
1809+
Array.each_product([[1, 2], [3], [5, 6]], reuse: true) do |r|
1810+
object_ids << r.object_id
1811+
res << r.dup
1812+
end
1813+
res.should eq([[1, 3, 5], [1, 3, 6], [2, 3, 5], [2, 3, 6]])
1814+
object_ids.size.should eq(1)
1815+
end
1816+
16591817
it "with splat" do
16601818
res = [] of Array(Int32 | Char)
16611819
Array.each_product([1, 2], ['a', 'b']) { |r| res << r }

‎spec/std/enumerable_spec.cr

+103
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,25 @@ describe "Enumerable" do
154154
result = [nil, nil, 1, 1, nil].chunk(&.itself).to_a
155155
result.should eq [{nil, [nil, nil]}, {1, [1, 1]}, {nil, [nil]}]
156156
end
157+
158+
it "reuses true" do
159+
iter = [1, 1, 2, 3, 3].chunk(reuse: true, &.itself)
160+
a = iter.next.as(Tuple)
161+
a.should eq({1, [1, 1]})
162+
163+
b = iter.next.as(Tuple)
164+
b.should eq({2, [2]})
165+
b[1].should be(a[1])
166+
167+
c = iter.next.as(Tuple)
168+
c.should eq({3, [3, 3]})
169+
c[1].should be(a[1])
170+
171+
iter.rewind
172+
a1 = iter.next.as(Tuple)
173+
a1.should eq({1, [1, 1]})
174+
a1[1].should be(a[1])
175+
end
157176
end
158177

159178
describe "chunks" do
@@ -227,19 +246,82 @@ describe "Enumerable" do
227246
iter.rewind
228247
iter.next.should eq([1, 2, 3])
229248
end
249+
250+
it "returns each_cons iterator with reuse = true" do
251+
iter = [1, 2, 3, 4, 5].each_cons(3, reuse: true)
252+
253+
a = iter.next
254+
a.should eq([1, 2, 3])
255+
256+
b = iter.next
257+
b.should be(a)
258+
end
259+
260+
it "returns each_cons iterator with reuse = array" do
261+
reuse = [] of Int32
262+
iter = [1, 2, 3, 4, 5].each_cons(3, reuse: reuse)
263+
264+
a = iter.next
265+
a.should eq([1, 2, 3])
266+
a.should be(reuse)
267+
end
268+
269+
it "returns running pairs with reuse = true" do
270+
array = [] of Array(Int32)
271+
object_ids = Set(UInt64).new
272+
[1, 2, 3, 4].each_cons(2, reuse: true) do |pair|
273+
object_ids << pair.object_id
274+
array << pair.dup
275+
end
276+
array.should eq([[1, 2], [2, 3], [3, 4]])
277+
object_ids.size.should eq(1)
278+
end
279+
280+
it "returns running pairs with reuse = array" do
281+
array = [] of Array(Int32)
282+
reuse = [] of Int32
283+
[1, 2, 3, 4].each_cons(2, reuse: reuse) do |pair|
284+
pair.should be(reuse)
285+
array << pair.dup
286+
end
287+
array.should eq([[1, 2], [2, 3], [3, 4]])
288+
end
230289
end
231290

232291
describe "each_slice" do
233292
it "returns partial slices" do
234293
array = [] of Array(Int32)
235294
[1, 2, 3].each_slice(2) { |slice| array << slice }
236295
array.should eq([[1, 2], [3]])
296+
array[0].should_not be(array[1])
237297
end
238298

239299
it "returns full slices" do
240300
array = [] of Array(Int32)
241301
[1, 2, 3, 4].each_slice(2) { |slice| array << slice }
242302
array.should eq([[1, 2], [3, 4]])
303+
array[0].should_not be(array[1])
304+
end
305+
306+
it "reuses with true" do
307+
array = [] of Array(Int32)
308+
object_ids = Set(UInt64).new
309+
[1, 2, 3, 4].each_slice(2, reuse: true) do |slice|
310+
object_ids << slice.object_id
311+
array << slice.dup
312+
end
313+
array.should eq([[1, 2], [3, 4]])
314+
object_ids.size.should eq(1)
315+
end
316+
317+
it "reuses with existing array" do
318+
array = [] of Array(Int32)
319+
reuse = [] of Int32
320+
[1, 2, 3, 4].each_slice(2, reuse: reuse) do |slice|
321+
slice.should be(reuse)
322+
array << slice.dup
323+
end
324+
array.should eq([[1, 2], [3, 4]])
243325
end
244326

245327
it "returns each_slice iterator" do
@@ -396,6 +478,27 @@ describe "Enumerable" do
396478
[1, 2, 4, 5].in_groups_of(3, 10) { |a| sums << a.sum }
397479
sums.should eq([7, 25])
398480
end
481+
482+
it "reuses with true" do
483+
array = [] of Array(Int32)
484+
object_ids = Set(UInt64).new
485+
[1, 2, 4, 5].in_groups_of(3, 10, reuse: true) do |group|
486+
object_ids << group.object_id
487+
array << group.dup
488+
end
489+
array.should eq([[1, 2, 4], [5, 10, 10]])
490+
object_ids.size.should eq(1)
491+
end
492+
493+
it "reuses with existing array" do
494+
array = [] of Array(Int32)
495+
reuse = [] of Int32
496+
[1, 2, 4, 5].in_groups_of(3, 10, reuse: reuse) do |slice|
497+
slice.should be(reuse)
498+
array << slice.dup
499+
end
500+
array.should eq([[1, 2, 4], [5, 10, 10]])
501+
end
399502
end
400503

401504
describe "includes?" do

0 commit comments

Comments
 (0)
Please sign in to comment.