"An implementation of `List` that wraps an `Iterable` of
elements. All operations on this `List` are performed on
the `Iterable`."
by ("Enrique Zamudio")
shared class LazyList<out Element>({Element*} elems)
satisfies List<Element> {
shared actual Integer? lastIndex {
value size = elems.size;
return size > 0 then size-1 else null;
}
shared actual Element? get(Integer index) {
if (index == 0) {
return elems.first;
}
else {
return elems.skipping(index).first;
}
}
shared actual List<Element> rest => LazyList(elems.rest);
shared actual Iterator<Element> iterator() =>
elems.iterator();
"Returns a `List` with the elements of this `List`
in reverse order. This operation will create copy
the elements to a new `List`, so changes to the
original `Iterable` will no longer be reflected in
the new `List`."
shared actual List<Element> reversed =>
elems.sequence.reversed;
shared actual List<Element> clone => this;
shared actual List<Element> span
(Integer from, Integer to) {
if (to < 0 && from < 0) {
return [];
}
Integer toIndex = largest(to,0);
Integer fromIndex = largest(from,0);
if (toIndex >= fromIndex) {
value els = fromIndex > 0
then elems.skipping(fromIndex)
else elems;
return LazyList(els.taking(toIndex-fromIndex+1));
}
else {
//reversed
value seq = toIndex>0
then elems.skipping(toIndex)
else elems;
return seq.taking(fromIndex-toIndex+1)
.sequence.reversed;
}
}
shared actual List<Element> spanTo(Integer to) =>
to<0 then {} else LazyList(elems.taking(to+1));
shared actual List<Element> spanFrom(Integer from) =>
from > 0 then LazyList(elems.skipping(from))
else this;
shared actual List<Element> segment
(Integer from, Integer length) {
if (length > 0) {
value els = from > 0 then elems.skipping(from)
else elems;
return LazyList(els.taking(length));
}
else {
return [];
}
}
shared actual default Boolean equals(Object that) {
if (is List<Anything> that) {
value size = elems.size;
if (that.size==size) {
for (i in 0..size-1) {
value x = this[i];
value y = that[i];
if (exists x) {
if (exists y) {
if (x!=y) {
return false;
}
}
else {
return false;
}
}
else if (exists y) {
return false;
}
}
else {
return true;
}
}
}
return false;
}
shared actual default Integer hash {
variable value hash = 1;
for (elem in elems) {
hash *= 31;
if (exists elem) {
hash += elem.hash;
}
}
return hash;
}
shared default actual Element? findLast(
Boolean selecting(Element elem)) =>
elems.findLast(selecting);
shared actual default Element? first => elems.first;
shared actual default Element? last => elems.last;
}