[JS] memoization, currying
memoization
동일한 계산을 반복해야 할 때 이전 계산 결과를 저장해놓음으로써
효율을 높이는 것. 관례상 변수는 ``js memo[]``
```js
var fibonacci = function ( ) {
var memo = [0, 1];
var fib = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}( );
```
* 클로저를 이용해 ``js memo[]``를 감췄다.
recursive를 사용하지 않고 iteration으로 짜면서 memo하려면 별도의 ``stack`` 변수를 하나 선언하고 거기다가 지나간 memo의 index들을 쌓아 둔 다음, 나중에 stack에서 꺼내면서 한꺼번에 memo를 업데이트하는 그런 로직이 들어가야 하는데 꽤 지저분해진다.
그래서 이런 경우 recursive를 쓰는게 깔끔함.
iteration으로 고치면서 STL같은걸 사용하는 경우 오히려 더 느려질 수 있음. 속도 때문에 바꾸는거면 STL같은걸 쓰지 말아야 함.
이를 일반화하여, 메모이제이션 함수를 만들어 반환하는 함수 ``memoizer``를 정의하면 이렇다.
```js
var memoizer = function (memo, fundamental) {
var shell = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n):
memo[n] = result;
}
return result;
};
return shell;
};
```
* ``memoizer``는 마지막에 ``( )``를 안붙였기 때문에 리턴하게 되는 변수 ``shell``이 아니라 ``js function (memo, fundamental) {...}`` 자체다.
메모이제이션할 함수를 ``fundamental``로 전달하면 그 함수의 메모이제이션 형태를 반환해준다.
이 때 ``js function(shell, n){ return shell( )... }`` 형태로 메모이제이션할 함수(재귀적으로 호출될 함수) ``shell``을 감싸서 전달해야 한다.
```js
var fibonacci = memoizer([0, 1], function (shell, n) {
return shell(n - 1) + shell(n - 2)
});
```
함수형 프로그래밍은 이렇게 함수를 반환하거나 인자로 받을 수 있어, 임의의 함수를 입력으로 받아 다른 함수를 만들어 낼 수 있다는데 강점이 있다.
currying
```js
Function.method('curry', function ( ) {
var slice = Array.prototype.slice,
args = slice.apply(arguments),
that = this;
return function ( ) {
return that.apply(null, args.concat(slice.apply(arguments)));
};
});
```
```js
var sum10 = sum.curry(10);
sum10(5); // 15
```
'JS Stack > JS' 카테고리의 다른 글
[jQuery] checkbox의 check all 기능 구현하기 (0) | 2018.11.30 |
---|---|
[JS] char <> code <> hex / unicode 공백 / Unpack (0) | 2017.06.04 |
[JS] 함수 #2. Call pattern, 생성자 대안(함수형 패턴), 상속 (0) | 2017.05.31 |
[JS] 함수 #1. 유효범위(scope), callback, 클로저(closure), 접근 제어 (0) | 2017.05.31 |
[JS] 객체, 프로토타입, 기본 타입에 기능 추가 (0) | 2017.05.29 |