Property definitions

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