Category talk:Wren-trait: Difference between revisions

→‎Source code: Removed iteration classes following their transfer to Wren-iterate.
(→‎Source code: Improved the robustness of the iteration classes.)
(→‎Source code: Removed iteration classes following their transfer to Wren-iterate.)
Line 34:
==(other) { compare(other) == 0 }
!=(other) { compare(other) != 0 }
}
 
/* Stepped wraps a Sequence so it can be iterated by steps other than 1. */
class Stepped is Sequence {
// Constructs a new stepped sequence.
construct new(seq, step) {
if (!(seq is Sequence)) Fiber.abort("First argument must be a sequence.")
if (!((step is Num) && step.isInteger && step > 0)) {
Fiber.abort("Second argument must be a positive integer.")
}
_seq = seq
_step = step
}
 
// Ensures a range is ascending before passing it to the constructor.
// It it isn't, returns an empty range. Useful when bounds are variable.
static ascend(range, step) {
if (!(range is Range)) Fiber.abort("First argument must be a range.")
return (range.from <= range.to) ? new(range, step) : 0...0
}
 
// Ensures a range is descending before passing it to the constructor.
// It it isn't, returns an empty range. Useful when bounds are variable.
static descend(range, step) {
if (!(range is Range)) Fiber.abort("First argument must be a range.")
return (range.from >= range.to) ? new(range, step) : 0...0
}
 
// Convenience versions of the above methods which call them with a step of 1.
static ascend(range) { ascend(range, 1) }
static descend(range) { descend(range, 1) }
 
// Iterator protocol methods.
iterate(iterator) {
if (!iterator) {
return _seq.iterate(iterator)
} else {
var count = _step
while (count > 0 && iterator) {
iterator = _seq.iterate(iterator)
count = count - 1
}
return iterator
}
}
 
iteratorValue(iterator) { _seq.iteratorValue(iterator) }
}
 
/*
Reversed wraps a Sequence so it can be iterated in reverse
and by steps other than 1. To ensure this always works, non-lists
are converted internally to lists.
*/
class Reversed is Sequence {
// Constructs a new reversed sequence.
construct new(seq, step) {
if (!(seq is Sequence)) Fiber.abort("First argument must be a sequence.")
if (!((step is Num) && step.isInteger && step > 0)) {
Fiber.abort("Second argument must be a positive integer.")
}
_seq = (seq is List) ? seq : seq.toList
_step = step
}
 
// Convenience method which calls the constructor with a step of 1.
static new(seq) { Reversed.new(seq, 1) }
 
// Iterator protocol methods.
iterate(iterator) {
var it = _seq.iterate(iterator)
if (it == null || it == 0) {
it = _seq.count - 1
} else if (it == false) {
it = _seq.count - 1 - _step
} else {
it = it - 1 - _step
}
return (it >= 0) ? it : false
}
 
iteratorValue(iterator) { _seq.iteratorValue(iterator) }
}
 
/* SeqEntry represents an (index, value) pair for use with the Indexed class. */
class SeqEntry {
// Constructs a new SeqEntry object.
construct new(index, value) {
_index = index
_value = value
}
 
// Properties.
index { _index }
value { _value }
 
// Returns the current instance's string representation.
toString { "%(_index):%(_value)" }
}
 
/*
Indexed wraps a Sequence so its elements can be iterated over
together with their zero-based indices. To ensure this always works, non-lists
are converted internally to lists.
*/
class Indexed is Sequence {
// Constructs a new indexed sequence with a step of 'step' and optionally reversed.
construct new(seq, step, reversed) {
if (!(reversed is Bool)) Fiber.abort("Third argument must be true or false.")
_seq = (seq is List) ? seq : seq.toList
_seq = !reversed ? Stepped.new(_seq, step) : Reversed.new(_seq, step)
}
 
// Constructs a new indexed sequence with a step of 'step' and 'reversed' set to false.
static new(seq, step) { new(seq, step, false) }
 
// Constructs a new indexed sequence with a step of 1 and reversed set to false.
static new(seq) { new(seq, 1, false) }
 
// Iterator protocol methods.
iterate(iterator) { _seq.iterate(iterator) }
 
iteratorValue(iterator) {
return SeqEntry.new(iterator, _seq.iteratorValue(iterator))
}
}
 
9,476

edits