'Currying'이란 무엇입니까?


652

여러 기사와 블로그에서 커리 함수에 대한 참조를 보았지만 좋은 설명 (또는 적어도 의미가있는 설명)을 찾을 수 없습니다!


12
[수학자가 아닌 사람들에게는 쓸모가 없으므로 주석으로 남겨둔다.] 직교 폐쇄 범주의 정의에 따라 X-> X x A와 X 사이 에는 고정 된 계열의 부속물 (자연적으로 A로 매개 변수화 됨)이있다 - "X ^ 답 isomorphisms의 HOM (X X A, Y) <-> HOM (X, Y ^ A)는 아르 curryuncurry하스켈 기능한다. 여기서 중요한 것은 이러한 동형이 사전에 고정되어 있으므로 언어에 "내장"되어 있다는 것입니다.
Alexandre C.

3
거기에 좋은 자습서는 여기 하스켈 무두질을위한 learnyouahaskell.com/higher-order-functions#curried-functions 간단한 코멘트 즉 add x y = x+y(카레)에 다른 add (x, y)=x+y(uncurried)
Jaider

답변:


872

카레는 여러 인수를 하나의 인수 만 취하는 일련의 함수로 나누는 함수를 세분화하는 것입니다. 다음은 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을 다시 생성합니다.


235
실용적인 의미에서이 개념을 어떻게 활용할 수 있습니까?
딸기

43
@Strawberry, 예를 들어 [1, 2, 3, 4, 5]임의의 숫자를 곱하려는 숫자 목록이 있다고 가정하십시오. Haskell에서는 map (* 5) [1, 2, 3, 4, 5]전체 목록에을 곱하여 목록 5을 생성하도록 작성할 수 있습니다 [5, 10, 15, 20, 25].
nyson

62
지도 기능이 무엇인지 이해하지만 설명하려는 요점을 이해하는지 잘 모르겠습니다. 지도 기능은 카레의 개념을 나타냅니다.
Strawberry

78
@Strawberry 첫 번째 인수 map는 하나의 인수 (목록의 요소) 만 취하는 함수 여야합니다. 수학적 개념으로서의 곱셈은 이항 연산입니다. 2 개의 인수가 필요합니다. 그러나 Haskell 에는이 답변 *의 두 번째 버전과 비슷한 카레 기능 add이 있습니다. 그 결과는 (* 5)하나의 인수를 취하고 5를 곱한 함수이며 map과 함께 사용할 수 있습니다.
Doval

26
@Strawberry Standard ML 또는 Haskell과 같은 기능적 언어에 대한 좋은 점은 "무료"카레를 얻을 수 있다는 것입니다. 다른 언어에서와 같이 다중 인수 함수를 정의 할 수 있으며 많은 람다를 던질 필요없이 자동으로 카레 버전을 얻을 수 있습니다. 따라서 많은 번거 로움이나 번거 로움없이 기존 함수의 인수를 덜받는 새로운 함수를 생성 할 수 있으므로 다른 함수에 쉽게 전달할 수 있습니다.
Doval

125

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

그렇다면 자연스럽게 표현한 것을 어떻게 다룰 f(x,y)까요? 자, 당신은 그것을 f(x)(y)- 와 동등한 것으로 간주하고 f(x)그것을 호출 g하고 함수이며, 그 함수를에 적용합니다 y. 다시 말해서, 당신은 하나의 인수를 취하는 함수만을 가지고 있지만, 그 함수 중 일부는 다른 함수를 반환합니다 (또한 하나의 인수를받습니다 ;-).

평소와 같이 wikipedia 에는 이것에 대한 멋진 요약 항목이 있으며, 많은 유용한 포인터 (아마도 좋아하는 언어에 대한 포인터 포함);와 약간 더 엄격한 수학적 처리가 있습니다.


1
위의 내용과 비슷한 의견이 있다고 가정합니다. 기능 언어가 함수를 단일 인수로 제한하는 것을 보지 못했습니다. 내가 착각 했니?
Eric M

1
@hoohoo : 함수형 언어는 일반적으로 함수를 단일 인수로 제한하지 않습니다. 그러나 수학 수준이 낮을수록 하나의 인수 만 취하는 함수를 다루기가 훨씬 쉽습니다. (예를 들어 람다 미적분학에서 함수는 한 번에 하나의 인수 만 취합니다.)
Sam DeFabbia-Kane

1
확인. 그때 또 다른 질문입니다. 다음은 진실한 진술입니까? 람다 미적분학은 함수형 프로그래밍의 모델로 사용될 수 있지만 함수형 프로그래밍은 람다 미적분학이 반드시 적용되는 것은 아닙니다.
Eric M

