forked from Mirror/wren
Added Sequence.take and Sequence.skip
These lazy iterator producing methods are useful when working with arbitrary sequences and you need to skip or take some number of elements at the start.
This commit is contained in:
@ -125,6 +125,23 @@ It is a runtime error to call this on an empty sequence.
|
|||||||
Similar to above, but uses `seed` for the initial value of the accumulator. If
|
Similar to above, but uses `seed` for the initial value of the accumulator. If
|
||||||
the sequence is empty, returns `seed`.
|
the sequence is empty, returns `seed`.
|
||||||
|
|
||||||
|
### **skip**(count)
|
||||||
|
|
||||||
|
Creates a new sequence that skips the first `count` elements of the original
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
The returned sequence is *lazy*. The first `count` elements are only skipped
|
||||||
|
once you start to iterate the returned sequence. Changes to the original
|
||||||
|
sequence will be reflected in the filtered sequence.
|
||||||
|
|
||||||
|
### **take**(count)
|
||||||
|
|
||||||
|
Creates a new sequence that iterates only the first `count` elements of the
|
||||||
|
original sequence.
|
||||||
|
|
||||||
|
The returned sequence is *lazy*. Changes to the original sequence will be
|
||||||
|
reflected in the filtered sequence.
|
||||||
|
|
||||||
### **toList**
|
### **toList**
|
||||||
|
|
||||||
Creates a [list][] containing all the elements in the sequence.
|
Creates a [list][] containing all the elements in the sequence.
|
||||||
|
|||||||
@ -56,6 +56,10 @@ class Sequence {
|
|||||||
|
|
||||||
map(transformation) { MapSequence.new(this, transformation) }
|
map(transformation) { MapSequence.new(this, transformation) }
|
||||||
|
|
||||||
|
skip(count) { SkipSequence.new(this, count) }
|
||||||
|
|
||||||
|
take(count) { TakeSequence.new(this, count) }
|
||||||
|
|
||||||
where(predicate) { WhereSequence.new(this, predicate) }
|
where(predicate) { WhereSequence.new(this, predicate) }
|
||||||
|
|
||||||
reduce(acc, f) {
|
reduce(acc, f) {
|
||||||
@ -112,6 +116,43 @@ class MapSequence is Sequence {
|
|||||||
iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }
|
iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SkipSequence is Sequence {
|
||||||
|
construct new(sequence, count) {
|
||||||
|
_sequence = sequence
|
||||||
|
_count = count
|
||||||
|
}
|
||||||
|
|
||||||
|
iterate(iterator) {
|
||||||
|
if (iterator) {
|
||||||
|
return _sequence.iterate(iterator)
|
||||||
|
} else {
|
||||||
|
iterator = _sequence.iterate(iterator)
|
||||||
|
var count = _count
|
||||||
|
while (count > 0 && iterator) {
|
||||||
|
iterator = _sequence.iterate(iterator)
|
||||||
|
count = count - 1
|
||||||
|
}
|
||||||
|
return iterator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iteratorValue(iterator) { _sequence.iteratorValue(iterator) }
|
||||||
|
}
|
||||||
|
|
||||||
|
class TakeSequence is Sequence {
|
||||||
|
construct new(sequence, count) {
|
||||||
|
_sequence = sequence
|
||||||
|
_count = count
|
||||||
|
}
|
||||||
|
|
||||||
|
iterate(iterator) {
|
||||||
|
if (!iterator) _taken = 1 else _taken = _taken + 1
|
||||||
|
return _taken > _count ? null : _sequence.iterate(iterator)
|
||||||
|
}
|
||||||
|
|
||||||
|
iteratorValue(iterator) { _sequence.iteratorValue(iterator) }
|
||||||
|
}
|
||||||
|
|
||||||
class WhereSequence is Sequence {
|
class WhereSequence is Sequence {
|
||||||
construct new(sequence, fn) {
|
construct new(sequence, fn) {
|
||||||
_sequence = sequence
|
_sequence = sequence
|
||||||
|
|||||||
@ -58,6 +58,10 @@ static const char* coreModuleSource =
|
|||||||
"\n"
|
"\n"
|
||||||
" map(transformation) { MapSequence.new(this, transformation) }\n"
|
" map(transformation) { MapSequence.new(this, transformation) }\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" skip(count) { SkipSequence.new(this, count) }\n"
|
||||||
|
"\n"
|
||||||
|
" take(count) { TakeSequence.new(this, count) }\n"
|
||||||
|
"\n"
|
||||||
" where(predicate) { WhereSequence.new(this, predicate) }\n"
|
" where(predicate) { WhereSequence.new(this, predicate) }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" reduce(acc, f) {\n"
|
" reduce(acc, f) {\n"
|
||||||
@ -114,6 +118,43 @@ static const char* coreModuleSource =
|
|||||||
" iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }\n"
|
" iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"class SkipSequence is Sequence {\n"
|
||||||
|
" construct new(sequence, count) {\n"
|
||||||
|
" _sequence = sequence\n"
|
||||||
|
" _count = count\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(iterator) {\n"
|
||||||
|
" if (iterator) {\n"
|
||||||
|
" return _sequence.iterate(iterator)\n"
|
||||||
|
" } else {\n"
|
||||||
|
" iterator = _sequence.iterate(iterator)\n"
|
||||||
|
" var count = _count\n"
|
||||||
|
" while (count > 0 && iterator) {\n"
|
||||||
|
" iterator = _sequence.iterate(iterator)\n"
|
||||||
|
" count = count - 1\n"
|
||||||
|
" }\n"
|
||||||
|
" return iterator\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iteratorValue(iterator) { _sequence.iteratorValue(iterator) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class TakeSequence is Sequence {\n"
|
||||||
|
" construct new(sequence, count) {\n"
|
||||||
|
" _sequence = sequence\n"
|
||||||
|
" _count = count\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(iterator) {\n"
|
||||||
|
" if (!iterator) _taken = 1 else _taken = _taken + 1\n"
|
||||||
|
" return _taken > _count ? null : _sequence.iterate(iterator)\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iteratorValue(iterator) { _sequence.iteratorValue(iterator) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
"class WhereSequence is Sequence {\n"
|
"class WhereSequence is Sequence {\n"
|
||||||
" construct new(sequence, fn) {\n"
|
" construct new(sequence, fn) {\n"
|
||||||
" _sequence = sequence\n"
|
" _sequence = sequence\n"
|
||||||
|
|||||||
28
test/core/sequence/skip.wren
Normal file
28
test/core/sequence/skip.wren
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
class TestSequence is Sequence {
|
||||||
|
construct new() {}
|
||||||
|
|
||||||
|
iterate(iterator) {
|
||||||
|
if (iterator == null) return 1
|
||||||
|
if (iterator == 3) return false
|
||||||
|
return iterator + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
iteratorValue(iterator) { iterator }
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = TestSequence.new().skip(0)
|
||||||
|
|
||||||
|
System.print(test is Sequence) // expect: true
|
||||||
|
System.print(test) // expect: instance of SkipSequence
|
||||||
|
|
||||||
|
// Skipping 0 changes nothing
|
||||||
|
System.print(test.toList) // expect: [1, 2, 3]
|
||||||
|
|
||||||
|
// Skipping 1 works
|
||||||
|
System.print(test.skip(1).toList) // expect: [2, 3]
|
||||||
|
|
||||||
|
// Skipping more than length of sequence produces empty list
|
||||||
|
System.print(test.skip(4).isEmpty) // expect: true
|
||||||
|
|
||||||
|
// Skipping less than 0 changes nothing
|
||||||
|
System.print(test.skip(-10).toList) // expect: [1, 2, 3]
|
||||||
28
test/core/sequence/take.wren
Normal file
28
test/core/sequence/take.wren
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
class TestSequence is Sequence {
|
||||||
|
construct new() {}
|
||||||
|
|
||||||
|
iterate(iterator) {
|
||||||
|
if (iterator == null) return 1
|
||||||
|
if (iterator == 3) return false
|
||||||
|
return iterator + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
iteratorValue(iterator) { iterator }
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = TestSequence.new().take(3)
|
||||||
|
|
||||||
|
System.print(test is Sequence) // expect: true
|
||||||
|
System.print(test) // expect: instance of TakeSequence
|
||||||
|
|
||||||
|
// Taking 0 produces empty list
|
||||||
|
System.print(test.take(0).isEmpty) // expect: true
|
||||||
|
|
||||||
|
// Taking 1 works
|
||||||
|
System.print(test.take(1).toList) // expect: [1]
|
||||||
|
|
||||||
|
// Taking more than length of sequence produces whole sequence
|
||||||
|
System.print(test.take(4).toList) // expect: [1, 2, 3]
|
||||||
|
|
||||||
|
// Taking less than 0 produces empty list
|
||||||
|
System.print(test.take(-10).isEmpty) // expect: true
|
||||||
Reference in New Issue
Block a user