-
-
Save nephilim/4976804 to your computer and use it in GitHub Desktop.
function curry(fn) { | |
var slice = Array.prototype.slice; | |
var args = slice.call(arguments); | |
// curry.call(obj)의 형태로 호출했을 경우 | |
var self = this; | |
if (typeof(args[0]) != "function") { | |
// 예외 처리 | |
throw { name: "ArgumentException", | |
message: "First argument should be a function" }; | |
} | |
called_args = args.slice(1); | |
return function() { | |
// 명시적으로 self를 지정하지 않고 | |
// this를 사용하면 반환된 함수를 사용하는 scope을 따라간다. | |
args = slice.call(called_args).concat(arguments); | |
// 책에 있는 예제와 달리 captured variable인 self를 전달함 | |
return fn.apply(self, args); | |
}; | |
} | |
var obj = { | |
base: 10, | |
add_to_base: function() { | |
// 인자 개수에 상관없이 동작하느라 좀 길지만, | |
// 결국 base에 인자를 모두 더하는 함수 | |
var args = Array.prototype.slice.call( arguments, 0); | |
sum = this.base; | |
for(var i =0; i < args.length; i++) { | |
sum += args[i]; | |
} | |
return sum; | |
}}; | |
/* | |
var add_to_hundred = curry.call(obj, obj.add_to_base, 90) | |
add_to_hundred(100) | |
> 200 | |
// 책의 예제는 다음과 같아서 실패함 | |
var add_to_hundred = curry.call(null, obj.add_to_base, 90) | |
add_to_hundred(100) | |
> NaN | |
*/ |
@outsideris "네피림 비켜~ 내가 진정한 자바스크립트 닌자야"라고 말하고 있군.
아닌자님과는 이야기한 내용이지만, 레식옹의 방법 또한 다음과 같은 결과가 나옵니다. 이 글타레를 (혹시나) 보시는 분이 있을 까봐 코드를 추가합니다.
var person = { age: 30,
yearsAfter: function( a,b,c) { return this.age + a + b + c; }
}
var yearsAfterTenYearsLater = person.yearsAfter.curry(10);
yearsAfterTenYearsLater(20,30);
// NaN
@outsideris 참고로 "아닌자"라는 발음은 보난자와 상당히 비슷하네요.
var a = function() {return this.age;}
a.curry().apply({age:5})
a.curry().apply({age:7})
아닌자 님의 코드는 다음과 같이 obj의 문맥을 적용할 수 있습니다.
obj.add_to_base.curry(20, 30).call(obj, 40)
// 100
obj.base60 = obj.add_to_base.curry(20, 30)
obj.base60(40)
// 100
개인적으로는 커리된 함수를 obj의 멤버로 지정하는 두 번째 방법이 좋아보입니다. 하지만 해당 문맥에 넣지 않으면 안되고, call/apply를 적용하는 건 애초에 불가능합니다. 이건 var fn = this 때문이기도...
this를 사용하는 레식옹의 코드도 나쁘지 않기는 한데... 어쨌던 제 방법에 레식옹의 function prototype을 적용하는 것은 생각해보지 못했네요, 책의 예제를 벗어나서 생각해본 건 아닌데... (부들부들)
@outsideris 그래도 지구는 돈다 궁시렁 궁시렁 @McTenshi 도와죠
초대 감사합니다. ㅋㅋ
"아닌자"라니 "Non-person" 같군요.
레식옹의 방법은 function의 prototype으로 하지 않았을 때 첫번째 인자가 function인지 검사하는 로직을 구조적으로 해결했다는 것이 참 아름답군요.
그나저나 두 코드가 비슷한걸 보니 네피림님에게서도 닌자의 향기가...
마지막줄에.. +1 입니다.
@nephilim 닌자님의 인술이 더 강력했습니다...
@outsideris 전 닌자가 아니에욧! 어쨌건 제 주장을 이해해 주시니 감사. (하지만 레식옹 코드 보자마자 이야기 했는데... 역시 보고 있지 않았;;; )
@McTenshi '아-닌자'로도 '아닌-자'로도 읽히는 군요. 두 개의 별명을 한 큐에!
Secrets of the JavaScript Ninja에 나온 curry 예제입니다.(비교하면서 얘기해봐도 잼날듯해요.)