core :: SequenceRead :: defaultinit
# Sequences are indexed collections.
# The first item is 0. The last is `length-1`.
#
# The order is the main caracteristic of sequence
# and all concrete implementation of sequences are basically interchangeable.
interface SequenceRead[E]
super Collection[E]
# Get the first item.
# Is equivalent with `self[0]`.
#
# var a = [1,2,3]
# assert a.first == 1
#
# REQUIRE `not is_empty`
redef fun first
do
assert not_empty: not is_empty
return self[0]
end
# Return the index-th element of the sequence.
# The first element is 0 and the last is `length-1`
# If index is invalid, the program aborts
#
# var a = [10,20,30]
# assert a[0] == 10
# assert a[1] == 20
# assert a[2] == 30
#
# REQUIRE `index >= 0 and index < length`
fun [](index: Int): E is abstract
# Return the index-th element but wrap
#
# Whereas `self[]` requires the index to exists, the `modulo` accessor automatically
# wraps overbound and underbouds indexes.
#
# ~~~
# var a = [10,20,30]
# assert a.modulo(1) == 20
# assert a.modulo(3) == 10
# assert a.modulo(-1) == 30
# assert a.modulo(-10) == 30
# ~~~
#
# REQUIRE `not_empty`
# ENSURE `result == self[modulo_index(index)]`
fun modulo(index: Int): E do return self[modulo_index(index)]
# Returns the real index for a modulo index.
#
# ~~~
# var a = [10,20,30]
# assert a.modulo_index(1) == 1
# assert a.modulo_index(3) == 0
# assert a.modulo_index(-1) == 2
# assert a.modulo_index(-10) == 2
# ~~~
#
# REQUIRE `not_empty`
fun modulo_index(index: Int): Int
do
var length = self.length
if index >= 0 then
return index % length
else
return length - (-1 - index) % length - 1
end
end
# Try to get an element, return `null` if the `index` is invalid.
#
# ~~~
# var a = [10,20,30]
# assert a.get_or_null(1) == 20
# assert a.get_or_null(3) == null
# assert a.get_or_null(-1) == null
# assert a.get_or_null(-10) == null
# ~~~
fun get_or_null(index: Int): nullable E
do
if index >= 0 and index < length then return self[index]
return null
end
# Try to get an element, return `default` if the `index` is invalid.
#
# ~~~
# var a = [10,20,30]
# assert a.get_or_default(1, -1) == 20
# assert a.get_or_default(3, -1) == -1
# assert a.get_or_default(-1, -1) == -1
# assert a.get_or_default(-10, -1) == -1
# ~~~
fun get_or_default(index: Int, default: E): E
do
if index >= 0 and index < length then return self[index]
return default
end
# Get the last item.
# Is equivalent with `self[length-1]`.
#
# var a = [1,2,3]
# assert a.last == 3
#
# REQUIRE `not is_empty`
fun last: E
do
assert not_empty: not is_empty
return self[length-1]
end
# The index of the first occurrence of `item`.
# Return -1 if `item` is not found.
# Comparison is done with `==`.
#
# var a = [10,20,30,10,20,30]
# assert a.index_of(20) == 1
# assert a.index_of(40) == -1
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.
# Comparison is done with `==`.
#
# 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: 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.
# Comparison is done with `==`.
#
# var a = [10,20,30,10,20,30]
# 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: nullable Object, pos: Int): Int
do
var p = 0
var i = iterator
while i.is_ok do
if p>=pos and i.item == item then return i.index
i.next
p += 1
end
return -1
end
# The index of the last occurrence of `item` starting from `pos` and decrementing.
# Return -1 if `item` is not found.
# Comparison is done with `==`.
#
# var a = [10,20,30,10,20,30]
# 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: nullable Object, pos: Int): Int do
var i = pos
while i >= 0 do
if self[i] == item then return i
i -= 1
end
return -1
end
# Two sequences are equals if they have the same items in the same order.
#
# var a = new List[Int]
# a.add(1)
# a.add(2)
# a.add(3)
# assert a == [1,2,3]
# assert a != [1,3,2]
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
# The 17 and 2/3 magic numbers were determined empirically.
# Note: the standard hash functions djb2, sbdm and fnv1 were also
# tested but were comparable (or worse).
var res = 17 + length
for e in self do
res = res * 3 / 2
if e != null then res += e.hash
end
return res
end
redef fun iterator: IndexedIterator[E] is abstract
# Gets a new Iterator starting at position `pos`
#
# var iter = [10,20,30,40,50].iterator_from(2)
# assert iter.to_a == [30, 40, 50]
fun iterator_from(pos: Int): IndexedIterator[E]
do
var res = iterator
while pos > 0 and res.is_ok do
res.next
pos -= 1
end
return res
end
# Gets an iterator starting at the end and going backwards
#
# var reviter = [1,2,3].reverse_iterator
# assert reviter.to_a == [3,2,1]
fun reverse_iterator: IndexedIterator[E] is abstract
# Gets an iterator on the chars of self starting from `pos`
#
# var reviter = [10,20,30,40,50].reverse_iterator_from(2)
# assert reviter.to_a == [30,20,10]
fun reverse_iterator_from(pos: Int): IndexedIterator[E]
do
var res = reverse_iterator
while pos > 0 and res.is_ok do
res.next
pos -= 1
end
return res
end
end
lib/core/collection/abstract_collection.nit:831,1--1070,3