ceylon.language.Measure.ceylon Maven / Gradle / Ivy
"A [[Range]] of adjacent [[Enumerable]] values generated by
a [[first]] element, and a strictly positive [[size]]. The
range includes all values whose offset from `first` is
non-negative and less than the `size`."
see (`class Span`,
`interface Enumerable`)
final serializable
class Measure(first, size)
extends Range()
given Element satisfies Enumerable {
"The start of the range."
shared actual Element first;
"The size of the range."
shared actual Integer size;
"must be nonempty"
assert (size > 0);
string => first.string + ":" + size.string;
last => first.neighbour(size - 1);
longerThan(Integer length) => size > length;
shorterThan(Integer length) => size < length;
lastIndex => size - 1;
rest => size > 1
then Measure(first.successor, size - 1)
else [];
getFromFirst(Integer index)
=> index >= 0 && index < size
then first.neighbour(index)
else null;
increasing => true;
decreasing => false;
iterator()
=> object satisfies Iterator {
variable value count = 0;
variable value current = first;
shared actual Element|Finished next() {
if (count >= size) {
return finished;
}
else if (count++ == 0) {
return current;
}
else {
return ++current;
}
}
string => "(``outer.string``).iterator()";
};
shared actual
{Element+} by(Integer step) {
"step size must be greater than zero"
assert (step > 0);
return step == 1 then this else By(step);
}
class By(Integer step)
satisfies {Element+} {
size => 1 + (outer.size - 1) / step;
first => outer.first;
string => "(``outer``).by(``step``)";
iterator() => object
satisfies Iterator {
variable value count = 0;
variable value current = first;
shared actual Element|Finished next() {
if (count >= size) {
return finished;
}
else if (count++ == 0) {
return current;
}
else {
current = current.neighbour(step);
return current;
}
}
string => "``outer``.iterator()";
};
}
shifted(Integer shift)
=> shift == 0
then this
else Measure(first.neighbour(shift), size);
containsElement(Element x)
=> 0 <= x.offset(first) < size;
shared actual
Boolean includesRange(Range range) {
switch (range)
case (is Measure) {
value offset = range.first.offset(first);
return 0 <= offset <= size - range.size;
}
case (is Span) {
if (range.decreasing) {
return false;
} else {
value offset = range.first.offset(first);
return 0 <= offset <= size - range.size;
}
}
}
shared actual
Boolean equals(Object that) {
if (is Measure that) {
//optimize for another Measure
return that.size == size && that.first == first;
} else if (is Span that) {
return that.increasing &&
that.first == first && that.size == size;
} else {
//it might be another sort of List
return super.equals(that);
}
}
shared actual
Element[] measure(Integer from, Integer length) {
if (length <= 0) {
return [];
} else {
value len = from + length < size
then length
else size - from;
return Measure(first.neighbour(from), len);
}
}
shared actual
Element[] span(Integer from, Integer to) {
if (from <= to) {
if (to < 0 || from >= size) {
return [];
} else {
value len = to < size
then to - from + 1
else size - from;
return Measure(first.neighbour(from), len);
}
} else {
if (from < 0 || to >= size) {
return [];
} else {
value len = from < size
then from - to + 1
else size - to;
return Measure(first.neighbour(to), len).reversed;
}
}
}
shared actual
Element[] spanFrom(Integer from) {
if (from <= 0) {
return this;
} else if (from < size) {
return Measure(first.neighbour(from), size - from);
} else {
return [];
}
}
shared actual
Element[] spanTo(Integer to) {
if (to < 0) {
return [];
} else if (to < size - 1) {
return Measure(first, to);
} else {
return this;
}
}
shared actual void each(void step(Element element)) {
variable value current = first;
variable value count = 0;
while (count++|[] measure
(Element first, Integer size)
given Element satisfies Enumerable
=> size <= 0 then [] else Measure(first, size);
© 2015 - 2024 Weber Informatics LLC | Privacy Policy