본문 바로가기

웹 프로그래밍/TypeScript

typescript - 람다 라이브러리

●배열에 담긴 수

보통 함수형 프로그래밍은 선언형 프로그래밍 방식으로 코드를 작성함

import * as R from 'ramda'

const numbers: number[] = R.range(1, 9+1)

const incNumbers = R.pipe(
    R.tap(a => console.log('before inc: ', a)),
    R.map(R.inc),
    R.tap(a => console.log('after inc: ', a))
)

const newNumbers = incNumbers(numbers)
before inc:  [
  1, 2, 3, 4, 5,
  6, 7, 8, 9
]
after inc:  [
  2, 3, 4,  5, 6,
  7, 8, 9, 10
]

 

사칙 연산 함수

R.add(x: number)(y: number) // x+y
R.substract(x: number)(b: number) // x-y
R.multiply(x: number)(b: number) // x * y
R.divide(x: number)(b: number) // x / y

 

R.addIndex 함수

Array.map은 두번째 매개변수로 index를 제공하는 반면 R.map은 index 매개변수를 기본으로 제공하지 않는다.

R.map이 Array.map 처럼 동작하려면 R.addIndex 함수를 사용해 R.map이 index를 제공하는 새로운 함수를 만들어야한다.

const indexedMap = R.addIndex(R.map)

이렇게 만들어진 indexedMap은 두 번째 매개변수로 index를 제공함

indexMap((value: number, index: number) => R.add(number)(index))

R.flip 함수

R.add 와 R.multiply와 달리 R.substract와 R.divide는 매개변수의 순서에 따라 결과가 달라진다.

R.flip은 2차 고차 함수의 매개변수 순서를 바꿔준다.

R.substract(1)(2)를 하면 1 - 2를 실행해서 -1이 되지만

R.flip을 이용하면 2 - 1 을 할 수 있다.

import * as R from 'ramda'

const reverseSubstract = R.flip(R.subtract)

const newArray = R.pipe(
    R.map(reverseSubstract(10)), // value - 10
    R.tap(a => console.log(a))
)(R.range(1, 10))
[
  -9, -8, -7, -6, -5,
  -4, -3, -2, -1
]

 

 

서술자와 조건 연산

Array.filter 함수에서 사용되는 콜백 함수는 boolean 타입 값2을 반환해야 하는데, 함수형 프로그래밍에서 boolean 타입 값을 반환하여 어떤 조건을 만족하는지 판단하는 함수를 서술자라고 한다.

 

수의 크기를 판단하는 서술자

R.lt(a)(b): boolean // a < b = true , a가 b보다 작음
R.lte(a)(b): boolean // a <= b = true, a가 b보다 작거나 같음
R.gt(a)(b): boolean // a > b = true, a가 b보다 큼
R.gte(a)(b): bollean // a >= b = true, a가 b보다 크거나 같음

boolean 타입의 값을 반환하는 함수들은 R.allPass와 R.anyPass라는 로직함수를 통해 결합할 수 있음

R.allPass(서술자 배열) // 배열의 조건을 모두 만족하면 true
R.anyPass(서술자 배열) // 배열의 조건을 하나라도 만족하면 true

R.not 함수

입력값이 true이면 false를 반환하고 , false이면 true를 반환하는 함수

 

R.ifElse 함수

3가지 매개변수를 포함한다. 첫 번째는 true, false를 반환하는 서술자, 두 번째는 선택자가 true를 반환할 때 실행할 함수, 세 번째는 선택자가 false를 반환할 때 실행하는 함수이다.

R.isElse(
	조건서술자,
    true일 때 실행하는함수,
    false일 때 실행하는 함수
)

●문자열 다루기

 

문자열 앞뒤의 백색 문자 자르기

R.trim 함수는 문자열의 앞 뒤 공백을 제거해준다.

import * as R  from 'ramda'

const str = '\t hellow world! \n'

console.log(str)
console.log(
    R.trim(str)
)
	 hellow world! 

hellow world!

 

대소문자 전환

R.toLower는 대문자를 모두 소문자로 변환하고, R.toUpper는 소문자를 대문자로 모두 변환한다.

import * as R  from 'ramda'

const str1 = 'hello world!'
const str2 = 'HELLO WORLD'
console.log(R.toUpper(str1))
console.log(R.toLower(str2))
HELLO WORLD!
hello world

 

구분자를 사용해 문자열을 배열로 변환

R.split 함수는 구분자를 사용해 문자열을 배열로 변환시켜줌

문자열 = R.join(구분자)(문자열 배열)
import * as R  from 'ramda'

const word: string[] = R.split(' ')(`Hello, Every one.`) # 공백을 기준으로 분리
console.log(word)
[ 'Hello,', 'Every', 'one.' ]

●렌즈

렌즈는 자바스크립트에서 동작할 수 있는 게터와 세터를 람다 함수로 구현한 것이다.

렌즈 기능을 활용하여 객체의 속성을 얻거나, 설정하는 작업을 쉽게 할 수 있다.

 

R.prop 함수

객체의 특정 속성값을 가져오는 함수.

const name = R.pipe(
    R.prop('name'),
    R.tap(name => console.log(name))
)(Person)

 

R.assoc 함수

객체의 특정 속성값을 변경하는 함수

R.assoc(속성이름, 변경할 내용)(객체)

●객체 다루기

R.toPairs 함수

객체의 속성들을 분해하여 배열로 만들어줌

