your programing

'커링'이 무엇인가요?

lovepro 2020. 10. 2. 23:03
반응형

'커링'이 무엇인가요?


여러 기사와 블로그에서 curried 함수에 대한 참조를 보았지만 좋은 설명을 찾을 수 없습니다 (또는 적어도 이해가되는 설명 하나 이상!)


Currying은 여러 인수를 사용하는 함수를 각각 하나의 인수 만 사용하는 일련의 함수로 분해하는 것입니다. 다음은 JavaScript의 예입니다.

function add (a, b) {
  return a + b;
}

add(3, 4); // returns 7

이것은 두 개의 인수 a와 b를 취하고 그 합계를 반환하는 함수입니다. 이제이 함수를 커리합니다.

function add (a) {
  return function (b) {
    return a + b;
  }
}

이것은 하나의 인수 a를 사용하고 다른 인수 b를 사용하는 함수를 반환하는 함수이며 해당 함수는 합계를 반환합니다.

add(3)(4);

var add3 = add(3);

add3(4);

첫 번째 문은 add (3, 4) 문과 같이 7을 반환합니다. 두 번째 문은 인수에 3을 더하는 add3이라는 새 함수를 정의합니다. 이것은 일부 사람들이 클로저라고 부르는 것입니다. 세 번째 문은 add3 연산을 사용하여 3을 4에 더하고 결과적으로 7을 다시 생성합니다.


함수 대수학에서 여러 인수 (또는 N- 튜플 인 동등한 하나의 인수)를 취하는 함수를 처리하는 것은 다소 우아하지 않습니다. 그러나 Moses Schönfinkel (그리고 독립적으로 Haskell Curry)이 증명했듯이 필요하지 않습니다. 하나의 인수를 취하는 함수가 필요합니다.

그래서 자연스럽게 표현되는 것을 어떻게 처리 f(x,y)합니까? 글쎄, 당신은 그것을 f(x)(y)- f(x)라고 부르고 g, 함수 라고 부르고 , 그 함수를 y. 즉, 하나의 인수를받는 함수 만 있지만 이러한 함수 중 일부는 다른 함수를 반환합니다 (또한 하나의 인수를 취하는 함수 ;-).

늘 그렇듯이, 위키피디아 는 이것에 대한 좋은 요약 항목을 가지고 있으며, 많은 유용한 포인터 (아마 좋아하는 언어에 관한 것 포함)와 약간 더 엄격한 수학적 처리가 있습니다.


다음은 구체적인 예입니다.

물체에 작용하는 중력을 계산하는 함수가 있다고 가정합니다. 공식을 모르면 여기에서 찾을 수 있습니다 . 이 함수는 세 가지 필수 매개 변수를 인수로받습니다.

이제 지구에 있으면이 행성의 물체에 대한 힘만 계산하려고합니다. 기능적 언어에서는 지구의 질량을 함수에 전달한 다음 부분적으로 평가할 수 있습니다. 당신이 되찾은 것은 단지 두 개의 인수만을 취하고 지구상의 물체의 중력을 계산하는 또 다른 함수입니다. 이것을 카레라고합니다.


Currying은 함수에 적용하여 이전보다 인수를 하나 더 적게 취할 수 있도록하는 변형입니다.

예를 들어 F #에서는 다음과 같이 함수를 정의 할 수 있습니다.

let f x y z = x + y + z

여기서 함수 f는 매개 변수 x, y 및 z를 취하여 합산합니다.

f 1 2 3

6을 반환합니다.

따라서 정의에서 f :-에 대한 카레 함수를 정의 할 수 있습니다.

let curry f = fun x -> f x

여기서 'fun x-> fx'는 C #의 x => f (x)에 해당하는 람다 함수입니다. 이 함수는 커리하려는 함수를 입력하고 단일 인수취하고 첫 번째 인수가 입력 인수로 설정된 지정된 함수를 반환하는 함수를 반환합니다.

이전 예제를 사용하여 f의 카레를 얻을 수 있습니다.

let curryf = curry f

그런 다음 다음을 수행 할 수 있습니다.

let f1 = curryf 1

f1 yz = 1 + y + z와 동등한 함수 f1을 제공합니다. 이는 다음을 수행 할 수 있음을 의미합니다.

f1 2 3

6을 반환합니다.

이 프로세스는 종종 다음과 같이 정의 될 수있는 '부분 기능 적용'과 혼동됩니다.

