개발/Java Script

[JS] Ramda

hojak99 2017. 11. 10. 15:45

Ramda js

람다 대수란?

이론 컴퓨터과학 및 수리논리학에서 함수 정의, 함수 적용, 귀납적 함수를 추상화한 형식 체계이다. - 위키백과

  • 람다 대수는 이름을 가질 필요가 없다. (익명함수)
  • 두 개 이상의 입력이 있는 함수는 최종적으로 1개의 입력만 받는 람다 대수로 단순화 될 수 있다. (커링)

람다의 특징

  1. 익명
    • 보통의 메소드와 달리 이름이 없음
  2. 함수
    • 클래스에 종속되는 메소드와 달리 함수라고 함
  3. 전달
    • 매개변수로 전달이 가능. 또한, 함수를 변수에 저장할 수 있음 (Java 8)
  4. 간결성

Ramda 를 알기 전 간단한 람다 예제


var a = [
    "1",
    "2",
    "3",
    "4",
    "5"
];

var a2 = a.map(function(s){return s.length});   // 람다식
var a3 = a.map(s => s.length);                  // Arrow function 을 사용한 람다식

console.log(a.length);      // 5
console.log(a2);            // 5
console.log(a3);            // 5

커링? (Currying)

커링은 여러 개의 인자를 받는 함수가 있을 때 일부의 인자만 받는 함수를 만드는 기법이다.


// 기존 함수
var plus = function (a, b, c) {
    return a + b + c;
}

Function.prototype.curry = function() {
    var args = [].slice.apply(arguments);
    var self = this;
    return funtion() {
        return self.apply(null, args.concat([].slice.apply(arguments)));
    }
}

var plus_1 = plus.curry(1);
console.log(plus_1(2, 3));  // 6

var plus_2 = plus_1.curry(2);
console.log(plus_2(4));     // 7

var plus_3 = plus.curry(1, 3);
console.log(plus_3(5));     // 9

위와 같은 방식으로 커링을 할 순 있지만 bind()함수를 사용하면 좀 더 깔끔하게, curry method를 prototype 에 추가할 필요 없이 사용할 수 있다.

bind() 함수는 호출 될 때 this 키워드가 제공된 값으로 설정되고, 새 함수가 호출 될 때 해당 value를 미리 채워서 넘겨준다.


var plus_1 = plus.bind(null, 1);
plus_1(2, 3);       // 6

var plus_2 = plus_1.bind(null, 2);
plus_2(4);          // 7

var plus_3 = plus.bind(null, 1, 3);
plus_3(5);          // 9

/*
    참고로 다음 코드는 커링하는 코드가 아니다. 왜냐하면, 커링은 여러 개의 인자를 받는 함수를 일부만 받도록 바꾸는 것이지, 처음부터 하나 씩만 받도록 하는게 아니기 때문이라고 한다.
*/
function multiply(x) {
    return funtion(y) {
        return x * y;
    };
}

multiply(4)(8);     // 32

출처 : https://www.zerocho.com/category/Javascript/post/579236d08241b6f43951af18


Ramda?

Ramdajs 는 함수형 프로그래밍 스타일을 위해 특별히 설계된 라이브러리가 필요했기 때문에, Ramda 는 유저 데이터를 변경시키지 않는 함수형 파이프라인을 쉽게 생성할 수 있도록 만들었다.

We wanted a library designed specifically for a functional programming style, one that makes it easy to create functional pipelines, one that never mutates user data.

다른 점?

Ramda 의 주요 특징들은 다음과 같다.

  • Ramda 는 순수 함수적인 스타일을 강조한다. 불변성과 side-effect 가 없는 함수는 디자인 철학의 핵심이다.
  • Ramda 함수들은 자동적으로 curried 된다. 이렇게 하면 최종 매개변수를 제공하지 않고, 간단하게 기존 함수에서 새 함수로 쉽게 빌드 할 수 있다.
  • Ramda 함수의 매개변수는 커링(currying)에 편리하도록 배열되어 만들어진다. 일반적으로 조작할 데이터는 마지막에 제공된다.

Ramda.js 예제

커링

위에 내용에서 bind() 함수를 이용해 커링을 한다고 했다. Ramda 에서도 커링을 할 수 있는 함수가 존재한다. 바로 R.curry()라는 함수이다.


var formatNames = R.curry(function(first, middle, last) {
    return first + ' ' + middle + ' ' + last;
});

// 'John Paul Jones'
formatNames('John', 'Paul', 'Jones');   

var temp = formatNames('John', 'Paul');
temp('hojak');      // 'John Paul hojak'
temp('laplace');    // 'John Paul laplace'
temp('gwang');      // 'John Pawl gwang'

var temp_1 = formatNames('James');
temp_1('hojak', 'laplace');     // 'James hojak laplace'
var temp_2 = temp_1('gwang');   
temp_2('good');                 // 'James gwang good'
temp_2('nice');                 // 'James gwang nice'

위의 예제에서는 개발자가 직접 정의한 함수에 R.curry를 이용해 커링 할 수 있도록 하지만, Ramda 에서 제공하는 함수에서도 커링이 가능하다.

다음 예제에서 그 함수에 대해 알아보자.


var add = function(a, b) {return a+ b;};
var numbers = [1, 2, 3, 4, 5];

var sum = numbers.reduce(add, 0);           // JS 내장 함수인 reduce : 15
var sumRamda = R.reduce(add, 0, numbers);   // Ramda 에서 제공하는 reduce : 15

// 여기서 R.reduce 는 커링이 되있는 함수이기 때문에 다음과 같이 코드를 작성할 수도 있다.
var total = R.reduce(add ,0);               // returs a funtion
var sumRamdaTest = total(numbers);          // 15


반응형