javascript Es6를 기반으로 하는 함수형 프로그래밍에 대해 배웠다.
함수형 프로그래밍을 처음 배워서 이해하는데 시간이 많이 걸렸다.
내가 생각했을 때 가장 중요한 것은, 어떤 인자가 들어가서 어떤 반환 값이 나오는가를 잘 파악해서 이용해야한다는 것이었다.
어떤 것을 반환하냐에 따라 함수의 실행문이 값이 되거나 함수 자체가 되고,
그 둘은 완전히 다르게 평가되기 때문에 해당 함수가 어떤 것을 반환하는지 잘 파악하고 있어야한다.
함수들을 중첩하고 연속적으로 실행시키면서 하나의 값으로 평가되게 만들어,
마지막 일을 처리하는 식으로 코딩하는 것.
오 -> 왼
왼 -> 오
const products = [
{ name: '반팔티', price: 15000 },
{ name: '긴팔티', price: 20000 },
{ name: '핸드폰케이스', price: 15000 },
{ name: '후드티', price: 30000 },
{ name: '바지', price: 25000 },
];
log(reduce( //2만원 이하의 상품들의 값을 합친 값
add,
map(p => p.price,
filter(p => p.price < 20000, products))));
go, pipe, curry함수로 함수형 프로그래밍 코드의 표현력을 높힐 수 있다.
const go = (...args) => reduce((a, f) => f(a), args);
go (
products, // 시작 liter
products => filter(p => p.price < 20000, products),
products => map(p => p.price, products),
prices => reduce(add, prices),
console.log);
go()
가 실행된다.const pipe = (...fs) => (a) => go(a, ...fs); // 함수를 반환하는 함수
const f = pipe(
a => a + 1,
a => a + 10,
a => a + 100);
console.log(f(0));
--------------------------------------------------
// 초기 값을 함수의 반환 값으로 하고싶다면?
const pipe = (f, ...fs) => (...as) => go(f(...as), ...fs);
const f = pipe(
(a, b) => a + b,
a => a + 10,
a => a + 100);
console.log(f(0,1));
왜 쓰나요?
go, pipe함수를 사용할 때 인자로 들어가는 함수들을 간략하게 만들어 읽기 쉽게 해준다.
const curry = f => (a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._);
const map = curry((f, iter) => { // 함수를 할당할 때 query에 한 번 싸아서 넣는다
let res = [];
for (const a of iter) {
res.push(f(a));
}
return res
});
// filter, map, reduce를 curry의 인수에 넣었다고 할 때,
// 1단계
go (
products, // 시작 liter
products => filter(p => p.price < 20000, products),
products => map(p => p.price, products),
prices => reduce(add, prices),
console.log);
// 2단계
go(
products,
products => filter(p => p.price < 20000)(products),
filteredProducts => map(p => p.price)(filteredProducts),
prices => reduce(add, prices)(prices),
console.log);
// 3단계
// 인자 리스트로 함수가 들어가 있으면 자동적으로
// 인자가 들어가고 결과 값 반환되어 다음 함수의 인자로 넘겨진다
go(
products,
filter(p => p.price < 20000), // (..._) => f(p => p.price < 20000, ..._)와 같다
map(p => p.price)
reduce(add, prices),
console.log);
중복되는 함수들을 또 하나의 함수로 만들어 효율적으로 사용할 수 있다.
const pipe = (...fs) => (a) => go(a, ...fs);
const totalPrice = pipe(
map(p => p.price,
reduce(add, prices)
)
const baseTotalPrice = predi => pipe(
filter(predi),
totalPrice,
)
go(
products,
baseTotalPrice(p => p.price < 20000),
console.log);
go(
products,
baseTotalPrice(p => p.price >= 20000),
console.log);
기존 함수들을 조합해 새로운 함수로 만들 때,
기존 함수를 그대로 사용하고 싶으면
→ 변수에 그대로 넣어서 사용한다.
기쫀 함수를 바꿔서 사용하고 싶으면
→ 해당 함수를 리턴하는 새로운 함수를 만들어서 할당하는데, 인자를 받아서 그 인자로 리턴하는 함수를 조작한다.
강의를 듣는 초반에는 쉽다고 생각했는데 뒤로 갈수록 뇌에 혼란이 왔다.
go, pipe도 그렇지만 특히 curry...
함수형 프로그래밍이 볼 때는 간략하고 쉬워보이지만 그렇게 만들기 위한 과정이 굉장히 어렵고 복잡하다는 것을 느꼈다.
1주차 과제를 풀 때 자료구조에 대해 완전히 이해하지 못했어서 결과가 만족스럽지 못했기 때문에, 2주차 때에는 개념과 원리를 완벽히 이해하고 과제를 구현하고 싶었다. 하지만 모든 걸 다 이해하고 넘어가려다보니 시간이 너무 소요됐다.
과제 기한이 정해져있기 때문에 어느 정도 융통성있게 학습하면서 시간 관리를
해야겠다는 생각이 들었다.