xtring.dev

[JS] (번역)JavaScript Currying 이해하기⛓ 본문

Front-End/JavaScript

[JS] (번역)JavaScript Currying 이해하기⛓

xtring 2022. 7. 22. 18:14

 

 

 

🕺 원문
https://blog.logrocket.com/understanding-javascript-currying/

 

Understanding JavaScript currying - LogRocket Blog

Learn what currying is in Javascript, why and where you should use currying, and how to implement it with code examples

blog.logrocket.com

 

 

Currying은 람다 계산법 컨셉이지만 걱정할 필요없습니다.(간단합니다!)

 

Currying은 한번에 하나의 인자(argument)를 가지고 다음 인자를 함께 새로운 함수에 반환하는 함수입니다. 함수를 f(a, b, c)로 호출할 수 있는 함수에서 f(a)(b)(c)로 호출할 수 있는 함수로 변환하는 함수의 변환입니다.

 

이 아티클에서 JavaScript에서 Currying이 무엇이며, 왜, 어디에서 당신이 Currying을 사용해야하는지를 탐색해보겠습니다. 그리고 예제로 알아볼게요!

 

 

What is currying in JavaScript?

Currying은 단순히 여러 인자로 함수를 평가하고, 단일 인자로 함수 순서(sequence)를 분해하는 것을 의미합니다.

다시 말해서, 커링은 한 번에 모든 인자를 가지는 함수를 리턴하는 것과 달리 첫 번째 인자를 가지고 새 함수를 반환하고, 두번째 인수가 새로운 함수를 반환하고, 또 세번째 인자를 가진 다음 새 함수를 반환합니다. 이것은 모든 인자가 완료될때까지 실행됩니다.

 

 

Why should I use currying?

Currying이 이상적인 이유는 몇가지가 있습니다.

  • Currying은 실행 전 필요한 것을 모두 얻었는지 확인하는 메소드입니다.
  • 동일한 변수를 재 전달하는 것을 피하는데 도움이 됩니다.
  • 다수의 하나의 책임을 다룰 수 있는 더 작은 함수들로 당신의 함수 쪼갭니다. 이것은 당신의 함수가 순수하고 오류 및 부작용이 적게 만들어 줍니다.
  • Currying은 고차 함수(higher-order function)를 생성하기 위한 함수형 프로그래밍(functional programming)에 사용되곤 합니다.

 

How does currying work?

Currying은 다수의 인자를 받는 함수입니다. 이 함수는 모든 작은 함수가 하나의 인자를 받아들이는 일련의 함수로 변환될 것입니다.

// Noncurried version
const add = (a, b, c)=>{
    return a+ b + c
}
console.log(add(2, 3, 5)) // 10

// Curried version
const addCurry =(a) => {
    return (b)=>{
        return (c)=>{
            return a+b+c
        }
    }
}
console.log(addCurry(2)(3)(5)) // 10

 

JavaScript에서 Currying은 함수를 정의하는 측면에서 약깐 까다로울 수 있지만 구현할수록 분명해질 것입니다.

그래서, 더 많은 코드 예제로 나눠봅시다!

 

 

Example one: A simple, three-parameter function

첫번째로, 나는 세 인자들을 받는 간단한 함수를 생성해보겠습니다.

const add =(a, b, c)=>{
    return a+b+c
}
console.log(add(2, 3, 5)) // 10

이 함수(add)는 10이라는 결과를 리턴합니다.

 

이 함수는 우리가 전달한 숫자의 모든 매개변수를 추가한다는 것입니다.

 

지금, 첫번째 예제는 단순히 다수의 매개변수를 받는 함수입니다.

 

기존 함수를 어떻게 curried version 함수로 변환할 수 있을까요?

 

 

Example two: Converting an existing function into a curried function

두번째 예제를 시도하고 어떻게 우리가 Curry function을 구현할지 봅시다.

 

이 예제에서, 이 함수는 하나의 인자를 받을 것입니다. 그리고 함수들을 순차적으로 반환합니다.

const addCurry =(a) => {
    return (b)=>{
        return (c)=>{
            return a+b+c
        }
    }
}

이는 함수의 curry 수행 방법을 보여줍니다. 출력하면 10이 나옵니다!

console.log(addCurry(2)(3)(5)) // 10

 

첫번째 예제에서 세 개의 인수 a, b, c를 받아들이고 그 합 a + b + c, (2) + (3) + (5)를 더하고 출력을 10으로 반환

addCurry 함수를 만들었습니다. 

 

이 두 번째 예제는 동일한 결과를 보여주는 함수를 구현했지만, 하나의 인자를 가지고 다른 인수 b를 가진 함수를 반환하는 Curry을 사용하여 다른 인자 c를 가지고 함수를 반환하고 해당 함수가 합을 반환하는 방법을 보여주었습니다. 예제 1과 동일한 출력: 10.

 

여기서 우리가 한 것은 중첩된(nested) 함수입니다. 각 함수는 다른 인자를 반환하는 하나의 인수를 취하고 모든 매개변수를 수신할 때까지 함수가 완료되지 않습니다.(순서를 보장한다.)

 

 

Example three: Creating a friend request curry function 

이 예제는 유저가 그의 친구인 John에게 친구 요청을 보내는 간단한 Curry function을 생성할 것입니다.

