Merge: Clean nit compilation directory
[nit.git] / lib / standard / collection / abstract_collection.nit
index d38e001..16e4b1e 100644 (file)
@@ -66,6 +66,14 @@ interface Collection[E]
        #     assert [1..1[.is_empty   == true
        fun is_empty: Bool do return length == 0
 
+       # Alias for `not is_empty`.
+       #
+       # Some people prefer to have conditions grammatically easier to read.
+       #
+       #     assert [1,2,3].not_empty  == true
+       #     assert [1..1[.not_empty   == false
+       fun not_empty: Bool do return not self.is_empty
+
        # Number of items in the collection.
        #
        #     assert [10,20,30].length == 3
@@ -84,7 +92,7 @@ interface Collection[E]
        #     assert [1,2,3].has(9)    == false
        #     assert [1..5[.has(2)     == true
        #     assert [1..5[.has(9)     == false
-       fun has(item: E): Bool
+       fun has(item: nullable Object): Bool
        do
                for i in self do if i == item then return true
                return false
@@ -101,7 +109,7 @@ interface Collection[E]
        #     assert [3..3[.has_only(1)          == true # empty collection
        #
        # ENSURE `is_empty implies result == true`
-       fun has_only(item: E): Bool
+       fun has_only(item: nullable Object): Bool
        do
                for i in self do if i != item then return false
                return true
@@ -111,7 +119,7 @@ interface Collection[E]
        # Comparisons are done with ==
        #
        #     assert [10,20,10].count(10)         == 2
-       fun count(item: E): Int
+       fun count(item: nullable Object): Int
        do
                var nb = 0
                for i in self do if i == item then nb += 1
@@ -139,7 +147,7 @@ interface Collection[E]
        #
        # Note that the default implementation is general and correct for any lawful Collections.
        # It is memory-efficient but relies on `has` so may be CPU-inefficient for some kind of collections.
-       fun has_all(other: Collection[E]): Bool
+       fun has_all(other: Collection[nullable Object]): Bool
        do
                for x in other do if not has(x) then return false
                return true
@@ -163,7 +171,7 @@ interface Collection[E]
        #
        # Note that the default implementation is general and correct for any lawful Collections.
        # It is memory-efficient but relies on `count` so may be CPU-inefficient for some kind of collections.
-       fun has_exactly(other: Collection[E]): Bool
+       fun has_exactly(other: Collection[nullable Object]): Bool
        do
                if length != other.length then return false
                for e in self do if self.count(e) != other.count(e) then return false
@@ -171,8 +179,9 @@ interface Collection[E]
        end
 end
 
-# Instances of the Iterator class generates a series of elements, one at a time.
-# They are mainly used with collections.
+# Iterators generate a series of elements, one at a time.
+#
+# They are mainly used with collections and obtained from `Collection::iterator`.
 interface Iterator[E]
        # The current item.
        # Require `is_ok`.
@@ -182,6 +191,37 @@ interface Iterator[E]
        # Require `is_ok`.
        fun next is abstract
 
+       # Jump to the next item `step` times.
+       #
+       # ~~~
+       # var i = [11, 22, 33, 44].iterator
+       # assert i.item == 11
+       # i.next_by 2
+       # assert i.item == 33
+       # ~~~
+       #
+       # `next_by` should be used instead of looping on `next` because is takes care
+       # of stopping if the end of iteration is reached prematurely whereas a loop of
+       # `next` will abort because of the precondition on `is_ok`.
+       #
+       # ~~~
+       # i.next_by 100
+       # assert not i.is_ok
+       # ~~~
+       #
+       # If `step` is negative, this method aborts.
+       # But specific subclasses can change this and do something more meaningful instead.
+       #
+       # Require `is_ok`
+       fun next_by(step: Int)
+       do
+               assert step >= 0
+               while is_ok and step > 0 do
+                       next
+                       step -= 1
+               end
+       end
+
        # Is there a current item ?
        fun is_ok: Bool is abstract
 