R.toPairs(객체)

 

R.fromPairs 함수

[키:값] 형태의 아이템을 가진 배열을 다시 객체로 만들어줌

R.fromPairs([키:값]) as 객체타입

R.keys 함수

객체의 속성 이름만 추려서 string[] 타입 배열로 반환함

R.keys(객체)

 

R.values 함수

객체의 속성값만 추려서 any[] 타입 배열로 반환

R.values(객체)

 

R.zipObj 함수

키 배열과 값 배열 두 가지 매개변수를 결합하여 객체로 만들어줌

객체 = R.zipObj(키 배열, 값 배열) as 객체타입

 

R.mergeLeft 함수

두 개의 객체를 입력받아 속성들을 결합하여 새 객체를 생성

속성값이 다를 때 왼쪽 객체의 우선순위가 높음

즉 같은 이름의 속성에 설정된 오른쪽의 값은 무시

객체 = R.mergeLeft(객체1)(객체2)

 

R.mergeRight 함수

두 개의 객체를 입력받아 속성들을 결합하여 새 객체를 생성

속성값이 다를 때 오른쪽 객체의 우선순위가 높음

즉 같은 이름의 속성에 설정된 왼쪽의 값은 무시

객체 = R.mergeLeft(객체1)(객체2)

 

R.mergeDeepLeft, R.mergeDeepRight 함수

R.mergeLeft 함수와 R.mergeRight 함수는 객체의 속성에 담긴 객체를 바꾸지 못한다.

반면 R.mergeDeepLeft 와 R.mergeDeepRight는 객체의 속성에 담긴 객체까지도 변경한다.

객체 = R.mergeDeepLeft(객체1)(객체2)
객체 = R.mergeDeepRight(객체1)(객체2)

 

●배열 다루기

R.prepend, R.append 함수

기존의 배열에 새 아이템을 삽입한 새 배열을 만들어줌.

R.prepend는 배열의 맨 앞에 R.append는 배열의 맨 뒤에 삽입을 함.

새 배열 = R.prepend(값)(배열)
새 배열 = R.append(값)(배열)
import * as R from 'ramda'

const array: number[] = [3, 4]
const prependArray = R.prepend(1)(array)
const appendArray = R.append(1)(array)
console.log(array)
console.log(prependArray)
console.log(appendArray)
[ 3, 4 ]
[ 1, 3, 4 ]
[ 3, 4, 1 ]

 

R.flatten 함수

복잡한 배열을 1차원의 배열로 변경시켜줌.

새 배열 = R.flatten(배열)
import * as R from 'ramda'

const array: number[][] = [[1, 2], [3, 4], [4,  5]]
const flattenArray: number[] = R.flatten(array)
console.log(array)
console.log(flattenArray)
[ [ 1, 2 ], [ 3, 4 ], [ 4, 5 ] ]
[ 1, 2, 3, 4, 4, 5 ]

 

R.unnest 함수

R.flatten 함수보다 좀 더 정교하게 배열을 가공한다.

새로운 배열 = R.unnest(배열)
import * as R from 'ramda'

const array: number[][][] = [[[1, 2]], [[3, 4]], [[4,  5]]]
const unnestArray: number[][] = R.unnest(array)
const unnestArray2: number[] = R.unnest(unnestArray)
console.log(array)
console.log(unnestArray)
console.log(unnestArray2)
[ [ [ 1, 2 ] ], [ [ 3, 4 ] ], [ [ 4, 5 ] ] ]
[ [ 1, 2 ], [ 3, 4 ], [ 4, 5 ] ]
[ 1, 2, 3, 4, 4, 5 ]

 

R.sort 함수

배열을 정렬하여 준다.

첫 번째 매개변수에 콜백 함수를 입력받는다.

배열 = R.sort(콜백 함수)(배열)

R.sort 의 콜백 함수는 다음과 같이 구현해야함.

(a: number, b: number) number => a - b // 마이너스 값이면 오름차순, 0이나 플러스면 내림차순

 

 

R.sortBy 함수

배열에 담긴 아이템이 객체라면 특정 속성값에 따라 정렬해줌, 오름차순으로만 가능

배열 = R.sortBy(객체의 속성을 얻는 함수)(배열)

 

R.sortWiht 함수

R.ascend, R.descend 함수와 함께 사용하여 오름차순, 내림차순 둘 다 가능

 

 

●조합 논리

조합자란?

- 특별한 형태의 고차 함수들을 결합해 새로운 조합자를 만들어내는 것.

 

람다가 제공하는 조합자.

조합자 의미 람다 함수 이름
I identity R.identity
K constant R.always
T thrush R.applyTo
W duplication R.unnest
C flip R.flip
S substitutionm R.ap

 

R.flip 조합자

R.flip은 2차 고차함수의 매개변수 순서를 서로 바꿔주는 역할을 한다.

const flip = cb => a => b => cb(b)(a)

 

R.always 조합자

두 개의 고차 매개변수 중 첫 번째 것을 반환한다.

const always = x => y => x

 

R.applyTo 조합자

값을 첫 번째 매개변수로, 이 값을 입력하는 콜백함수를 두 번째 매개변수로 받는다.

const applyTo = value => cb => cb(value)

 

R.ap 조합자

콜백 함수들의 배열을 첫 번째 매개변수로, 배열을 두 번째 매개변수로 입력받는다.

const ap = ([콜백 함수]) => 배열 => [콜백함수](배열)