let papply f x = f x

하나 이상의 매개 변수로 확장 할 수 있지만, 즉 :-

let papply2 f x y = f x y
let papply3 f x y z = f x y z
etc.

부분 응용 프로그램은 함수와 매개 변수를 취하고 하나 이상의 매개 변수가 필요한 함수를 반환합니다. 앞의 두 예에서 보여 주듯이 표준 F # 함수 정의에서 직접 구현되므로 이전 결과를 얻을 수 있습니다.

let f1 = f 1
f1 2 3

6의 결과를 반환합니다.

결론적으로:-

카레와 부분 기능 적용의 차이점은 다음과 같습니다.

Currying은 함수를 가져와 단일 인수를 받아들이고 첫 번째 인수가 해당 인수로 설정된 지정된 함수를 반환하는 새 함수를 제공합니다. 이를 통해 여러 매개 변수가있는 함수를 일련의 단일 인수 함수로 나타낼 수 있습니다 . 예:-

let f x y z = x + y + z
let curryf = curry f
let f1 = curryf 1
let f2 = curryf 2
f1 2 3
6
f2 1 3
6

부분 함수 응용 프로그램은 더 직접적입니다. 함수와 하나 이상의 인수를 취하고 지정된 n 개의 인수로 설정된 첫 번째 n 개의 인수가있는 함수를 반환합니다. 예:-

let f x y z = x + y + z
let f1 = f 1
let f2 = f 2
f1 2 3
6
f2 1 3
6

기능을 사용하여 다른 기능을 만드는 방법이 될 수 있습니다.

자바 스크립트에서 :

let add = function(x){
  return function(y){ 
   return x + y
  };
};

다음과 같이 호출 할 수 있습니다.

let addTen = add(10);

이것이 실행 10되면는 다음과 같이 전달됩니다 x.

let add = function(10){
  return function(y){
    return 10 + y 
  };
};

즉,이 함수가 반환됩니다.

function(y) { return 10 + y };

그래서 전화 할 때

 addTen();

당신은 정말로 전화하고 있습니다.

 function(y) { return 10 + y };

따라서 이렇게하면 :

 addTen(4)

다음과 같습니다.

function(4) { return 10 + 4} // 14

그래서 우리는 addTen()항상 우리가 전달하는 것에 10을 더합니다. 같은 방식으로 비슷한 함수를 만들 수 있습니다.

let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
let addSeventy = add(70)  // ... and so on...

커리 함수는 첫 번째 인수를 받아들이고 두 번째 인수 등을받는 함수를 반환하도록 재 작성된 여러 인수의 함수입니다. 이를 통해 여러 인수의 함수가 초기 인수 중 일부를 부분적으로 적용 할 수 있습니다.


다음은 Python의 장난감 예제입니다.

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(비 Python 프로그래머가주의를 분산시키지 않도록 +를 통한 연결 만 사용합니다.)

추가 할 편집 :

http://docs.python.org/library/functools.html?highlight=partial#functools.partial을 참조 하십시오 . 또한 Python이이를 구현하는 방식에서 부분 객체와 함수 구분을 보여줍니다.


커링는 호출 함수로부터 변환되는 f(a, b, c)등으로 호출 f(a)(b)(c).

Otherwise currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments.

Literally, currying is a transformation of functions: from one way of calling into another. In JavaScript, we usually make a wrapper to keep the original function.

Currying doesn’t call a function. It just transforms it.

Let’s make curry function that performs currying for two-argument functions. In other words, curry(f) for two-argument f(a, b) translates it into f(a)(b)

function curry(f) { // curry(f) does the currying transform
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}

// usage
function sum(a, b) {
  return a + b;
}

let carriedSum = curry(sum);

alert( carriedSum(1)(2) ); // 3

As you can see, the implementation is a series of wrappers.

  • The result of curry(func) is a wrapper function(a).
  • When it is called like sum(1), the argument is saved in the Lexical Environment, and a new wrapper is returned function(b).
  • Then sum(1)(2) finally calls function(b) providing 2, and it passes the call to the original multi-argument sum.

If you understand partial you're halfway there. The idea of partial is to preapply arguments to a function and give back a new function that wants only the remaining arguments. When this new function is called it includes the preloaded arguments along with whatever arguments were supplied to it.

In Clojure + is a function but to make things starkly clear:

(defn add [a b] (+ a b))

You may be aware that the inc function simply adds 1 to whatever number it's passed.