@@ -197,13 +237,50 @@ interface Iterator[E]
        #
        # Do nothing by default.
        fun finish do end
+
+       # A decorator around `self` that advance self a given number of steps instead of one.
+       #
+       # ~~~
+       # var i = [11, 22, 33, 44, 55].iterator
+       # var i2 = i.to_step(2)
+       #
+       # assert i2.item == 11
+       # i2.next
+       # assert i2.item == 33
+       #
+       # assert i.item == 33
+       # ~~~
+       fun to_step(step: Int): Iterator[E] do return new StepIterator[E](self, step)
+end
+
+# A basic helper class to specialize specific Iterator decorators
+abstract class IteratorDecorator[E]
+       super Iterator[E]
+
+       # The underling iterator
+       protected var real: Iterator[E]
+
+       redef fun is_ok do return real.is_ok
+       redef fun item do return real.item
+       redef fun finish do real.finish
+       redef fun next do real.next
+       redef fun next_by(step) do real.next_by(step)
+end
+
+# A decorator that advance a given number of steps
+private class StepIterator[E]
+       super IteratorDecorator[E]
+       var step: Int
+
+       redef fun next do real.next_by(step)
+       redef fun next_by(step) do real.next_by(step * self.step)
 end
 
 # A collection that contains only one item.
 #
 # Used to pass arguments by reference.
 #
-# Also used when one want to give asingle element when a full
+# Also used when one want to give a single element when a full
 # collection is expected
 class Container[E]
        super Collection[E]
@@ -240,7 +317,7 @@ private class ContainerIterator[E]
 
        redef fun next do is_ok = false
 
-       redef var is_ok: Bool = true
+       redef var is_ok = true
 
        var container: Container[E]
 end
@@ -258,19 +335,19 @@ interface RemovableCollection[E]
        # ENSURE `is_empty`
        fun clear is abstract
 
-       # Remove an occucence of `item`
+       # Remove an occurrence of `item`
        #
        #     var a = [1,2,3,1,2,3]
        #     a.remove 2
        #     assert a == [1,3,1,2,3]
-       fun remove(item: E) is abstract
+       fun remove(item: nullable Object) is abstract
 
-       # Remove all occurences of `item`
+       # Remove all occurrences of `item`
        #
        #     var a = [1,2,3,1,2,3]
        #     a.remove_all 2
        #     assert a == [1,3,1,3]
-       fun remove_all(item: E) do while has(item) do remove(item)
+       fun remove_all(item: nullable Object) do while has(item) do remove(item)
 end
 
 # Items can be added to these collections.
@@ -336,7 +413,7 @@ interface Set[E]
        # Equality is defined on set and means that each set contains the same elements
        redef fun ==(other)
        do
-               if not other isa Set[Object] then return false
+               if not other isa Set[nullable Object] then return false
                if other.length != length then return false
                return has_all(other)
        end
@@ -387,7 +464,7 @@ interface MapRead[K, V]
        #
        # If the key is not in the map, `provide_default_value` is called (that aborts by default)
        # See `get_or_null` and `get_or_default` for safe variations.
-       fun [](key: K): V is abstract
+       fun [](key: nullable Object): V is abstract
 
        # Get the item at `key` or null if `key` is not in the map.
        #
@@ -397,7 +474,7 @@ interface MapRead[K, V]
        #     assert x.get_or_null("five") == null
        #
        # Note: use `has_key` and `[]` if you need the distinction between a key associated with null, and no key.
-       fun get_or_null(key: K): nullable V
+       fun get_or_null(key: nullable Object): nullable V
        do
                if has_key(key) then return self[key]
                return null
@@ -410,7 +487,7 @@ interface MapRead[K, V]
        #     assert x.get_or_default("four", 40) == 4
        #     assert x.get_or_default("five", 50) == 50
        #
-       fun get_or_default(key: K, default: V): V
+       fun get_or_default(key: nullable Object, default: V): V
        do
                if has_key(key) then return self[key]
                return default
