modelize_property: use resolve_mtype_unchecked during build_signature
[nit.git] / lib / standard / collection / range.nit
index 1c3e934..da68294 100644 (file)
@@ -19,18 +19,25 @@ import abstract_collection
 class Range[E: Discrete]
        super Collection[E]
 
-       redef readable var _first: E
+       redef var first: E
 
        # Get the last element.
-       readable var _last: E
+       var last: E
 
        # Get the element after the last one.
-       readable var _after: E
+       var after: E
 
-       redef fun has(item) do return item >= _first and item <= _last
+       #     assert [1..10].has(5)
+       #     assert [1..10].has(10)
+       #     assert not [1..10[.has(10)
+       redef fun has(item) do return item >= first and item <= last
 
-       redef fun has_only(item) do return _first == item and item == _last or is_empty
+       #     assert [1..1].has_only(1)
+       #     assert not [1..10].has_only(1)
+       redef fun has_only(item) do return first == item and item == last or is_empty
 
+       #     assert [1..10].count(1)   == 1
+       #     assert [1..10].count(0)   == 0
        redef fun count(item)
        do
                if has(item) then
@@ -42,9 +49,14 @@ class Range[E: Discrete]
 
        redef fun iterator do return new IteratorRange[E](self)
 
+       #     assert [1..10].length             == 10
+       #     assert [1..10[.length             == 9
+       #     assert [1..1].length              == 1
+       #     assert [1..-10].length    == 0
        redef fun length
        do
-               var nb = _first.distance(_after)
+               if is_empty then return 0
+               var nb = first.distance(after)
                if nb > 0 then
                        return nb
                else
@@ -52,48 +64,87 @@ class Range[E: Discrete]
                end
        end
 
-       redef fun is_empty do return _first >= _after
+       #     assert not [1..10[.is_empty
+       #     assert not [1..1].is_empty
+       #     assert [1..-10].is_empty
+       redef fun is_empty do return first >= after
 
        # Create a range [`from`, `to`].
-       # The syntax `[from..to[` is equivalent.
-       init(from: E, to: E)
-       do
-               _first = from
-               _last = to
-               _after = to.succ
+       # The syntax `[from..to]` is equivalent.
+       #
+       #     var a = [10..15]
+       #     var b = new Range[Int] (10,15)
+       #     assert a == b
+       #     assert a.to_a == [10, 11, 12, 13, 14, 15]
+       init(from: E, to: E) is old_style_init do
+               first = from
+               last = to
+               after = to.successor(1)
        end
 
        # Create a range [`from`, `to`[.
        # The syntax `[from..to[` is equivalent.
+       #
+       #     var a = [10..15[
+       #     var b = new Range[Int].without_last(10,15)
+       #     assert a == b
+       #     assert a.to_a == [10, 11, 12, 13, 14]
        init without_last(from: E, to: E)
        do
-               _first = from
-               _last = to.prec
-               _after = to
+               first = from
+               last = to.predecessor(1)
+               after = to
+       end
+
+       # Two ranges are equals if they have the same first and last elements.
+       #
+       #     var a = new Range[Int](10, 15)
+       #     var b = new Range[Int].without_last(10, 15)
+       #     assert a == [10..15]
+       #     assert a == [10..16[
+       #     assert not a == [10..15[
+       #     assert b == [10..15[
+       #     assert b == [10..14]
+       #     assert not b == [10..15]
+       redef fun ==(o) do
+               return o isa Range[E] and self.first == o.first and self.last == o.last
+       end
+
+       #     var a = new Range[Int](10, 15)
+       #     assert a.hash == 455
+       #     var b = new Range[Int].without_last(10, 15)
+       #     assert b.hash == 432
+       redef fun hash do
+               # 11 and 23 are magic numbers empirically determined to be not so bad.
+               return first.hash * 11 + last.hash * 23
        end
 end
 
-class IteratorRange[E: Discrete]
+private class IteratorRange[E: Discrete]
        # Iterator on ranges.
        super Iterator[E]
-       var _range: Range[E]
-       redef readable var _item: E
+       var range: Range[E]
+       redef var item is noinit
 
        redef fun is_ok do return _item < _range.after
        
-       redef fun next do _item = _item.succ
+       redef fun next do _item = _item.successor(1)
        
-       init(r: Range[E])
+       init
        do
-               _range = r
-               _item = r.first
+               _item = _range.first
        end
 end
 
-redef class Discrete
+redef class Int
        # Returns the range from 0 to `self-1`, is used to do:
        #
-       #    for i in 3.times do print "Cool"
-       #    for i in 100.times do print "{i}/100"
-       fun times: Range[OTHER] do return new Range[OTHER](0, self-1)
+       #     var s = new Array[String]
+       #     for i in 3.times do s.add "cool"
+       #     assert s.join(" ") == "cool cool cool"
+       #
+       #     s.clear
+       #     for i in 10.times do s.add(i.to_s)
+       #     assert s.to_s == "0123456789"
+       fun times: Range[Int] do return [0 .. self[
 end