Currying 이란?

  • 다중 인자를 갖는 하나의 함수를 단일 인자를 갖는 여러개의 함수로 변환하는 기법입니다. x = f(a,b,c) => x = i(c), i = h(b), h = g(a) => x = g(a)(b)(c)

코드) 세 수의 곱셈을 currying으로 해봅시다.

function multiply(a,b,c) {
    return a*b*c;
}

function curried_multiply(a){
    return (b) => {
        return (c) => {
            return a*b*c;
        }
    }
}

let result1 = multiply(1,2,3); // 6
let result2 = curried_multiply(1)(2)(3); // 6
  • curried_multiply가 적용되는 방식을 살펴보면 다음과 같다.
    //1. curried_multiply(1)은 아래를 반환. 
    return (b) => {
        return (c) => {
            return a*b*c;
        }
    }
    //2. curried_multiply(1)(2)은 아래를 반환. 
    return (c) => {
        return a*b*c;
    }
    //3. 마지막 curried_multiply(1)(2)(3)이 호출되면 파라미터에 값이 바인딩되며 결과가 나옴.
    return 1*2*3

  • currying의 장점 link
    • 함수 로직이 모듈화되어 각각이 재사용 될 수 있게 합니다
    • 추상화의 여지 제공합니다
    • 관심사를 분리하여 로직을 더 아토믹하게 합니다 (다 비슷한 말이네!)

덧) React-Redux 사용시 hook을 사용하지 않으면 말미에 들어가는 connect()

connect(mapStateToProps, mapDispatchToProps)(MyApp)

표현이 처음엔 생소했는데, 지금 보니 currying을 활용한 함수형 프로그래밍스러운 설계였다는 생각이 드네요.

  • tuple은 immutable, constant size, heterogenous collections of items 이라는 특징을 갖는 타입입니다.
      let pair = ("name", "age");
      let triple = ("hello", 1, true);
    
      Js.log2("pair=>", pair); //pair=> [ 'name', 'age' ]
      Js.log2("triple=>",triple); //triple=> [ 'hello', 1, true ]
    
  • 아래와 같은 destructuring도 가능합니다. 언더스코어(_)는 인자로서 자리는 차지해야하지만 아무값도 전달하고 싶지 않을 때 사용하는 syntax 입니다.
    let (_, second) = pair;
    let (first, _, third) = triple;

    Js.log2("second=>", second); //second=> age
    Js.log2("first=>", first); //first=> hello
    Js.log2("third=>", third); //third=> true
  • 패턴 매칭은 아래처럼 할 수 있습니다.
      let triple = ("hello", 1, true);
    
      let pattern_match = (triple) => {
      switch (triple) {
      | ("hello", 1, false) => print_endline("first");
      | ("none", 1, false) => print_endline("second");
      | (_, _, true) => print_endline("third");
      | (_, _, _) => print_endline("default");
      };
    
      // 어떤 결과가 출력될까요~~!!!
    }
    
  • 모듈은 작은 파일처럼 사용할 수 있고, 타입 정의, let 바인딩, nested 모듈등으로도 활용할 수 있습니다.

  • 원할때마다 Yo! 를 console에 출력하는 간단한 모듈을 만들어서 사용해보겠습니다.

module SayYo = {
  let speak = () => print_endline("Yo!");
};
  • 이상 모듈 파일입니다. yo.re로 저장되어 있습니다.
let test = () => {
    Yo.SayYo.speak();       
}
test();
  • 모듈을 불러와서 테스트할 test_yo.re 파일입니다.
  • 모듈안의 함수나 값을 사용할 때는 단순히 module_name 뒤에 .을 붙이면 됩니다.