2014-06-06 5 views
2

이 같은 유사한 형태로 스칼라에서 일부 코드 건너 온 :스칼라 구문 도움말 커링

def test1(f : Int => Int)(x : Int) = x + f(x) 

    def test2(f : Int => Int)(x : Int) = f(x) 

    test2(test1(x => 2*x))(2) 

기능 TEST1 함수를 취하고 매개 변수로 INT, 및 함수를 반환 그래서 내가 혼란 스러워요, 권리? 그렇다면 test1(x => 2*x)은 어떻게 유효 할 수 있으며 test2에 함수를 반환합니까? 분명히 2 정수 매개 변수가 걸립니다,하지만 왜? 명세서 test2(test1(x => 2*x))(2)은 어떻게 확장됩니까?

미리 감사드립니다.

답변

0

이 :

는 가
test2(y => test1(x => 2*x)(y))(2) 

여러 인수 목록과 스칼라의 방법은 다른 언어 카레 기능과 같은 많은 역할을 할 수 있지만,이 방법으로 구현됩니다 사실 그 필요 :

test2(test1(x => 2*x))(2) 

이로 확장 모든 매개 변수는 구문에 표시됩니다. 예를 들어 이것을 REPL에 넣으면 다음과 같습니다 :

test1(x => 2*x) 

인수가 누락되었다고 불평 할 것입니다. 이 구문이 허용하는 것은 메서드가 함수로 변환되는 "η 확장"입니다. 당신이 작성하는 경우 :

val func: Int => Int = test1(x => 2*x) _ 

을 당신은 test1 부분적으로 적용 나타내는 기능을 얻을 수 있습니다. 스칼라는 문맥에 따라 자동으로 η 확장을 수행 할 것이고, 이는 test2(test1(x => 2*x))(2)에서 일어난다. test1 자체는 결코 함수를 반환하지 않지만 컴파일러는 필요할 때 함수를 기반으로 함수를 빌드합니다. 당신이 test1 같이 정의하면

그러나 :

def test1(f : Int => Int) = (x : Int) => x + f(x) 

그리고 컴파일러는 _없이 test1(x => 2*x)을 받아 들일 것입니다.또한 기본 구현에서 test1으로 고정 된 클로저를 구현하는 클래스는 단 하나만 존재하지만 원래 정의에서는 모든 부분 적용 test1을 사용하면 새 클래스가 만들어집니다. 반대로 클로저가 항상 만들어지기 때문에 두 매개 변수를 모두 사용하면 효율성이 떨어집니다.

+0

자, 스칼라가이 경우 cura 함수를 구현하기 위해 η 확장을 사용하고 있다고 말할 수는 있지만, test1이 함수를 반환한다고 생각하도록 권장할까요? – ekinrf

+0

일종. 다중 매개 변수 목록에는 currying이 구현되어 있다고 제안하는 문서가 많이 있지만 실제 currying을 사용하는 것처럼 맹목적으로 사용할 수는 없으며 여러 매개 변수 목록이있는 대부분의 메서드 인스턴스는 부분적으로 사용되는 것이 아닙니다. 'list.foldLeft (0)'은 드뭅니다. 내 새로운 편집보기 - 진정한 카레 드 된 방법/기능을 만드는 방법을 보여줍니다. – wingedsubmariner

1

function test1은 함수와 Int를 매개 변수로 사용하여 함수를 반환합니다.

아니오, 함수를 인수로 취하여 함수를 반환합니다. 그런 다음 반환 된 함수는 int를 인수로 취해 int를 반환합니다.

그런 다음 어떻게 test1 (x => 2 * x)가 유효하고 test2에 함수를 반환 할 수 있습니까?

지금은 분명합니다.

test2 (test1 (x => 2 * x)) (2) 문은 어떻게 확장됩니까?

test1은 인수로 x => 2*x을 호출하고 함수를 반환합니다. 그러면 test2이 리턴 된 함수를 인수로 호출하고 다른 함수를 리턴합니다. 그런 다음 다른 함수는 2을 인수로 호출됩니다.

+0

감사합니다. 저는 명령형 프로그래밍 스타일에 너무 몰두하고 있습니다. 카레 시도는 구문 론적 설탕이라고 생각했습니다. 이것은 이제 많은 의미가 있습니다. – ekinrf

+0

이것은 실제로 올바르지 않습니다. REPL 내부에서'test1 (x => 2 * x)'만 시도해보십시오. – wingedsubmariner