-
-
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 | |
| */ |
아닌자님과는 이야기한 내용이지만, 레식옹의 방법 또한 다음과 같은 결과가 나옵니다. 이 글타레를 (혹시나) 보시는 분이 있을 까봐 코드를 추가합니다.
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 '아-닌자'로도 '아닌-자'로도 읽히는 군요. 두 개의 별명을 한 큐에!
@outsideris "네피림 비켜~ 내가 진정한 자바스크립트 닌자야"라고 말하고 있군.