7
위키피디아 페이지에서 알 수 있듯이, 대부분의 FP 언어는 단순히 "적용"하는 것이 아니라 "일부"또는 "증강"람다 미적분학 (예 : 일부 상수 및 데이터 유형)이지만 가깝지는 않습니다. BTW, Haskell이 "단일 인수를 취하는 기능을 제한하지 않는다"는 인상을주는 것은 무엇입니까? 물론 카레 덕분에 관련이 없습니다. 예를 들어 div :: Integral a => a -> a -> a-여러 개의 화살표를 주목하십시오. "a를 a로 맵핑하는 함수 a"는 한 번의 읽기 ;-)입니다. 당신은 의 (단일) 튜플 인수 사용 div& C를,하지만 하스켈 정말 안티 관용적 될 것이다.
Alex Martelli

@Alex-wrt Haskell & arg count, 나는 Haskell에 많은 시간을 소비하지 않았으며, 그것은 몇 주 전이었습니다. 따라서 만들기 쉬운 오류였습니다.
Eric M

100

구체적인 예는 다음과 같습니다.

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

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


2
호기심으로 JavaScript 용 프로토 타입 라이브러리는 여기에서 설명한 것과 거의 동일한 "카레"기능을 제공합니다. prototypejs.org/api/function/curry
shuckster

새로운 프로토 타입 JS 카레 기능 링크. prototypejs.org/doc/latest/language/Function/prototype/curry/…
Richard Ayotte

7
이것은 나에게 부분적으로 적용되는 것처럼 들립니다. 카레를 적용하면 하나의 인수로 함수를 만들고 더 복잡한 함수를 구성하도록 작성할 수 있습니다. 뭔가 빠졌습니까?
neontapir

9
@neontapir가 정확합니다. 시어가 말한 것은 카레가 아닙니다. 부분 적용입니다. 3 인수 함수가 커리되어 f (1)이라고 부르면, 2 인수 함수가 아닙니다. 다른 1 인수 함수를 리턴하는 1 인수 함수를 다시 얻습니다. 커리 함수에는 인수가 하나만 전달 될 수 있습니다. PrototypeJS의 카레 기능도 카레가 아닙니다. 부분 적용입니다.
MindJuice

아니오 (부분 평가) 및 아니오 (카레). 이것을 부분 응용 프로그램이라고합니다. 이를 가능하게하려면 커링이 필요합니다.
Will Ness

47

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

그렇다면 C #의 메소드는 부분적으로 적용되기 전에 커리되어야합니까?
cdmckay

"이것은 여러 매개 변수가있는 함수를 일련의 단일 인수 함수로 표현할 수있게 해줍니다."-완벽합니다. 감사합니다
퍼지 분석

44

함수를 사용하여 다른 함수를 만드는 방법이 될 수 있습니다.

자바 스크립트에서 :

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...

이제 분명한 후속 질문은 왜 지구상에서 그렇게하고 싶습니까? 그것은 열심 인 작업 x + y을 느슨하게 밟을 수있는 작업 으로 바꿉니다 . 즉, 적어도 두 가지 일을 할 수 있습니다 1. 고가의 작업을 캐시합니다. 2. 기능적 패러다임에서 추상화를 얻습니다.

우리의 카레 함수가 다음과 같다고 상상해보십시오.

let doTheHardStuff = function(x) {
  let z = doSomethingComputationallyExpensive(x)
  return function (y){
    z + y
  }
}

이 함수를 한 번 호출 한 다음 많은 곳에서 사용하기 위해 결과를 전달할 수 있습니다. 즉, 계산적으로 비싼 작업을 한 번만 수행합니다.

let finishTheJob = doTheHardStuff(10)
finishTheJob(20)
finishTheJob(30)

비슷한 방식으로 추상화를 얻을 수 있습니다.


5
여기에서 본 본질적으로 순차적 인 프로세스와 로트에 대한 가장 설명이 가장 좋은 답변을 단계별로 설명하는 가장 좋은 방법입니다.

4
@ jonsilver 나는 좋은 설명이 아니라 그 반대라고 말하고 싶습니다. 나는 그것이 제시된 예를 설명하는 것이 좋다는 데 동의하지만, 사람들은“그렇게 완벽하게 분명하지만 카레가 좋은 것이 다른 방법으로 같은 것을 할 수 있었 을까?”라고 생각하는 경향이 있습니다. 다시 말해서, 나는 카레가 어떻게 작동하는지뿐만 아니라 10을 더하는 다른 방법과 비교하여 쓸모없고 사소한 관찰이 아닌 이유를 조명하기에 충분한 맥락이나 설명이 있었으면 좋겠다.
휘트니 랜드

