[개념잡기] 함수형 프로그래밍 - (9) 마무리
_.js
지금까지 작성한 함수들을 정리해 보려고 한다.
기존에 작성한 코드는 const
를 사용하여 함수를 선언하였는데 호이스팅 관련 문제로 var
로 변경하였다. (다음부터는 어떤 것을 사용할 때 알고 사용해야 겠다는 생각이 들었다.)
curry
함수의 평가시점을 늦춰줌. 2개의 인자가 채워지면 함수를 실행시킴
// curry
var _curry = (fn) => {
return function (a, b) {
return arguments.length == 2 ? fn(a,b) : b => fn(a, b)
}
}
curryr
curry
의 두개의 인자를 따로 받을 때 처리되는 순서를 반대로 해줌
// curryr
var _curryr = (fn) => {
return function (a, b) {
return arguments.length == 2 ? fn(a,b) : b => fn(b, a)
}
}
get
오브젝트에서 원하는 key를 가져옴
// get
var _get = _curryr((obj, key) => {
return obj == null ? undefined : obj[key]
})
filter
특정 배열에서 원하는 값을 걸러냄
// filter
var _filter = _curryr((list, predi) => {
var new_list = []
_each(list, (val) => {
if(predi(val)) {
new_list.push(val)
}
})
return new_list
})
map
특정 배열에서 원하는 값을 배열 형태로 반환
// map
var _map = _curryr((list, mapper) => {
var new_list = []
_each(list, (val) => {
new_list.push(mapper(val))
})
return new_list
})
is object
해당 오브젝트의 type 검사
// is_object
var _is_object = (obj) => {
return typeof(obj) == "object" && !!obj
}
keys
해당 오브젝트의 key 들을 리스트 형태로 반환
// keys
var _keys = (obj) => {
return _is_object(obj) ? Object.keys(obj) : []
}
length
해당 배열의 길이를 반환
// length
var _length = _get("length")
each
해당 오브젝트 순회
// each
var _each = (list, iter) => {
var keys = _keys(list)
for(var i = 0, len = keys.length ; i < len; i++) {
iter(list[keys[i]])
}
}
reduce
해당 오브젝트를 순회하면서 함수에 값을 넣어 리턴값 반환
// reduce
var _reduce = function(list, iter, memo) {
if(arguments.length == 2) {
[memo, ...list] = list
}
_each(list, (val) => {
memo = iter(memo, val)
})
return memo
}
pipe
함수 리스트를 받아 해당 순회하며 실행하는 함수 리턴
// pipe
var _pipe = function() {
var fns = arguments
return function(arg) {
return _reduce(fns, function(arg, fn){
return fn(arg)
}, arg)
}
}
go
pipe
즉시 실행함수
// go
var _go = function() {
[arg, ...fns] = arguments
return _pipe.apply(null, fns)(arg)
}
마무리
이렇게 _.js
의 기본 함수들이 마무리되었다. 함수와 함수가 하는 동작이 잘 연결되었는지 모르겠다. 만약 이상한 부분있으면 피드백바랍니다. 마지막으로 전체 소스이다.
_.js
// curry
var _curry = (fn) => {
return function (a, b) {
return arguments.length == 2 ? fn(a,b) : b => fn(a, b)
}
}
// curryr
var _curryr = (fn) => {
return function (a, b) {
return arguments.length == 2 ? fn(a,b) : b => fn(b, a)
}
}
// getters
var _get = _curryr((obj, key) => {
return obj == null ? undefined : obj[key]
})
// filter
var _filter = _curryr((list, predi) => {
var new_list = []
_each(list, (val) => {
if(predi(val)) {
new_list.push(val)
}
})
return new_list
})
// map
var _map = _curryr((list, mapper) => {
var new_list = []
_each(list, (val) => {
new_list.push(mapper(val))
})
return new_list
})
// is_object
var _is_object = (obj) => {
return typeof(obj) == "object" && !!obj
}
// keys
var _keys = (obj) => {
return _is_object(obj) ? Object.keys(obj) : []
}
// length
var _length = _get("length")
// each
var _each = (list, iter) => {
var keys = _keys(list)
for(var i = 0, len = keys.length ; i < len; i++) {
iter(list[keys[i]])
}
}
// reduce
var _reduce = function(list, iter, memo) {
if(arguments.length == 2) {
[memo, ...list] = list
}
_each(list, (val) => {
memo = iter(memo, val)
})
return memo
}
// pipe
var _pipe = function() {
var fns = arguments
return function(arg) {
return _reduce(fns, function(arg, fn){
return fn(arg)
}, arg)
}
}
// go
var _go = function() {
[arg, ...fns] = arguments
return _pipe.apply(null, fns)(arg)
}
'Study > VanillaJS' 카테고리의 다른 글
[개념잡기] 컬렉션 중심 프로그래밍 - (2) 거르기 (filter, reject, compact) (0) | 2019.03.11 |
---|---|
[개념잡기] 컬렉션 중심 프로그래밍 - (1) 수집하기 (map, values, plunk) (0) | 2019.03.11 |
[개념잡기] 함수형 프로그래밍 - (8) 다형성 높이기 (0) | 2019.03.08 |
[개념잡기] 함수형 프로그래밍 - (7) go, pipe (0) | 2019.03.07 |
[개념잡기] 함수형 프로그래밍 - (6) call (0) | 2019.03.06 |