함수형 프로그래밍은 가능한 한 가지 의미있는 작업을 하는 순수 함수를 만들고 이 함수들을 조합해서 더 큰 프로그램을 만든다.
함수의 재사용성과 합성을 용이하기 위해 함수는 여러가지 일이 아닌 하나의 일만 제대로 처리하는 것이 중요
const stockItem = (item: Item) :string=> {
const name = item.name;
const price = item.price;
const quantity = item.quantity;
return `이름: ${name}, 가격 : ${price}, 수량 ${quantity}`
}
const outOfStockItem = (item: Item): string => {
const name = item.name;
const price = item.price;
const quantity = item.quantity;
return `이름: ${name} 품절, 가격 : ${price}, 수량 ${quantity}`
}
const item = (item: Item): string => {
if (item.outOfStock) {
return outOfStockItem(item)
} else {
return stockItem(item)
}
}
const totalCnt = (): string => {
let totalCnt = 0;
for (let i = 0; i < cart.length; i++) {
if (!cart[i].outOfStock) {
totalCnt += cart[i].quantity;
}
}
return `전체수량: ${totalCnt}`
}
const totalPrice = (): string => {
let totalPrice = 0;
for (let i = 0; i < cart.length; i++) {
if (!cart[i].outOfStock) {
totalPrice += cart[i].price * cart[i].quantity;
}
}
return `전체수량: ${totalCnt}`
}
그러나 여기까지 만든 item, totalCnt, totalPrice는 순수함수로 보기 어려운데 일종의 전역변수인 cart를 묵시적으로 의존하며 아무런 인자를 받고 있지 않기 때문
각각의 함수에 list인자 받도록 수정 필요, 내부에 for문과 if문 중복되는 부분은 고차함수로 추상화하기
const totalCal = (list: Array<Item>, getValue: (item: Item) => number) => {
// 전체 목록 중 재고가 있는 상품만 getValue를 실행하고 그 값을 모두 더함
list
// 1, 재고가 있는 상품만 분류 - filter
.filter(item => item.outOfStock ===false)
// 2. 분류된 상품에 대해 getValue 실행 - map
.map(getValue)
// 3. getValue가 실행된 값 모두 더하기 - reduce
.reduce((total,value)=> total +value, 0)
// let total = 0
// for (let i = 0; i < list.length; i++) {
// if (!list[i].outOfStock) {
// total += getValue(list[i]);
// }
// }
// return total
}
const totalCnt = (list:Array<Item>): string => {
let totalCnt = totalCal(list, (item)=>item.quantity);
return `전체수량: ${totalCnt}`
}
const totalPrice = (list:Array<Item>):string => {
let totalPrice = totalCal(list, (item)=>item.price);
return `전체수량: ${totalCnt}`
}
const list = (list: Array<Item>) => {
// 목록에 있는 아이템 태그 변경
return `
${list
// 태그 목록을 하나 문자열로 연결
.map(item)
.reduce((tags,tag)=>tags+tag,"")
}`
}
const totalCal2 = (list: Array<Item>, getValue: (item: Item) => number) => {
// 재고가 있는 상품만 getValue를 실행하기 위해 새로운 변수 result추가
const result:Array<number> = []
list.forEach(function (item) {
if (!item.outOfStock) {
result.push(getValue(item))
}
})
return result.reduce((total,value)=> total + value)
}
const suits = ["♠", "♥", "♣", "♦"];
const numbers = [
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K",
"A"
];
const cards: Array<string> = []
// 중첩된 for 구무
for (const suit of suits) {
for (const number of numbers) {
cards.push(suit+number)
}
}
// 우리가 원하는 작업 정리
// 모든 카드 목록 아래의 작업이 완료
const card2=
// 아래의 작업을 모든 무늬에 적용
suits.flatMap((suit)=> // 문자열 배열에 리턴된 함수를 다시 map에 적용해 배열이 중첩된 문자열 리턴
// 아래의 작업을 모든 숫자에 적용
numbers.map((number)=> // 최종적 리턴은 문자열의 배열
// 한장의 카드는 무늬외 숫자를 연결한 문자열
suit + number))
// 무늬별로 나누어진 카드를 하나로 합침
// .flat()
cards
card2