람다 라이브러리에 대한 자세한 함수 사용법은 공식문서를 참고한다.
아래 글은 책의 내용 중, 중요한 부분만 간략하게 정리했다.
09-1 람다 라이브러리 소개
ramda 패키지는 compose나 pipe를 사용하는 함수 조합을 쉽게 할 수 있게 설계된 오픈소스 자바스크립트 라이브러리이다.
람다 라이브러리는 순수 함수를 고려해 설계었고, 람다 라이브러리가 제공하는 함수들은 항상 입력 변수의 상태를 변화시키지 않고 새로운 값을 반환한다.
- 타입스크립트 언어와 100% 호환
- compose와 pipe 함수 제공
- 자동 커리 기능 제공
- 포인트가 없는 고차 도움 함수 제공
- 조합 논리 함수 일부 제공
- 하스켈 렌즈 라이브러리 기능 일부 제공
- 자바스크립트 표준 모나드 규격과 호환
09-2 람다 기본 사용법
R.compose 함수
R.compose 함수를 사용해 함수를 조합한다.
import * as R from 'ramda'
const str = R.toUpper('a')
R.compose(
R.tap(n => console.log(n))
)(str)
// A
R.pipe 함수
R.tap 디버깅용 함수는 2차 함수 형태로 현재 값을 파악할 수 있게 해 준다.
R.pipe 함수를 사용해 함수를 조합한다.
import * as R from 'ramda'
const array: number[] = R.range(1, 10)
R.pipe(
R.tap(n => console.log(n))
)(array)
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
자동 커리 이해하기
매개변수가 2개인 일반 함수처럼 사용할 수도 있고,
2차 고차 함수로 만들어 사용할 수도 있다.
import * as R from 'ramda'
console.log(
R.add(1, 2), // 3
R.add(1)(3) // 4
)
09-3 배열에 담긴 수 다루기
사칙 연산 함수
import * as R from 'ramda'
console.log(R.add(1)(2)) // 3
console.log(R.subtract(1)(2)) // -1
console.log(R.multiply(1)(2)) // 2
console.log(R.divide(1)(2)) // 0.5
09-4 서술자와 조건 연산
수의 크기를 판단하는 서술자
lt : a < b 이면 true
lte : a<=b 이면 true
gt : a>b 이면 true
gte : a>=b 이면 true
import * as R from 'ramda'
console.log(R.lt(1)(2)) // true
console.log(R.lte(1)(2)) // true
console.log(R.gt(1)(2)) // false
console.log(R.gte(1)(2)) // false
import * as R from 'ramda'
R.pipe(
R.filter(R.lte(3)),
R.tap(n => console.log(n))
)(R.range(1, 10))
// [3, 4, 5, 6, 7, 8, 9]
R.ifElse 함수
조건 서술자, true일 때 실행할 함수, false일 때 실행할 함수 구조로 되어있다.
import * as R from 'ramda'
const substractOrAdd = R.pipe(
R.map(R.ifElse(
R.lte(5), // a<=b
R.inc,
R.dec
)),
R.tap(n => console.log(n))
)
const result1 = substractOrAdd([1, 2, 3]) // [0, 1, 2]
const result2 = substractOrAdd([6, 7, 8]) // [7, 8, 9]
09-5 문자열 다루기
구분자를 사용해 문자열을 배열로 전환
import * as R from 'ramda'
console.log(R.split(' ')(`Hello World`)) // [ 'Hello', 'World' ]
console.log(R.join(' ')(['Hello World'])) // Hello World
09-6 chance 패키지로 객체 만들기
chance 패키지는 가짜 데이터를 만들어주는 라이브러리이다.
// @ts-ignore
import Chance from 'chance'
const c = new Chance
console.log(c.animal()) // Pigs and Hogs
console.log(c.color()) // #236e2d
console.log(c.sentence()) // Egoemu buzok el cawefwu vipur kokjuwcek ko hinhelci seal ho deunuda amuw fuvaer urbo ju.
09-7 렌즈를 활용한 객체의 속성 다루기
렌즈란?
렌즈(lens)는 하스켈 언어의 Control.Lens 라이브러리 내용 중 자바스크립트에서 동작할 수 있는 게터(getter)와 세터(setter) 기능만을 람다 함수로 구현한 것이다.
복잡한 객체(depth가 깊은 구조)를 다룰 때 유용하다.
R.prop 함수
특정 속성값을 가지고 오고, 이를 게터(getter)라고 한다.
import * as R from 'ramda'
const person = {name: '보라돌이'}
const name = R.pipe(
R.prop('name'),
R.tap(name => console.log(name))
)(person)
// 보라돌이
R.assoc 함수
특정 속성값을 변경하고, 이를 세터(setter)라고 한다.
import * as R from 'ramda'
const person = {name: '보라돌이'}
const name = R.pipe(
R.assoc('name', '뚜비'),
R.tap(name => console.log(name))
)(person)
// { name: '뚜비' }
R.lens 함수
타입스크립트에서 동작하게 하려면 제네릭 타입으로 선언해주어야 한다.
import * as R from 'ramda'
const xLens = R.lens(R.prop('x'), R.assoc('x'))
R.view(xLens, {x: 1, y: 2}) // 1
R.set(xLens, 3, {x: 1, y: 2}) // {x: 3, y: 2}
R.over(xLens, R.negate, {x: 1, y: 2}) // {x: -1, y: 2}
R.lensIndex 함수
지정된 인덱스 값을 반환한다.
import * as R from 'ramda'
const headLens = R.lensIndex(0)
R.view(headLens, ['a', 'b', 'c']) // 'a'
R.set(headLens, 'x', ['a', 'b', 'c']) // ['x', 'b', 'c']
R.over(headLens, R.toUpper, ['a', 'b', 'c']) // ['A', 'b', 'c']
R.lensPath 함수
지정된 경로의 값을 반환한다.
import * as R from 'ramda'
const xHeadYLens = R.lensPath(['x', 0, 'y']);
R.view(xHeadYLens, {x: [{y: 2, z: 3}, {y: 4, z: 5}]}) // 2
R.set(xHeadYLens, 1, {x: [{y: 2, z: 3}, {y: 4, z: 5}]}) // {x: [{y: 1, z: 3}, {y: 4, z: 5}]}
R.over(xHeadYLens, R.negate, {x: [{y: 2, z: 3}, {y: 4, z: 5}]}) // {x: [{y: -2, z: 3}, {y: 4, z: 5}]}
R.lensProp 함수
지정된 속성의 값을 반환한다.
import * as R from 'ramda'
const xLens = R.lensProp('x')
R.view(xLens, {x: 1, y: 2}) // 1
R.set(xLens, 4, {x: 1, y: 2}) // {x: 4, y: 2}
R.over(xLens, R.negate, {x: 1, y: 2}) // {x: -1, y: 2}
09-8 객체 다루기
R.key와 R.value 함수
import * as R from 'ramda'
const obj = {name: 'Jae', age: 10}
const key = R.keys(obj)
const value = R.values(obj)
console.log(key) // [ 'name', 'age' ]
console.log(value) // [ 'Jae', 10 ]
09-9 배열 다루기
R.map 함수
import * as R from 'ramda'
const array = [1, 2, 3]
console.log(R.map(item => item * 2, array)) // [ 2, 4, 6 ]
R.filter 함수
import * as R from 'ramda'
const array = [1, 2, 3]
console.log(R.filter(item => item % 2 === 0, array)) // [2]
R.sort 함수
import * as R from 'ramda'
const sortArr = R.sort((a: number, b: number): number => a - b)
console.log(sortArr([3, 5, 1, 7, 9])) // [ 1, 3, 5, 7, 9 ]
R.sortBy 함수
import * as R from 'ramda'
const persons = [
{ name: '보라돌이', age: 10},
{ name: '뚜비', age: 5},
{ name: '나나', age: 15},
{ name: '뽀', age: 1},
]
const nameSort = R.sortBy(R.prop('name'))(persons)
const ageSort = R.sortBy(R.prop('age'))(persons)
console.log(nameSort)
// [
{ name: '나나', age: 15 },
{ name: '뚜비', age: 5 },
{ name: '보라돌이', age: 10 },
{ name: '뽀', age: 1 }
]
console.log(ageSort)
// [
{ name: '뽀', age: 1 },
{ name: '뚜비', age: 5 },
{ name: '보라돌이', age: 10 },
{ name: '나나', age: 15 }
]
09-10 조합 논리 이해하기
조합자란?
조합 논리학은 '조합자(combinator)'라는 특별한 형태의 고차 함수들을 결합해 새로운 조합자를 만들어 내는 것입니다.
R.chain 함수
import * as R from 'ramda'
const arr = [1, 2, 3]
const chain = R.pipe(
R.chain(n => [n, n])
)(arr)
console.log(chain) // [ 1, 1, 2, 2, 3, 3 ]
참고자료
Do it! 타입스크립트 프로그래밍
'TypeScript' 카테고리의 다른 글
[타입스크립트] 10장 제네릭 프로그래밍 (0) | 2023.07.11 |
---|---|
[타입스크립트] 08장 함수 조합의 원리와 응용 (0) | 2023.06.26 |
[타입스크립트] 07장 Promise와 async/await 구문 (0) | 2023.06.19 |
[타입스크립트] 06장 반복기와 생성기 (0) | 2023.06.12 |
[타입스크립트] 05장 배열과 튜플 (0) | 2023.06.07 |