Skip to content

Commit ec9a64c

Browse files
committed
Merge branch 'release/v0.1.3'
2 parents 7de6bc8 + ef4918c commit ec9a64c

File tree

3 files changed

+56
-23
lines changed

3 files changed

+56
-23
lines changed

shard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: multiset
2-
version: 0.1.2
2+
version: 0.1.3
33

44
authors:
55
- Tom Crouch <tom.crouch@gmail.com>

spec/multiset_spec.cr

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,17 @@ describe "Multiset" do
356356

357357
describe "#each" do
358358
context "with no block given" do
359-
it "iterates over unique elements" do
359+
context "with no values" do
360+
it "returns Stop" do
361+
iter = Multiset.new(Array(Int32).new).each
362+
iter.next.should be_a(Iterator::Stop)
363+
iter.next.should be_a(Iterator::Stop)
364+
iter.rewind
365+
iter.next.should be_a(Iterator::Stop)
366+
end
367+
end
368+
369+
it "iterates over unique elements of one type" do
360370
iter = Multiset{1, 2, 3}.each
361371
iter.next.should eq(1)
362372
iter.next.should eq(2)
@@ -367,6 +377,17 @@ describe "Multiset" do
367377
iter.next.should eq(1)
368378
end
369379

380+
it "iterates over unique elements of union type" do
381+
iter = Multiset{1, "a", 3}.each
382+
iter.next.should eq(1)
383+
iter.next.should eq("a")
384+
iter.next.should eq(3)
385+
iter.next.should be_a(Iterator::Stop)
386+
387+
iter.rewind
388+
iter.next.should eq(1)
389+
end
390+
370391
it "iterates over duplicate elements" do
371392
iter = Multiset{1, 2, 3, 2, 1, 1}.each
372393
iter.next.should eq(1)
@@ -383,11 +404,18 @@ describe "Multiset" do
383404
end
384405

385406
context "with block" do
386-
it "yields each element" do
387-
ms = Multiset{1, 2, 2, 3}
407+
it "yields each over unique elements" do
408+
ms = Multiset{1, 2, 3}
409+
elems = [] of Int32
410+
ms.each { |e| elems << e }
411+
elems.should eq [1, 2, 3]
412+
end
413+
414+
it "yields each over duplicate elements" do
415+
ms = Multiset{1, 2, 3, 2, 1, 1}
388416
elems = [] of Int32
389417
ms.each { |e| elems << e }
390-
elems.should eq [1, 2, 2, 3]
418+
elems.should eq [1, 1, 1, 2, 2, 3]
391419
end
392420
end
393421
end

src/multiset.cr

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct Multiset(T)
1818
include Enumerable(T)
1919
include Iterable
2020

21-
VERSION = "0.1.2"
21+
VERSION = "0.1.3"
2222

2323
# creates a new empty multiset
2424
#
@@ -92,7 +92,7 @@ struct Multiset(T)
9292

9393
# returns an iterator over each element
9494
def each
95-
MultiEntryIterator(T).new(@hash, @hash.@first)
95+
MultiEntryIterator(typeof(@hash.each), T).new(@hash.each)
9696
end
9797

9898
# increments multiplicity of the given `Object` by `count` and returns self
@@ -449,33 +449,38 @@ struct Multiset(T)
449449
end
450450

451451
# :nodoc:
452-
class MultiEntryIterator(T)
452+
private class MultiEntryIterator(I, T)
453453
include Iterator(T)
454454

455-
@h : Hash(T, Int32)
456-
@current : Hash::Entry(T, Int32)?
455+
@val : T | Stop
456+
@count : Int32
457457

458-
def initialize(@h, @current)
459-
@remaining = @current.try(&.value) || 0
458+
def initialize(@iterator : I)
459+
@val, @count = next_tuple
460460
end
461461

462462
def next
463-
if current = @current
464-
value = current.key
465-
if (@remaining -= 1) <= 0
466-
@current = current.fore
467-
@remaining = @current.try(&.value) || 0
468-
end
469-
value
470-
else
471-
stop
463+
value = @val
464+
return value if value.is_a?(Stop)
465+
466+
if (@count -= 1) <= 0
467+
@val, @count = next_tuple
472468
end
469+
value
473470
end
474471

475472
def rewind
476-
@current = @h.@first
477-
@remaining = @current.try(&.value) || 0
473+
@iterator.rewind
474+
@val, @count = next_tuple
478475
self
479476
end
477+
478+
protected def next_tuple : Tuple(T | Stop, Int32)
479+
if (value = @iterator.next).is_a?(Stop)
480+
{Iterator.stop, 0}
481+
else
482+
value
483+
end
484+
end
480485
end
481486
end

0 commit comments

Comments
 (0)