커링(Curring)
function add(x, y) { var oldx = x, oldy = y; if (typeof oldy === 'undefined') { // 부분적인 적용 return function (newy) { return oldx = newy; } } // 전체 인자를 적용 return x + y; } //테스트 typeof add(5); // "function" add(3)(4); // 7 // 새로운 함수를 만들어 저장 var add200 = add(200); add200(10); // 2010
function add(x, y) { if (typeof y === "undefined") { return function (y) { return x + y; } } // 전체 인자를 적용 return x + y; }여기에는 oldx, oldy가 없는데 원래 x는 암묵적으로 클로저에 저장되어 있고, y는 재사용을 하고 있다.
조금더 범용적인 방식으로 처리할 수 있을까?
어떤 함수라도 부분적인 매개변수를 받는 새로운 함수로 변형할 수 있을까?function flexible_curry(fn) { var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); }; }되게 복잡해 보이는 이유는 단시 arguments가 배열이 아니기 때문이다. slice를 쓰고 싶은데 arguments는 배열처럼 보일 뿐 배열이 아니기 때문에 var slice = Array.prototype.slice로 slice안에 메소드를 넣었다. 그리고는 slice.call(arguments, 1); argument를 배열의 메소드로 배열처럼 사용하는 것이다. 이해가 안된다면
[1, 2, 3, 4, 5].slice(1); // [2, 3, 4, 5] Array.prototpye.slice.call([1, 2, 3, 4, 5], 1);이제 테스트를 해보자
function add(x, y) { return x + y; } function flexible_curry(fn) { var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); }; } var newadd = flexible_curry(add, 5); newadd(5); // 10add(fn)는 클로저로서 값이 휘발성으로 사라지지 않는다. (객체화도 되지 않았는데 어떻게?) 그것이 클로저다. 나중에 좀 더 공부해보도록 하자. 어쨋든 argument에서 첫번째 것만을 잘라내서(slice) sotred_args에 넣기 위해 Array.prototype.slice.call(arguments, 1)을 사용하였다.
그리고 반쪽자리 add(fn)를 반환한다. 그것을 newadd에 넣었고 newadd(5)를 실행하면 더하기를 수행 할 것이다. 여기서 concat은 배열끼리의 접합을 수행한 후, args에 넣는다. 그 후 fn.apply(null, args); 를 실행한다. (apply는 call과 비슷하게 동작하지만 배열을 받는 다는 것을 기억하라. 이 예제에서 apply는 아주 잘 맞는다.)
function multifly(a, b, c, d, e) { return a * b * c * d * e; } function flexible_curry(fn) { var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); }; } flexible_curry(multifly, 1, 2, 3)(5, 5); var a = flexible_curry(multifly, 1.534); a(10, 10, 10, 10); var b = flexible_curry(a, 2, 3); b(6, 7);커링은 엄청난 자유를 준다.
댓글 없음:
댓글 쓰기