@@ -424,7 +501,7 @@ interface MapRead[K, V]
        #     assert x.has_key("five") == false
        #
        # By default it is a synonymous to `keys.has` but could be redefined with a direct implementation.
-       fun has_key(key: K): Bool do return self.keys.has(key)
+       fun has_key(key: nullable Object): Bool do return self.keys.has(key)
 
        # Get a new iterator on the map.
        fun iterator: MapIterator[K, V] is abstract
@@ -472,7 +549,7 @@ interface MapRead[K, V]
        #
        # Note: the value is returned *as is*, implementations may want to store the value in the map before returning it
        # @toimplement
-       protected fun provide_default_value(key: K): V do abort
+       protected fun provide_default_value(key: nullable Object): V do abort
 
        # Does `self` and `other` have the same keys associated with the same values?
        #
@@ -497,6 +574,25 @@ interface MapRead[K, V]
                end
                return true
        end
+
+       # A hashcode based on the hashcode of the keys and the values.
+       #
+       # ~~~
+       # var a = new HashMap[String, Int]
+       # var b = new ArrayMap[Object, Numeric]
+       # a["one"] = 1
+       # b["one"] = 1
+       # assert a.hash == b.hash
+       # ~~~
+       redef fun hash
+       do
+               var res = length
+               for k, v in self do
+                       if k != null then res += k.hash * 7
+                       if v != null then res += v.hash * 11
+               end
+               return res
+       end
 end
 
 # Maps are associative collections: `key` -> `item`.
@@ -688,7 +784,7 @@ interface SequenceRead[E]
        #     var a = [10,20,30,10,20,30]
        #     assert a.index_of(20)   == 1
        #     assert a.index_of(40)   == -1
-       fun index_of(item: E): Int do return index_of_from(item, 0)
+       fun index_of(item: nullable Object): Int do return index_of_from(item, 0)
 
        # The index of the last occurrence of `item`.
        # Return -1 if `item` is not found.
@@ -697,7 +793,7 @@ interface SequenceRead[E]
        #     var a = [10,20,30,10,20,30]
        #     assert a.last_index_of(20)   == 4
        #     assert a.last_index_of(40)   == -1
-       fun last_index_of(item: E): Int do return last_index_of_from(item, length-1)
+       fun last_index_of(item: nullable Object): Int do return last_index_of_from(item, length-1)
 
        # The index of the first occurrence of `item`, starting from pos.
        # Return -1 if `item` is not found.
@@ -707,7 +803,7 @@ interface SequenceRead[E]
        #     assert a.index_of_from(20, 3)   == 4
        #     assert a.index_of_from(20, 4)   == 4
        #     assert a.index_of_from(20, 5)   == -1
-       fun index_of_from(item: E, pos: Int): Int
+       fun index_of_from(item: nullable Object, pos: Int): Int
        do
                var p = 0
                var i = iterator
@@ -727,7 +823,7 @@ interface SequenceRead[E]
        #     assert a.last_index_of_from(20, 2)   == 1
        #     assert a.last_index_of_from(20, 1)   == 1
        #     assert a.last_index_of_from(20, 0)   == -1
-       fun last_index_of_from(item: E, pos: Int): Int
+       fun last_index_of_from(item: nullable Object, pos: Int): Int
        do
                var res = -1
                var p = 0
@@ -977,7 +1073,7 @@ interface CoupleMap[K, V]
 
        # Return the couple of the corresponding key
        # Return null if the key is no associated element
-       protected fun couple_at(key: K): nullable Couple[K, V] is abstract
+       protected fun couple_at(key: nullable Object): nullable Couple[K, V] is abstract
 
        # Return a new iteralot on all couples
        # Used to provide `iterator` and others
@@ -1004,7 +1100,7 @@ end
 private class CoupleMapIterator[K, V]
        super MapIterator[K, V]
        redef fun item do return _iter.item.second
-       
+
        #redef fun item=(e) do _iter.item.second = e
 
        redef fun key do return _iter.item.first