lib: add `provide_default_value` in Map to allow subclasses to provide
[nit.git] / lib / standard / collection / abstract_collection.nit
index 536d656..18bac96 100644 (file)
@@ -54,17 +54,6 @@ interface Collection[E]
        # Get a new iterator on the collection.
        fun iterator: Iterator[E] is abstract
 
-       # Iterate over each element of the collection
-       fun iterate
-               !each(e: E)
-       do
-               var i = iterator
-               while i.is_ok do
-                       each(i.item)
-                       i.next
-               end
-       end
-
        # Is there no item in the collection?
        #
        #     assert [1,2,3].is_empty  == false
@@ -124,7 +113,7 @@ interface Collection[E]
                return nb
        end
 
-       # Return one the item of the collection
+       # Return the first item of the collection
        #
        #    assert [1,2,3].first                == 1
        fun first: E
@@ -162,6 +151,7 @@ interface Iterator[E]
 end
 
 # A collection that contains only one item.
+# Used to pass arguments by reference
 class Container[E]
        super Collection[E]
 
@@ -233,7 +223,7 @@ end
 
 # Abstract sets.
 #
-# Set contains contains only one element with the same value (according to ==).
+# Set is a collection without ducplicates (according to ==)
 #      var s: Set[String] = new ArraySet[String]
 #      var a = "Hello"
 #      var b = "Hel" + "lo"
@@ -275,6 +265,14 @@ interface Set[E: Object]
                if other.length != length then return false
                return has_all(other)
        end
+
+       # because of the law between `==` and `hash`, hash is redefined to be the sum of the hash of the elements
+       redef fun hash
+       do
+               var res = 0
+               for e in self do res += res.hash
+               return res
+       end
 end
 
 # MapRead are abstract associative collections: `key` -> `item`.
@@ -282,6 +280,20 @@ interface MapRead[K: Object, E]
        # Get the item at `key`.
        fun [](key: K): E is abstract
 
+       # Get the item at `key` or null if `key` is not in the map.
+       #
+       #     var x = new HashMap[String, Int]
+       #     x["four"] = 4
+       #     assert x.get_or_null("four") == 4
+       #     assert x.get_or_null("five") == null
+       #
+       # Note: use `has_key` and `[]` if you need the distinction bewteen a key associated with null, and no key.
+       fun get_or_null(key: K): nullable E
+       do
+               if has_key(key) then return self[key]
+               return null
+       end
+
        # Get the item at `key` or return `default` if not in map
        fun get_or_default(key: K, default: E): E
        do
@@ -295,17 +307,6 @@ interface MapRead[K: Object, E]
        # Get a new iterator on the map.
        fun iterator: MapIterator[K, E] is abstract
 
-       # Iterate over each element of the collection
-       fun iterate
-               !each(k: K, v: E)
-       do
-               var i = iterator
-               while i.is_ok do
-                       each(i.key, i.item)
-                       i.next
-               end
-       end
-
        # Return the point of view of self on the values only.
        # Note that `self` and `values` are views on the same data;
        # therefore any modification of one is visible on the other.
@@ -321,6 +322,13 @@ interface MapRead[K: Object, E]
 
        # Number of items in the collection.
        fun length: Int is abstract
+
+       # Called by the underling implementation of `[]` to provide a default value when a `key` has no value
+       # By default the behavior is to abort.
+       #
+       # 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): E do abort
 end
 
 # Maps are associative collections: `key` -> `item`.
@@ -453,6 +461,28 @@ interface SequenceRead[E]
        end
 
        redef fun iterator: IndexedIterator[E] is abstract
+
+       # Two sequences are equals if they have the same items in the same order.
+       redef fun ==(o)
+       do
+               if not o isa SequenceRead[nullable Object] then return false
+               var l = length
+               if o.length != l then return false
+               var i = 0
+               while i < l do
+                       if self[i] != o[i] then return false
+                       i += 1
+               end
+               return true
+       end
+
+       # because of the law between `==` and `hash`, hash is redefined to be the sum of the hash of the elements
+       redef fun hash
+       do
+               var res = 0
+               for e in self do res += res.hash
+               return res
+       end
 end
 
 # Sequence are indexed collection.
@@ -522,7 +552,7 @@ interface CoupleMap[K: Object, E]
        do
                var c = couple_at(key)
                if c == null then
-                       abort
+                       return provide_default_value(key)
                else
                        return c.second
                end