function sendRequest(greet){
    return function(name){
        return function(message){
            return `${greet} ${name}, ${message}`
        }
    }
}
sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')
// "Hello John, Please can you add me to your Linkedin network?"

 

greet 하나의 인자만 필요한 sendRequest를 만들었습니다.
그리고 이 함수는 사용자의 이름과 사용자에게 보내고 싶은 메시지를 반환합니다. 그런 다음 함수를 호출하면 메시지가 출력됩니다.

 

Basic vs. advanced currying techniques

Basic currying

const getPanCakeIngredients = (ingredient1) =>{
    return (ingredient2) => {
        return (ingredient3) => {
            return ${ingredient1}, ${ingredient2}, ${ingredient3}; 
        } 
    } 
} 
getPanCakeIngredients('Egg')('flour')('milk');
이 코드 예제는 Currying을 구현하는 기본적인 예제입니다.
위 예제에서, getPanCakeIngredients 함수는 하나의 인자로서 ingredient1를 가지고 펜케이크를 만들기 위해 필요한 다른 ingredient들을 가진 일련의 함수들을 반환합니다. 

이 함수는 모든 매개변수를 받기 전까지 완성되지 않습니다. 이는 만약 펜케이크를 위한 ingredient들이 완전하지 않는다면, 이 함수는 좋은 결과를 반환하지 않습니다.

 

Advanced currying

여기에 진화된 currying 코드 예제가 있습니다.

const curry = (fn) =>{
    return curried = (...args) => {
        if (fn.length !== args.length) {
            return curried.bind(null, ...args)
        }
    return fn(...args);
    };
}

const totalNum = (x,y,z) => {
    return x+y+z 
} 

const curriedTotal = curry(totalNum);

console.log(curriedTotal(10) (20) (30));

위 예제에서는 고정된 숫자 매개변수가 필요한 함수를 생성했습니다.

 

외부함수로 함수 curry를 받습니다. 이 함수는 rapper 함수입니다. 먼저, 함수 길이를 비교하고 spread operator(...args)로 인자를 받는 curried 함수와 또 다른 함수를 리턴합니다.

 

함수 길이는 여기에 전달하는 매개변수의 수가 어떻게 되던지 함수의 길이 property에 반영됨을 의미합니다.

 

그러나, 인자는 매번 증가할 것 입니다. 필요한 매개변수의 수가 같지 않으면 Curry를 반환합니다. bind를 호출하면 새 함수가 생성되고 ( ...args)를 전달합니다.

*참고: bind는 새로운 함수를 생성합니다.

 

 

Modern currying with ES6

ES6 arraw function을 사용하는 것으로 currying을 더 모던하고 적은 양의 코드로 구현할 수 있습니다.

const sendRequest = greet => name => message => `${greet} ${name}, ${message}`

sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')
// "Hello John, Please can you add me to your Linkedin network?"

 

 

Currying Can be used to manipulate the DOM in JavaScript

const updateElemText = id => content => document.querySelector(`#${id}`).textContent= content;
const updateHeaderText = updateElemText('header');
updateHeaderText('Hello Samuel!');

// header 엘리먼트에 'Hello Samuel!'이 표현됨

 

 

Currying vs. partial application

이제 Currying이 작동하는 방식을 알았습니다. Currying과 partial application의 차이점은 무엇입니까? 이것은 프로그래머가 계속 묻는 질문 중 하나입니다.

나는 마침내 이 질문에 대한 답을 얻었습니다. 그러나 몇 가지 코드 예제를 사용하여 이 설명을 더 자세히 설명하기 전에 해당 정의에 익숙해지는 것이 가장 좋습니다.

  • Currying: 여러 인자(argument)를 허용하는 함수입니다. 이 함수를 일련의 함수로 변환합니다. 여기서 모든 작은 함수는 모든 인수가 완료될 때까지 단일 인수를 받아들입니다.
  • Partial application: 함수에 예상보다 적은 인수가 주어지면 함수가 부분적으로 적용되고 나머지 인수를 예상하는 새 함수를 반환합니다.(사이드 이펙트가 발생할 수 있다. 순수함수가 되지 않는다.)

 

정의를 아는 것만으로는 차이점을 이해하기에 충분하지 않습니다. 커링이 작동하는 것을 보았지만 다음은 partial application의 예입니다.

const addPartial = (x, y, z) => {
    return x + y + z 
}

const partialFunc= addPartial.bind(this, 2, 3);

partialFunc(5); //returns 10
이것은 curried-version이 아니지만 addPartial 함수를 부분적으로 적용했습니다. 숫자 목록을 추가하고 결과를 반환하는 간단한 함수를 만들었습니다.
*참고: 함수가 전달하는 인자 중 일부가 불완전할 때 함수를 partial application이라고 합니다.
Currying과 partial application은 실제로 다르지 않습니다. 그들은 관련되어 있지만 이론과 응용이 다릅니다.
partial application은 함수를 다른 함수로 변환하지만 arity(함수가 가질 수 있는 인자의 수)는 더 작습니다.
 
 

Conclusion

  • Currying은 Javascript에서 DOM을 조작하는 데 사용할 수 있습니다.
  • 이벤트 리스너를 트리거하는 데 사용할 수 있습니다.
  • 단일 인수만 수신하는 함수를 생성하려는 경우 Currying을 사용할 수 있습니다.

 

 
반응형
Comments