reject함수는 filter함수를 거꾸로 구현했다고 생각하면 된다.
먼저 _filter함수에 대해 복습해보자.
function _curryr(fn) {
return function(a, b) {
return arguments.length == 2 ? fn(a, b) : function(b) { return fn(b, a); };
}
}
function _is_object(obj) {
return typeof obj == 'object' && !!obj;
}
function _keys(obj) {
return _is_object(obj) ? Object.keys(obj) : [];
}
function _each(list, iter) {
var keys = _keys(list);
for (var i = 0, len = keys.length; i < len; i++) {
iter(list[keys[i]], keys[i]);
}
return list;
}
function _filter(list, predi) {
var new_list = [];
_each(list, function(val) {
if (predi(val)) {
new_list.push(val);
}
});
return new_list;
}
var _filter = _curryr(_filter);
console.log(_filter(users, function(user) { return user.age > 20; }));
filter함수는 조건을 만족시키는 자료를 취합한다면, reject함수는 해당 조건을 만족시키는 자료를 제외하여 취합하는 기능을 가진다.
function _reject(data, predi) {
return _filter(data, function(val) {
return !predi(val);
});
}
console.log( _reject(users, function(user) { return user.age > 30 }); );
underscore.js에서도 사용하고 있는 nagate함수를 이용하여 reject함수를 좀 더 간단하게 구현해보자.
function _nagate(fn) {
return function(val) {
return !fn(val);
}
}
function _reject(data, predi) {
return _nagate(predi));
}
결국 함수들의 응용과 조합을 강조하는 함수형 프로그래밍을 이용한 셈이다.
이번엔 compact함수를 구현해보자.
compact함수는 트루디앙 값만 남기는 함수이다.
(*트루디앙 : if의 조건부에서 true 로 평가되는 값)
function _identity(val) {
return val;
}
var _compact = _filter(_identity);
console.log(
_compact([1, 2, 0, false, null, {}])
);
이렇게 별거 아닌것 같았던 _identity의 함수를 이용하여 다양한 기능을 구현할 수 있게 된다.
앞 전에 만들었던 함수를 이용하여 또 다른 새로운 함수를 만들었다.
이렇게 뚱뚱한 하나의 함수를 만드는 것보다, 여러개의 함수를 만들어 새로운 함수를 조합하여 만드는 것이 프로그래밍에 있어서 훨씬 유리하다는 사례다.