(inc 7) # => 8

Let's build it ourselves using partial:

(def inc (partial add 1))

Here we return another function that has 1 loaded into the first argument of add. As add takes two arguments the new inc function wants only the b argument -- not 2 arguments as before since 1 has already been partially applied. Thus partial is a tool from which to create new functions with default values presupplied. That is why in a functional language functions often order arguments from general to specific. This makes it easier to reuse such functions from which to construct other functions.

Now imagine if the language were smart enough to understand introspectively that add wanted two arguments. When we passed it one argument, rather than balking, what if the function partially applied the argument we passed it on our behalf understanding that we probably meant to provide the other argument later? We could then define inc without explicitly using partial.

(def inc (add 1)) #partial is implied

This is the way some languages behave. It is exceptionally useful when one wishes to compose functions into larger transformations. This would lead one to transducers.


I found this article, and the article it references, useful, to better understand currying: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

As the others mentioned, it is just a way to have a one parameter function.

This is useful in that you don't have to assume how many parameters will be passed in, so you don't need a 2 parameter, 3 parameter and 4 parameter functions.


As all other answers currying helps to create partially applied functions. Javascript does not provide native support for automatic currying. So the examples provided above may not help in practical coding. There is some excellent example in livescript (Which essentially compiles to js) http://livescript.net/

times = (x, y) --> x * y
times 2, 3       #=> 6 (normal use works as expected)
double = times 2
double 5         #=> 10

In above example when you have given less no of arguments livescript generates new curried function for you (double)


Curry can simplify your code. This is one of the main reasons to use this. Currying is a process of converting a function that accepts n arguments into n functions that accept only one argument.

The principle is to pass the arguments of the passed function, using the closure (closure) property, to store them in another function and treat it as a return value, and these functions form a chain, and the final arguments are passed in to complete the operation.

The benefit of this is that it can simplify the processing of parameters by dealing with one parameter at a time, which can also improve the flexibility and readability of the program. This also makes the program more manageable. Also dividing the code into smaller pieces would make it reuse-friendly.

For example:

function curryMinus(x) 
{
  return function(y) 
  {
    return x - y;
  }
}

var minus5 = curryMinus(1);
minus5(3);
minus5(5);

I can also do...

var minus7 = curryMinus(7);
minus7(3);
minus7(5);

This is very great for making complex code neat and handling of unsynchronized methods etc.


A curried function is applied to multiple argument lists, instead of just one.

Here is a regular, non-curried function, which adds two Int parameters, x and y:

scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3

Here is similar function that’s curried. Instead of one list of two Int parameters, you apply this function to two lists of one Int parameter each:

scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Intscala> second(2)
res6: Int = 3
scala> curriedSum(1)(2)
res5: Int = 3

What’s happening here is that when you invoke curriedSum, you actually get two traditional function invocations back to back. The first function invocation takes a single Int parameter named x , and returns a function value for the second function. This second function takes the Int parameter y.

Here’s a function named first that does in spirit what the first traditional function invocation of curriedSum would do:

scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)(Int) => Int

Applying 1 to the first function—in other words, invoking the first function and passing in 1 —yields the second function:

scala> val second = first(1)
second: (Int) => Int = <function1>

Applying 2 to the second function yields the result:

scala> second(2)
res6: Int = 3

An example of currying would be when having functions you only know one of the parameters at the moment:

For example:

func aFunction(str: String) {
    let callback = callback(str) // signature now is `NSData -> ()`
    performAsyncRequest(callback)
}

func callback(str: String, data: NSData) {
    // Callback code
}

func performAsyncRequest(callback: NSData -> ()) {
    // Async code that will call callback with NSData as parameter
}

Here, since you don't know the second parameter for callback when sending it to performAsyncRequest(_:) you would have to create another lambda / closure to send that one to the function.


Here you can find a simple explanation of currying implementation in C#. In the comments, I have tried to show how currying can be useful:

public static class FuncExtensions {
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return x1 => x2 => func(x1, x2);
    }
}

//Usage
var add = new Func<int, int, int>((x, y) => x + y).Curry();
var func = add(1);

//Obtaining the next parameter here, calling later the func with next parameter.
//Or you can prepare some base calculations at the previous step and then
//use the result of those calculations when calling the func multiple times 
//with different input parameters.

int result = func(1);

참고URL : https://stackoverflow.com/questions/36314/what-is-currying

반응형