-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathiterator.ts
executable file
·104 lines (86 loc) · 2.6 KB
/
iterator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// An implementation of the Iterator Helpers proposal. #iterator #rewrite
export class Iterator<T, TReturn = any, TNext = undefined>
implements globalThis.Iterator<T, TReturn, TNext>
{
next: (...args: [] | [TNext]) => IteratorResult<T, TReturn>
return?: (value?: TReturn) => IteratorResult<T, TReturn>
throw?: (e?: any) => IteratorResult<T, TReturn>
constructor(iterator: globalThis.Iterator<T, TReturn, TNext>) {
this.next = iterator.next.bind(iterator)
this.return = iterator.return?.bind(iterator)
this.throw = iterator.throw?.bind(iterator)
}
[Symbol.iterator]() {
return this
}
*take(count: number): Generator<T, TReturn | undefined, TNext> {
let sent: TNext | undefined
for (let i = 0; i < count; i++) {
const { value, done } = this.next(sent!)
if (done) return value
sent = yield value
}
}
drop(count: number): Iterator<T, TReturn, TNext> {
for (let i = 0; i < count; i++) {
const { done } = this.next()
if (done) return this
}
return this
}
*map<U>(fn: (value: T) => U): Generator<U, TReturn, TNext> {
let sent: TNext | undefined
while (true) {
const { value, done } = this.next(sent!)
if (done) return value
yield fn(value)
}
}
*filter(fn: (value: T) => unknown): Generator<T, TReturn, TNext> {
let sent: TNext | undefined
while (true) {
const { value, done } = this.next(sent!)
if (done) return value
if (fn(value)) sent = yield value
}
}
some(fn: (value: T) => unknown): boolean {
while (true) {
const { value, done } = this.next()
if (done) return false
if (fn(value)) return true
}
}
every(fn: (value: T) => unknown): boolean {
while (true) {
const { value, done } = this.next()
if (done) return true
if (!fn(value)) return false
}
}
forEach(fn: (value: T) => void): void {
while (true) {
const { value, done } = this.next()
if (done) return
fn(value)
}
}
reduce(fn: (oldValue: T, value: T) => T): T
reduce<U>(fn: (oldValue: U, value: T) => U, initialValue?: U): U
reduce<U>(fn: (oldValue: U, value: T) => U, initialValue?: U): U {
if (initialValue === undefined) {
const { value, done } = this.next()
if (done) {
throw new Error(
"When initialValue is not passed, the underlying iterator must have at least one element.",
)
}
initialValue = value as any
}
while (true) {
const { value, done } = this.next()
if (done) return initialValue!
initialValue = fn(initialValue!, value)
}
}
}