Object.entries
> Object.entries({'a': 10, 'b': 20, 'c': 30})
< (3) [Array(2), Array(2), Array(2)]
[
["a", 10 ],
["b", 20 ],
["c", 30 ]
]
range
인자로 limit
을 받아 limit
만큼의 숫자 배열을 반환
const range = l => {
let i = -1
let res = []
while(++i < l) {
res.push(i)
}
return res
}
log(range(10)) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
take
인자로 limit
과 이터러블을 받아 해당 이터러블을 limit
만큼 잘라서 반환
const take = curry((l, iter) => {
let res = []
for(const a of iter) {
res.push(a)
if(res.length === l) return res
}
return res
})
log(take(5, range(10))) // [0, 1, 2, 3, 4]
사용할 함수 코드
const log = console.log
const curry = f =>
(a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._)
const map = curry((f, iter) => {
let res = []
for(const a of iter) {
res.push(f(a))
}
return res
})
const filter = curry((f, iter) => {
let res = []
for(const a of iter) {
if(f(a)) res.push(a)
}
return res
})
const reduce = curry((f, acc ,iter) => {
if(!iter) {
iter = acc[Symbol.iterator]()
acc = iter.next().value
}
for(const a of iter) {
acc = f(acc, a)
}
return acc
})
const go = (...args) => reduce((a, f) => f(a), args)
const pipe = (f, ...fs) => (...args) => go(f(...args), ...fs)
const take = curry((l, iter) => {
let res = []
for(const a of iter) {
res.push(a)
if(res.length === l) return res
}
return res
})
const range = l => {
let i = -1
let res = []
while(++i < l) {
res.push(i)
}
return res
}
// 지연 평
const L = {}
L.range = function *(l) {
let i = -1
while (++i < l) yield i
}
L.map = curry(function *(f, iter) {
for(const a of iter) {
yield f(a)
}
})
L.filter = curry(function *(f, iter) {
for(const a of iter) {
if(f(a)) yield a
}
})
지연평가
해당 계산이 필요할 때 까지 미뤄 평가하는 것
기존 평가와 지연 평가를 비교해보는 코드를 작성해 보았다.
// 평가
go(
range(10),
map(v => v + 10),
filter(v => v % 2),
take(2),
log
)
// 지연 평가
go(
L.range(10),
L.map(v => v + 10),
L.filter(v => v % 2),
take(2),
log
)
기존 평가의 동작 순서는 다음과 같다.
- range(10) 를 통해 길이가 10인 배열 생성 [0, 1, 2..., 8, 9]
- map을 통해 해당 배열에 10씩을 더한다. [10, 11, 12..., 18, 19]
- filter을 통해 해당 배열의 홀수를 걸러냄 [11, 13, 15, 17, 19]
- take(2) 를 통해 앞에서 2개만 자름 [11, 13]
- log 를 찍음
지연 평가의 동작순서는 다음과 같다.
- range, map, filter 에 이터레이터들은 아직 평가가 되고 있지 않기 때문에 take 함수를 실행
- take 함수에 있는
for of
문으로 인하여 인자로 넘겨 받은 이터레이터 에 next() 가 실행됨 - 이터레이터를 평가하기 위해 filter 함수를 실행
- filter 함수에 있는
for of
문으로 인하여 인자로 넘겨 받은 이터레이터 에 next() 가 실행됨 - 이터레이터를 평가하기 위해 map 함수를 실행
- map 함수에 있는
for of
문으로 인하여 인자로 넘겨 받은 이터레이터 에 next() 가 실행됨 - 이터레이터를 평가하기 위해 range 함수를 실행
- range 함수에서 next() 를 통해서 0을 map 에게 넘겨줌
- map에서 0을 받아 10으로 만든 후 filter에게 넘겨줌
- filter 에서 10은 홀수가 아니므로 false 로 판단해 다음 데이터를 요청
- 위 동작을 반복하면서 filter 에서 참인 값을 take 함수에게 넘겨줌
- take 함수에 조건인 2개의 값이 차면 즉시 함수를 종료하고 채워진 값인 [11, 13] 을 리턴
지연 평가 효율성 비교
console.time("")
go(
range(10000),
map(v => v + 10),
filter(v => v % 2),
take(2),
log
)
console.timeEnd("")
console.time("L")
go(
L.range(10000),
L.map(v => v + 10),
L.filter(v => v % 2),
take(2),
log
)
console.timeEnd("L")
'Study > Today I Learn' 카테고리의 다른 글
[TIL] 2019.04.02 (0) | 2019.04.02 |
---|---|
[TIL] 2019.04.01 (0) | 2019.04.01 |
[TIL] 2019.03.24 (0) | 2019.03.24 |
[TIL] 2019.03.22 (0) | 2019.03.23 |
[TIL] 2019.03.21 (0) | 2019.03.22 |