Generator
well-formed iterator를 리턴하는, iterable을 생성하는 함수
함수앞에 *
을 붙여 만들고, yield
를 통하여 몇번의 next 로 값을 꺼내줄지 결정
return 값을 줄 수 있음, 하지만 return 값을 순회에 영향을 주지 못함
function *gen () {
yield 1
yield 2
yield 3
return 100
}
let iter = gen()
let iter2 = gen()
log(iter == iter[Symbol.iterator]())
for(const a of iter) log(a)
log(iter2.next()) // {value: 1, done: false}
log(iter2.next()) // {value: 2, done: false}
log(iter2.next()) // {value: 3, done: false}
log(iter2.next()) // {value: 100, done: true}
generator의 이점
자바스크립트에서 모든 iterable은 순회가 가능하다. generator는 iterable 을 생성하는 함수이므로 generator 를 이용하면 거의 모든 값들을 순회가능 하도록 만들수 있다.
Generator 활용
짝수 걸러내기
function *infinity(i = 0) {
while(1) yield i++
}
function *limit(l, iter) {
for(const a of iter) {
yield a
if(a == l) return
}
}
function *even(l = 1){
for(const a of limit(l, infinity(1))){
if(!(a % 2)) yield a
}
}
for(const a of even(8)) log(a)
// 2 4 6 8
map
const map = (f, iter) => {
let res = []
for(const a of iter) {
res.push(f(a))
}
return res
}
log(map(v => v * 2, [1, 2, 3, 4])) // [2, 4, 6, 8]
filter
const filter = (f, iter) => {
let res = []
for(const a of iter) {
if(f(a)) res.push(a)
}
return res
}
log(filter(v => v % 2, function *(){
yield 1
yield 2
yield 3
} ())) // [1, 3]
reduce
const reduce = (f, acc ,iter) => {
if(!iter) {
iter = acc[Symbol.iterator]()
acc = iter.next().value
}
for(const a of iter) {
acc = f(acc, a)
}
return acc
}
log(reduce((a, b) => a + b, 0, [1, 2, 3, 4])) // 10
log(reduce((a, b) => a + b, [1, 2, 3, 4])) // 10
go
const go = (...args) => reduce((a, f) => f(a), args)
go(
0,
a => a+1,
a => a+10,
a => a+100,
log
) // 111
pipe
const pipe = (f, ...fs) => (...args) => go(f(...args), ...fs)
et f1 = pipe(
(a, b) => a + b,
a => a + 1,
log,
)
let f2 = pipe(
a => a + 1,
a => a + 10,
log,
)
f1(1, 2) // 4
f2(1) // 12
'Study > Today I Learn' 카테고리의 다른 글
[TIL] 2019.04.01 (0) | 2019.04.01 |
---|---|
[TIL] 2019.03.30 (0) | 2019.03.30 |
[TIL] 2019.03.22 (0) | 2019.03.23 |
[TIL] 2019.03.21 (0) | 2019.03.22 |
[TIL] 2019.03.20 (0) | 2019.03.20 |