29

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


5
"이로 인해 여러 인수의 함수가 초기 인수 중 일부를 부분적으로 적용 할 수 있습니다." -왜 유리한가요?
acarlon

5
@acarlon 함수는 종종 하나 이상의 인수를 사용하여 반복적으로 호출됩니다. 예를 들어 목록 목록에 map대해 기능 을 수행하려는 경우 수행 할 수 있습니다 . fxssmap (map f) xss
Jon Harrop

1
감사합니다. 나는 조금 더 독서를했고 그것은 제자리에 떨어졌습니다.
acarlon

4
나는이 대답이 좋은 간결한 방식으로 올바르게 얻는다고 생각합니다. "카레 링"은 여러 인수의 함수를 가져 와서 각각 단일 인수를 가져와 단일 인수의 함수를 리턴하거나 최종 함수의 경우 실제 결과를 리턴하는 심각한 함수로 변환하는 프로세스입니다. . 언어에 의해 자동으로 수행되거나 다른 언어로 된 curry () 함수를 호출하여 카레 버전을 생성 할 수 있습니다. 매개 변수를 사용하여 카레 함수를 호출하는 것은 카레가 아닙니다. 카레는 이미 일어났다.
MindJuice

7

다음은 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이이를 구현하는 방식에서 부분 개체와 기능 구분이 표시됩니다.


나는 이것을 얻지 못한다-당신은 이것을한다 : >>> am_quote = curry (display_quote, "Alex Martelli") 그러나 당신은 이것을 다음에한다 : >>> am_quote ( "currying", "평소와 같이, wikipedia에는 ​​좋은 요약이있다. .. ") 따라서 두 개의 인수가있는 함수가 있습니다. 카레는 당신이 작곡 할 세 가지 다른 펑크를 줄 것 같습니까?
Eric M

매개 변수를 하나만 사용하여 두 개의 인수가있는 함수를 생성하기 위해 partial을 사용하고 있습니다. 원하는 경우 am_quote를 추가로 작성하여 특정 주제에 대해서만 Alex를 인용 한 것을 만들 수 있습니다. 수학 backgound는 하나의 매개 변수로 함수를 끝내는 데 초점을 맞출 수 있습니다. 그러나 이와 같은 여러 매개 변수를 수정하는 것은 일반적으로 (수학적 관점에서 정확하지 않은 경우) 카레라고합니다.
Anon

(btw- '>>>'는 코드의 일부가 아닌 Python 대화식 인터프리터의 프롬프트입니다.)
Anon

args에 대한 설명을 해주셔서 감사합니다. 나는 파이썬 인터프리터 프롬프트에 대해 알고있다. 나는 라인을 인용하려고했지만 작동하지 않았다 ;-)
Eric M

귀하의 의견 후, 나는 여기에 포함하여 "커링"과의 차이점에 대한 다른 참조를 검색하고 발견했습니다. 내가 익숙한 부정확 한 사용법의 많은 인스턴스에 대한 "부분 응용 프로그램". 예를 들어 : stackoverflow.com/questions/218025/…
Anon

5

카레는 함수를 호출 가능에서 f(a, b, c)로 호출 가능으로 변환하고 있습니다 f(a)(b)(c).

그렇지 않으면 카레는 여러 인수를 인수로 사용하는 일련의 함수로 나누는 함수를 분해 할 때 발생합니다.

말 그대로 카레는 한 가지 방식에서 다른 방식으로 호출하는 기능의 변형입니다. JavaScript에서는 일반적으로 원래 기능을 유지하기 위해 래퍼를 만듭니다.

카레는 함수를 호출하지 않습니다. 그것은 단지 그것을 변형시킵니다.

2 인수 함수에 대해 카레를 수행하는 카레 기능을 만들어 봅시다. 다시 말해, curry(f)두 개의 인수 f(a, b)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

보시다시피 구현은 일련의 래퍼입니다.

  • 결과 curry(func)는 랩퍼 function(a)입니다.
  • 처럼 호출되면 sum(1)인수가 Lexical Environment에 저장되고 새 랩퍼가 리턴 function(b)됩니다.
  • 그런 다음 sum(1)(2)마지막으로 function(b)2를 제공하여 호출하면 원래 다중 인수 합계로 호출을 전달합니다.

4

