lib/collection: fix doc of the popular `Container`
[nit.git] / lib / standard / collection / abstract_collection.nit
index fa16295..e1cb6a0 100644 (file)
@@ -33,25 +33,29 @@ import kernel
 # Subclasses often provide a more efficient implementation.
 #
 # Because of the `iterator` method, Collections instances can use
-# the `for` control structure:
+# the `for` control structure.
 #
-#         var x: Collection[U]
-#         # ...
-#         for u in x do
-#             # u is a U
-#             # ...
-#         end
+# ~~~nitish
+# var x: Collection[U]
+# # ...
+# for u in x do
+#      # u is a U
+#      # ...
+# end
+# ~~~
 #
-# that is equivalent with
+# that is equivalent with the following:
 #
-#         var x: Collection[U]
-#         # ...
-#         var i = x.iterator
-#         while i.is_ok do
-#             var u = i.item # u is a U
-#             # ...
-#             i.next
-#         end
+# ~~~nitish
+# var x: Collection[U]
+# # ...
+# var i = x.iterator
+# while i.is_ok do
+#     var u = i.item # u is a U
+#     # ...
+#     i.next
+# end
+# ~~~
 interface Collection[E]
        # Get a new iterator on the collection.
        fun iterator: Iterator[E] is abstract
@@ -106,7 +110,7 @@ interface Collection[E]
        # How many occurrences of `item` are in the collection?
        # Comparisons are done with ==
        #
-       #    assert [10,20,10].count(10)         == 2
+       #     assert [10,20,10].count(10)         == 2
        fun count(item: E): Int
        do
                var nb = 0
@@ -116,7 +120,7 @@ interface Collection[E]
 
        # Return the first item of the collection
        #
-       #    assert [1,2,3].first                == 1
+       #     assert [1,2,3].first                == 1
        fun first: E
        do
                assert length > 0
@@ -125,13 +129,13 @@ interface Collection[E]
 
        # Does the collection contain at least each element of `other`?
        #
-       #    assert [1,3,4,2].has_all([1..2])    == true
-       #    assert [1,3,4,2].has_all([1..5])    == false
+       #     assert [1,3,4,2].has_all([1..2])    == true
+       #     assert [1,3,4,2].has_all([1..5])    == false
        #
        # Repeated elements in the collections are not considered.
        #
-       #    assert [1,1,1].has_all([1])         == true
-       #    assert [1..5].has_all([1,1,1])      == true
+       #     assert [1,1,1].has_all([1])         == true
+       #     assert [1..5].has_all([1,1,1])      == true
        #
        # 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.
@@ -146,16 +150,16 @@ interface Collection[E]
        # The same elements must be present in both `self` and `other`,
        # but the order of the elements in the collections are not considered.
        #
-       #    assert [1..3].has_exactly([3,1,2]) == true  # the same elements
-       #    assert [1..3].has_exactly([3,1])   == false # 2 is not in the array
-       #    assert [1..2].has_exactly([3,1,2]) == false # 3 is not in the range
+       #     assert [1..3].has_exactly([3,1,2]) == true  # the same elements
+       #     assert [1..3].has_exactly([3,1])   == false # 2 is not in the array
+       #     assert [1..2].has_exactly([3,1,2]) == false # 3 is not in the range
        #
        # Repeated elements must be present in both collections in the same amount.
        # So basically it is a multi-set comparison.
        #
-       #    assert [1,2,3,2].has_exactly([1,2,2,3]) == true  # the same elements
-       #    assert [1,2,3,2].has_exactly([1,2,3])   == false # more 2 in the first array
-       #    assert [1,2,3].has_exactly([1,2,2,3])   == false # more 2 in the second array
+       #     assert [1,2,3,2].has_exactly([1,2,2,3]) == true  # the same elements
+       #     assert [1,2,3,2].has_exactly([1,2,3])   == false # more 2 in the first array
+       #     assert [1,2,3].has_exactly([1,2,2,3])   == false # more 2 in the second array
        #
        # 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.
