[functional-programming] ‘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
. 다시 말해서, 당신은 하나의 인수를 취하는 함수만을 가지고 있지만, 그 함수 중 일부는 다른 함수를 반환합니다 (또한 하나의 인수를받습니다 ;-).
평소와 같이 wikipedia 에는 이것에 대한 멋진 요약 항목이 있으며, 많은 유용한 포인터 (아마도 좋아하는 언어에 대한 포인터 포함);와 약간 더 엄격한 수학적 처리가 있습니다.
답변
구체적인 예는 다음과 같습니다.
물체에 작용하는 중력을 계산하는 함수가 있다고 가정하십시오. 수식을 모르는 경우 여기에서 찾을 수 있습니다 . 이 함수는 세 가지 필수 매개 변수를 인수로 사용합니다.
이제 지구상에 있으면이 행성의 물체에 대한 힘만 계산하려고합니다. 기능적 언어에서는 지구 덩어리를 기능에 전달한 다음 부분적으로 평가할 수 있습니다. 되돌아가는 것은 두 개의 인수 만 취하고 지구상의 물체의 중력을 계산하는 또 다른 함수입니다. 이것을 카레라고합니다.
답변
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...
이제 분명한 후속 질문은 왜 지구상에서 그렇게하고 싶습니까? 그것은 열심 인 작업 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)
비슷한 방식으로 추상화를 얻을 수 있습니다.
답변
커리 함수는 첫 번째 인수를 허용하고 두 번째 인수 등을 허용하는 함수를 반환하도록 여러 인수를 다시 작성한 함수입니다. 이를 통해 여러 인수의 함수가 초기 인수 중 일부를 부분적으로 적용 할 수 있습니다.
답변
다음은 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이이를 구현하는 방식에서 부분 개체와 기능 구분이 표시됩니다.