https://ramdajs.com/docs/

람다 라이브러리에 대한 자세한 함수 사용법은 공식문서를 참고한다.

아래 글은 책의 내용 중, 중요한 부분만 간략하게 정리했다.

 

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! 타입스크립트 프로그래밍

+ Recent posts