당신이 이해 partial하면 반쯤에 있습니다. 아이디어는 partial함수에 인수를 미리 적용하고 나머지 인수 만 원하는 새 함수를 돌려주는 것입니다. 이 새로운 함수가 호출되면 사전로드 된 인수와 함께 제공된 인수가 포함됩니다.

Clojure에서는 +기능이지만 완전히 명확하게 만드는 기능입니다.

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

inc함수는 전달 된 숫자에 단순히 1을 더한다 는 것을 알고있을 것 입니다.

(inc 7) # => 8

다음을 사용하여 직접 빌드 해 봅시다 partial.

(def inc (partial add 1))

여기서 첫 번째 인수에 1이로드 된 다른 함수를 반환 add합니다. add두 개의 인수를 취하는 것처럼 새 inc함수는 b인수 만 원합니다. 1은 이미 부분적으로 적용 되었으므로 이전과 같이 2 개의 인수는 아닙니다 . 따라서 partial기본값이 사전 제공된 새 기능을 작성하는 도구입니다. 그렇기 때문에 기능적 언어 기능에서 종종 일반에서 특정까지 인수를 주문합니다. 이것은 다른 기능을 구성하기 위해 그러한 기능을 쉽게 재사용 할 수있게합니다.

이제 언어가 내면적으로 이해하기에 충분히 똑똑하여 add두 가지 주장 을 원한다고 상상해보십시오 . Balking 대신 인수 하나를 전달했을 때 함수가 인수를 부분적으로 적용한 경우 나중에 다른 인수를 제공 할 수 있다는 것을 이해하여 인수를 전달한 경우는 어떻게됩니까? 그런 다음 inc을 명시 적으로 사용하지 않고 정의 할 수 partial있습니다.

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

이것은 일부 언어가 작동하는 방식입니다. 함수를 더 큰 변환으로 구성하려고 할 때 매우 유용합니다. 이것은 변환기로 이어질 것입니다.


3

내가 더 잘 무두질 이해하기 위해,이 기사 및 기사 그것을 참조, 유용한 발견 : http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

다른 사람들이 언급했듯이 하나의 매개 변수 기능을 갖는 방법 일뿐입니다.

이것은 몇 개의 매개 변수가 전달 될지에 대해 가정 할 필요가 없으므로 2 개의 매개 변수, 3 개의 매개 변수 및 4 개의 매개 변수 기능이 필요하지 않습니다.


3

다른 모든 답변과 마찬가지로 카레는 부분적으로 적용된 함수를 만드는 데 도움이됩니다. Javascript는 자동 카레를 기본적으로 지원하지 않습니다. 따라서 위에 제공된 예제는 실제 코딩에 도움이되지 않을 수 있습니다. livescript에는 훌륭한 예제가 있습니다 (필수적으로 js로 컴파일하는 것) http://livescript.net/

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

위의 예에서 인수를 적게 줄인 경우 livescript는 새로운 카레 함수를 생성합니다 (이중)


3

카레는 코드를 단순화 할 수 있습니다. 이것이 이것을 사용하는 주된 이유 중 하나입니다. 카레는 n 개의 인수를 허용하는 함수를 하나의 인수 만 허용하는 n 개의 함수로 변환하는 프로세스입니다.

원칙은 클로저 (클로저) 속성을 사용하여 전달 된 함수의 인수를 전달하여 다른 함수에 저장하고이를 반환 값으로 처리하는 것입니다. 이러한 함수는 체인을 형성하고 최종 인수는 전달되어 완성됩니다. 작업.

이것의 장점은 한 번에 하나의 매개 변수를 처리하여 매개 변수 처리를 단순화 할 수 있으며 프로그램의 유연성과 가독성을 향상시킬 수 있다는 것입니다. 또한 프로그램을보다 관리하기 쉽게 만듭니다. 또한 코드를 작은 조각으로 나누면 재사용하기 쉽습니다.

예를 들면 다음과 같습니다.

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

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

나도 할 수있어 ...

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

복잡한 코드를 깔끔하게 만들고 동기화되지 않은 메소드 등을 처리하는 데 매우 좋습니다.


2

커리 함수는 하나가 아닌 여러 인수 목록에 적용됩니다.

다음은 두 가지 Int 매개 변수 x와 y를 추가하는 비 커리 링 된 일반 함수입니다.

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

여기 카레와 비슷한 기능이 있습니다. 두 개의 Int 매개 변수 중 하나의 목록 대신이 함수를 각각 하나의 Int 매개 변수의 두 목록에 적용합니다.

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

