Category talk:Wren-seq: Difference between revisions
Content added Content deleted
(→Source code: Added Lst.sortPart methods.) |
(→Source code: Added View class.) |
||
Line 487: | Line 487: | ||
// Returns the string representation of the underlying list. |
// Returns the string representation of the underlying list. |
||
toString { _stack.toString } |
toString { _stack.toString } |
||
} |
|||
/* View represents a fixed window into a list and behaves for many purposes like a slice. |
|||
However, unlike a slice, it does not create a new list but references the existing one |
|||
which saves memory and reduces pressure on the garbage collector. |
|||
Indexing of the view always starts at 0, and setting/swapping/sorting elements of |
|||
of the view will be reflected in the underlying list and vice versa. However, deletions |
|||
from the underlying list may invalidate the view bounds and insertions may 'move' it. |
|||
As in the case of the List class, views support negative indices. |
|||
*/ |
|||
class View is Sequence { |
|||
// Creates a new View of a list between indices 'start' and 'end' inclusive. |
|||
construct new(lst, start, end) { |
|||
Lst.isList_(lst) |
|||
var c = lst.count |
|||
if (c == 0) Fiber.abort("List cannot be empty.") |
|||
if (start < 0) start = c + start |
|||
if (!(start is Num && start.isInteger && start>= 0 && start < c)) { |
|||
Fiber.abort("'start' is out of range.") |
|||
} |
|||
if (end < 0) end = c + end |
|||
if (!(end is Num && end.isInteger && end >= 0 && end < c)) { |
|||
Fiber.abort("'end' is out of range.") |
|||
} |
|||
if (start > end) { |
|||
Fiber.abort("'end' cannot be before 'start'.") |
|||
} |
|||
_lst = lst |
|||
_start = start |
|||
_end = end |
|||
_count = end - start + 1 |
|||
} |
|||
// Self-evident properties |
|||
primary { _lst } |
|||
start { _start } |
|||
end { _end } |
|||
count { _count } |
|||
// Converts the view to a new independent list. |
|||
toList { _lst[_start.._end] } |
|||
// Gets or sets the value at index 'i' of the view (zero based). |
|||
[i] { (i >= 0) ?_lst[i + _start] : _lst[_count + i + _start] } |
|||
[i]=(v) { |
|||
if (i >= 0) _lst[i + _start] = v else _lst[_count + i + _start] = v |
|||
} |
|||
// Returns the index of 'v' in the view or -1 if it does not exist. |
|||
indexOf(v) { |
|||
for (i in 0..._count) { |
|||
if (_lst[i + _start] == v) return i |
|||
} |
|||
return -1 |
|||
} |
|||
// Returns the last index of 'v' in the view or -1 if it does not exist. |
|||
lastIndexOf(v) { |
|||
for (i in _count-1..0) { |
|||
if (_lst[i + _start] == v) return i |
|||
} |
|||
return -1 |
|||
} |
|||
// Returns whether or not the view contains the value 'v' |
|||
contains(v) { indexOf(v) >= 0 } |
|||
// Swaps the elements at indices 'i' and 'j' in the view. |
|||
swap(i, j) { |
|||
if (i < 0) i = _count + i |
|||
if (j < 0) j = _count + j |
|||
_lst.swap(i + _start, j + _start) |
|||
} |
|||
// Sorts the elements of the view in place using 'comparer' and returns it. |
|||
sort(comparer) { |
|||
Lst.sortPart(_lst, _start, _end, comparer) |
|||
return this |
|||
} |
|||
// Sorts the elements of the view in place using the default comparer and returns it. |
|||
sort() { |
|||
Lst.sortPart(_lst, _start, _end) |
|||
return this |
|||
} |
|||
// Sets all the elements of the view to the value 'v'. |
|||
setAll(v) { |
|||
for (i in _start.._end) _lst[i] = v |
|||
} |
|||
// Checks whether the view bounds are still valid following deletions from the underlying list. |
|||
// If false, do not use unless and until the view becomes valid again. |
|||
isValid { _end < _lst.count } |
|||
// Iteration protocol methods. Note that the indices returned (although not normally exposed) |
|||
// are those into the underlying list not the view itself. |
|||
iterate(iterator) { |
|||
if (!iterator) { |
|||
_taken = 1 |
|||
return _start |
|||
} |
|||
_taken = _taken + 1 |
|||
return _taken > _count ? null : _lst.iterate(iterator) |
|||
} |
|||
iteratorValue(iterator) { _lst.iteratorValue(iterator) } |
|||
// Returns the string representation of the view. |
|||
toString { "[" + _lst.skip(_start).take(_count).join(", ") + "]" } |
|||
}</lang> |
}</lang> |