[Functional JS] curry, curryr, reduce
함수형으로 전환하기 (2)
커링, curry, curryr
커링은 함수와 인자를 다루는 기법이다. 함수의 인자를 하나씩 적용해 나가다가 필요한 인자가 모두 채워지면 함수 본체를 실행하는 기법이다.
/* 1. _curry, _curryr */
// 인자로 본체 함수를 받는다.
function _curry(fn) {
return function(a) {
return function(b) {
return fn(a, b);
}
}
}
var add = _curry(function(a, b) {
return a + b;
});
var add10 = add(10);
console.log(add10(5)); // 15
console.log(add(5)(3)); // 8
// 인자를 오른쪽부터 적용해나가는 curryr(curry-right)
function _curryr(fn) {
return function(a, b) {
return arguments.length == 2 ? fn(a, b) : function(b) {return fn(b, a);};
}
}
var sub = _curryr(function(a, b) {
return a - b;
})
console.log(sub(10, 5)); // 5
var sub10 = sub(10);
console.log(sub10(5)); // -5 (5에서 sub10, 즉 5 - 10이 된다.)
/* 2. _get 만들어 좀 더 간단하게 하기 */
// get 함수는 object의 값을 안전하게 참조하려는 데 의미를 지닌다.
function _get(obj, key) {
return obj == null ? undefined : obj[key];
}
var user1 = users[0];
console.log(user1.name); // 'ID' (만약 users[0] 값이 없다면 에러 발생)
console.log(_get(user1, 'name')); // 'ID' (users[0] 값이 없다면 undefined 리턴)
var _get = _curryr(function(obj, key) {
return obj == null ? undefined : obj[key];
})
console.log(_get('name')(user1)); // 'ID'
var get_name = _get('name'); // 커링을 이용해서 이름을 가져오는 함수를 변수로 만들 수 있다.
console.log(get_name(user1)) // 'ID'
reduce
/* _reduce 만들기 */
// Array 클래스의 메서드인 slice를 복사해 놓는다.
var slice = Array.prototype.slice;
// slice 메서드를 이용해서 list를 원하는 개수만큼 잘라내는 함수를 만든다.
function _rest(list, num) {
// call 메서드를 이용해 slice의 this를 list로 만들어준다.
return slice.call(list, num || 1);
}
function _reduce(list, iter, memo) {
// memo 인자에 아무것도 들어오지 않았을 경우 (undefined일 경우)
if(arguments.length == 2) {
memo = list[0];
// list = list.slice(1); // 이렇게 하면 slice 메서드를 쓸 수 있는 array에만 이 함수를 적용할 수 있게 되기 때문에 다형성이 떨어진다.
list = _rest(list); // 이렇게 해야 slice 메서드를 array-like 객체에도 적용할 수 있어서 다형성이 좋아진다.
}
_each(list, function(val) {
memo = iter(memo, val);
})
return memo;
}
console.log(_reduce([1, 2, 3], add, 0)); // 6
console.log(_reduce([1, 2, 3], add)); // 6
console.log(_reduce([1, 2, 3, 4], add)); // 10
console.log(_reduce([1, 2, 3, 4], add, 10)); // 20
댓글남기기