지연평가

nn·2023년 6월 23일
0

지연평가

제때 계산법, 느긋한 계산법으로 연산을 미룰 수 있을 때까지 미루었다가 필요한 시점에 값을 만들어 계산하는 것으로 굉장히 영리한 평가 방법이다.

L.map

지연평가는 제너레이터/이터레이터 프로토콜을 기반으로 구현되어야 한다.

L.map = function *(f, iter) {
 for (const a of iter){
 	yield f(a)
 }
}

const it = L.map((a) => a+1, [0,1,2,3,4])

log(...it) ///  1 2 3 4 5

L.filter

L.filter = function*(f, iter){
  for (const a of iter){
    if (f(a)) {
    	yield a;
    }
  }
}

const fi = L.filter((v) => v%2, [1,2,3,4,5,6])
log(...fi) //  1 3 5

L.range, L.map, L.filter, take, reduce 중첩사용

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;
    }
  }
})

curry를 적용해서 리턴되는 함수의 인자가 맞춰질때까지 기다렸다가 실행되도록 했다.

go(
L.range(10000),
L.filter((v) => v %2), 
L.map((v) => v + 10),
take(3),
reduce(add),
log
) /// 200

go(
L.range(10000),
L.map((v) => v + 10),
L.filter((v) => v %2), 
take(3),
reduce(add),
log
) /// 200

이렇게 지연평가가 적용된 함수를 작성하게 되면 이터러블을 처음부터 만들어 놓고 시작하는 것이 아니기때문에 어떤 순서로 결합을 하던 같은 결과가 출력된다.

queryStr

const L.entries = function*(obj){
  for (const a in obj){
  	yield [a, obj[a]];
  }
}
const join = curry((sep=",", iter) => {
	return reduce((a,b)=> ${a}${sep}${b} ,iter)
})

const queryStr = pipe(
  L.entries(obj),
  L.map([k,v]  => ${k}=${v}),
  join('&'))
	
  log(queryStr({ limit: 10, offset: 10, type: 'notice' }));

take, find


const users = [
    { age: 32 },
    { age: 31 },
    { age: 37 },
    { age: 28 },
    { age: 25 },
    { age: 32 },
    { age: 31 },
    { age: 37 }
  ]


const find = curry((f,iter) => {
return go(iter,
         L.filter(f),
          take(1),
          ([v]) => v)
})

console.log(find((users) => users.age < 30)(users)) 
// {age: 28}

go(
users,
find((user) => user.age < 30),
console.log
)
// // {age: 28}



profile
내가 될 거라고 했잖아

0개의 댓글