@@ -199,7 +203,7 @@ end
 #
 # 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]
@@ -301,7 +305,7 @@ end
 #      # ...
 #      s.add(a)
 #      assert s.has(b)      ==  true
-interface Set[E: Object]
+interface Set[E]
        super SimpleCollection[E]
 
        redef fun has_only(item)
@@ -373,7 +377,7 @@ interface Set[E: Object]
 end
 
 # MapRead are abstract associative collections: `key` -> `item`.
-interface MapRead[K: Object, V]
+interface MapRead[K, V]
        # Get the item at `key`
        #
        #     var x = new HashMap[String, Int]
@@ -412,7 +416,14 @@ interface MapRead[K: Object, V]
                return default
        end
 
-       # Alias for `keys.has`
+       # Is there an item associated with `key`?
+       #
+       #     var x = new HashMap[String, Int]
+       #     x["four"] = 4
+       #     assert x.has_key("four") == true
+       #     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)
 
        # Get a new iterator on the map.
@@ -462,6 +473,30 @@ interface MapRead[K: Object, 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
+
+       # Does `self` and `other` have the same keys associated with the same values?
+       #
+       # ~~~
+       # var a = new HashMap[String, Int]
+       # var b = new ArrayMap[Object, Numeric]
+       # assert a == b
+       # a["one"] = 1
+       # assert a != b
+       # b["one"] = 1
+       # assert a == b
+       # b["one"] = 2
+       # assert a != b
+       # ~~~
+       redef fun ==(other)
+       do
+               if not other isa MapRead[nullable Object, nullable Object] then return false
+               if other.length != self.length then return false
+               for k, v in self do
+                       if not other.has_key(k) then return false
+                       if other[k] != v then return false
+               end
+               return true
+       end
 end
 
 # Maps are associative collections: `key` -> `item`.
@@ -488,7 +523,7 @@ end
 #     assert map.values.has(1)      ==  true
 #     assert map.values.has(3)      ==  false
 #
-interface Map[K: Object, V]
+interface Map[K, V]
        super MapRead[K, V]
 
        # Set the `value` at `key`.
@@ -548,7 +583,7 @@ interface Map[K: Object, V]
 end
 
 # Iterators for Map.
-interface MapIterator[K: Object, V]
+interface MapIterator[K, V]
        # The current item.
        # Require `is_ok`.
        fun item: V is abstract
@@ -579,7 +614,7 @@ interface MapIterator[K: Object, V]
 end
 
 # Iterator on a 'keys' point of view of a map
-class MapKeysIterator[K: Object, V]
+class MapKeysIterator[K, V]
        super Iterator[K]
        # The original iterator
        var original_iterator: MapIterator[K, V]
@@ -590,7 +625,7 @@ class MapKeysIterator[K: Object, V]
 end
 
 # Iterator on a 'values' point of view of a map
-class MapValuesIterator[K: Object, V]
+class MapValuesIterator[K, V]
        super Iterator[V]
        # The original iterator
        var original_iterator: MapIterator[K, V]
@@ -937,7 +972,7 @@ end
 
 # Associative arrays that internally uses couples to represent each (key, value) pairs.
 # This is an helper class that some specific implementation of Map may implements.
-interface CoupleMap[K: Object, V]
+interface CoupleMap[K, V]
        super Map[K, V]
 
        # Return the couple of the corresponding key
@@ -959,12 +994,14 @@ interface CoupleMap[K: Object, V]
                        return c.second
                end
        end
+
+       redef fun has_key(key) do return couple_at(key) != null
 end
 
 # Iterator on CoupleMap
 #
 # Actually it is a wrapper around an iterator of the internal array of the map.
-private class CoupleMapIterator[K: Object, V]
+private class CoupleMapIterator[K, V]
        super MapIterator[K, V]
        redef fun item do return _iter.item.second