2011-01-15 4 views
6

스칼라에서 두 매개 변수 목록을 사용하여 함수를 정의 할 수 있습니다.중첩 된 함수 또는 다중 매개 변수 목록으로 스칼라 currying

def myAdd(x :Int)(y :Int) = x + y 

이렇게하면 부분 적용 기능을 쉽게 정의 할 수 있습니다.

val plusFive = myAdd(5) _ 

그러나 중첩 된 함수를 정의하고 반환하여 비슷한 결과를 얻을 수 있습니다.

def myOtherAdd(x :Int) = { 
    def f(y :Int) = x + y 
    f _ 
    } 

외면적으로 나는 밑줄을 옮겼지만, 여전히 카레 시도처럼 느껴집니다.

val otherPlusFive = myOtherAdd(5) 

한 접근법을 다른 기준보다 선호하려면 어떤 기준을 사용해야합니까?

답변

6

또한이 작업을 수행 할 수 있습니다 :

def yetAnotherAdd(x: Int) = x + (_: Int) 

당신은 의도에 따라 API를 선택해야합니다. 스칼라에서 여러 매개 변수 목록을 갖는 주된 이유는 형식 유추를 돕는 데 있습니다. 예를 들면 다음과 같습니다.

def f[A](x: A)(f: A => A) = ... 
f(5)(_ + 5) 

여러 varargs를 사용할 수도 있지만 이런 코드는 본 적이 없습니다. 물론 암묵적인 매개 변수 목록이 필요하지만 꽤 많은 문제입니다.

이제는 함수를 반환하는 함수를 여러 가지 방법으로 사용할 수 있습니다. 이 함수를 반환하는 함수로 생각되어야한다면 API를 사용해야합니다.

이보다 더 정확한 정보를 얻는 것은 어렵다고 생각합니다.

+0

감사합니다, 다니엘. 여러 매개 변수 목록에 대한 동기로서 형식 유추에 대한 귀하의 의견은 눈을 뜨게합니다. 이것은 정말로 도움이되었습니다. –

+0

또 다른 동기는 'using (x) {...}'과 같이 언어에 잘 통합 된 DSL을 작성하는 것입니다. 이것은 물론, 여러 블록에 제공되는 유 형 추론을 사용합니다. –

9

같은 일을 달성하기 위해 적어도 네 가지가 있습니다

def myAddA(x: Int, y: Int) = x + y 
val plusFiveA: Int => Int = myAddA(5,_) 

def myAddB(x: Int)(y : Int) = x + y 
val plusFiveB = myAddB(5) _ 

def myAddC(x: Int) = (y: Int) => x + y 
val plusFiveC = myAddC(5) 

def myAddD(x: Int) = { 
    def innerD(y: Int) = x + y 
    innerD _ 
} 
val plusFiveD = myAddD(5) 

당신은 가장 효율적인 을 알고 할 수 있습니다 또는 일부 비 성능 기반 측정에 가장 적합한 스타일을 (이다 최고).

효율이 향상되는 한, 네 가지가 본질적으로 동일하다는 것이 밝혀졌습니다. 처음 두 사례는 실제로 정확히 동일한 바이트 코드를 방출합니다. JVM은 여러 매개 변수 목록에 대해 아무 것도 모릅니다. 따라서 컴파일러가이를 파악하면 (사례 A의 형식 주석으로 도울 필요가 있음) 모두 동일합니다. 세 번째 경우도 매우 가깝지만 함수를 반환하기 위해 앞을 내다 보게하고 그 자리에서 지정하기 때문에 하나의 내부 필드를 피할 수 있습니다. 네 번째 사례는 완료된 첫 번째 두 사례와 거의 같습니다. 대신 외부의 메서드 내에서 Function1으로 변환됩니다.

스타일 측면에서 B와 C가 자신이하는 일에 따라 최선의 방법이라고 제안합니다. 기본 유스 케이스가 함수를 작성하고 두 매개 변수 목록으로 현재 위치에서 호출하지 않는 경우, C가 사용하는 것을 알려주기 때문에 C를 사용하십시오. (이 버전은 또한 예를 들어 하스켈에서 온 사람들에게 특히 친숙합니다.) 반면에 대부분 카스퍼 스키를 카레에 넣기 만한다면 B를 사용하십시오. 그것은 할 것으로 예상됩니다.

+0

고마워요, 렉스. 나는 접근법 A와 C를 모르고있었습니다. 당신의 대답은 정말로 도움이됩니다. –

4

메서드가 부분적으로 응용 프로그램을 사용하는 대신에 직접 함수를 반환하도록하는 또 다른 이점은 중위 표기법을 사용할 때 코드가 훨씬 명확 해 지므로 더 복잡한 식에서는 괄호로 묶인 bucketload를 피할 수 있습니다.

고려 :

val list = List(1,2,3,4) 

def add1(a: Int)(b: Int) = a + b 
list map { add1(5) _ }  

//versus 

def add2(a: Int) = a + (_: Int) 
list map add2(5) 
관련 문제