여기서 일어나는 것은 호출 할 때 curriedSum실제로 두 개의 전통적인 함수 호출을 연속적으로 받는다는 것입니다. 첫 번째 함수 호출은이라는 단일 Int 매개 변수 x를 사용하고 두 번째 함수의 함수 값을 반환합니다. 이 두 번째 함수는 Int 매개 변수를 사용 y합니다.

다음 first은 최초의 전통적인 함수 호출이하는 일을 정신적으로하는 함수입니다 curriedSum.

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

첫 번째 함수에 1을 적용하면, 즉 첫 번째 함수를 호출하고 1을 전달하면 두 번째 함수가 생성됩니다.

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

두 번째 함수에 2를 적용하면 결과가 나타납니다.

scala> second(2)
res6: Int = 3

2

커링의 예는 기능을 사용할 때 현재 매개 변수 중 하나만 알고 있습니다.

예를 들면 다음과 같습니다.

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
}

콜백을 보낼 때 두 번째 매개 변수를 알지 못하므로 performAsyncRequest(_:)다른 람다 / 클로저를 만들어 함수로 보냅니다.


되는 func callback자체를 반환? 호출되는 것 @ callback(str)그래서 let callback = callback(str), 콜백은 단지 반환 값이다func callback
nikk 웡은

아니오, func callback(_:data:)두 개의 매개 변수를 허용합니다. 여기서는 하나만 제공하므로 다음 매개 변수를 String기다리고 있습니다 ( NSData). 이제 let callback데이터가 전달되기를 기다리는 또 다른 함수입니다.
S2dent

2

다음은 n no로 함수 카레 링을위한 일반 및 가장 짧은 버전의 예입니다. 매개 변수

const add = a => b => b ? add(a + b) : a; 

const add = a => b => b ? add(a + b) : a; 
console.log(add(1)(2)(3)(4)());


1

C #에서 카레 구현에 대한 간단한 설명을 찾을 수 있습니다. 의견에서 나는 카레가 어떻게 유용한 지 보여 주려고 노력했다.

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);

1

카레는 Java Script의 고차 함수 중 하나입니다.

Currying은 많은 인수의 함수로, 첫 번째 인수를 가져 와서 나머지 인수를 사용하고 값을 반환하는 함수를 반환하도록 다시 작성되었습니다.

혼란 스러운가?

예를 보자.

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

이것은 다음과 같은 카레 기능과 유사합니다.

function add(a)
    {
        return function(b){
            return a+b;
        }
    }
var curryAdd = add(5);
curryAdd(6);

이 코드는 무엇을 의미합니까?

이제 정의를 다시 읽으십시오.

Currying은 많은 인수의 함수로 다시 작성되어 첫 번째 인수를 취하고 나머지 인수를 사용하고 값을 반환하는 함수를 반환합니다.

아직도 혼란스러워? 자세히 설명하겠습니다!

이 함수를 호출하면

var curryAdd = add(5);

다음과 같은 함수를 반환합니다.

curryAdd=function(y){return 5+y;}

이를 고차 함수라고합니다. 즉, 한 함수를 차례로 호출하면 다른 함수가 반환됩니다 (고차 함수의 정확한 정의). 이것은 전설 인 Java Script의 가장 큰 장점입니다. 카레로 돌아와서

이 줄은 두 번째 인수를 curryAdd 함수에 전달합니다.

curryAdd(6);

결과적으로

curryAdd=function(6){return 5+6;}
// Which results in 11

카레 사용법을 이해 하시길 바랍니다. 따라서 장점에 도달하면

왜 카레?

코드 재사용 성을 활용합니다. 적은 코드, 적은 오류. 코드가 적은 방법을 물을 수 있습니까?

ECMA 스크립트 6의 새로운 기능 화살표 기능으로이를 증명할 수 있습니다.

예! ECMA 6, 화살표 기능이라는 멋진 기능을 제공합니다.

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

화살표 기능을 사용하여 위의 기능을 다음과 같이 작성할 수 있습니다.

x=>y=>x+y

멋지다?

코드가 적고 버그가 적습니다!

이러한 고차 함수의 도움으로 버그가없는 코드를 쉽게 개발할 수 있습니다.

나는 당신에게 도전합니다!

희망, 당신은 카레가 무엇인지 이해했습니다. 설명이 필요하면 여기에 의견을 남겨주세요.

고마워, 좋은 하루 되세요!


0

"Ceasoning in ReasonML"의 예가 있습니다.

let run = () => {
    Js.log("Curryed function: ");
    let sum = (x, y) => x + y;
    Printf.printf("sum(2, 3) : %d\n", sum(2, 3));
    let per2 = sum(2);
    Printf.printf("per2(3) : %d\n", per2(3));
  };
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.