2010-07-23 3 views
11

내가 스칼라에서 this class이 : 이제스칼라 타입 유추가 여기서 실패하는 이유는 무엇입니까?

object Util { 
    class Tapper[A](tapMe: A) { 
    def tap(f: A => Unit): A = { 
     f(tapMe) 
     tapMe 
    } 

    def tap(fs: (A => Unit)*): A = { 
     fs.foreach(_(tapMe)) 
     tapMe 
    } 
    } 

    implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap) 
} 

,

"aaa".tap(_.trim) 

왜 타입이 String으로 추론되지 않는 오류

error: missing parameter type for expanded function ((x$1) => x$1.trim)

을 제공, 컴파일되지 않습니다? 이 오류로 인해 암시 적 변환이 실행되는 것 같습니다 (그렇지 않으면 "tap은의 멤버가 아닙니다"라는 줄을 따라 오류가 발생합니다). 그리고 변환은 Tapper[String]이어야하며 이는 인수의 유형이 String => Unit (또는 (String => Unit)*)임을 의미합니다.

흥미로운 점은 내가 tap 중 하나를 주석으로 정의하면 컴파일된다는 것입니다. tap

답변

17

6.26.3 Overloading Resolution

One first determines the set of functions that is potentially applicable based on the shape of the arguments

...

If there is precisely one alternative in B, that alternative is chosen.

Otherwise, let S1, . . . , Sm be the vector of types obtained by typing each argument with an undefined expected type.

두 오버로드합니다 (arity에 입력 생성자 FunctionN를 차지 인수의 '모양'기준) 잠재적으로 적용 할 수 있습니다.

그래서 TYPER 진행와는 것 같은 :

val x = _.trim 

및 실패합니다.

더 똑똑한 알고리즘은 각 대안에 해당하는 매개 변수 유형의 최소 상한을 취할 수 있으며이를 예상 유형으로 사용할 수 있습니다. 그러나이 복잡성은 그만한 가치는 없습니다. 오버로딩은 많은 코너 케이스를 가지고 있지만, 이것은 다른 것입니다.

그러나이 경우에 사용할 수있는 트릭이있다, 당신이 정말로 하나의 매개 변수를 받아들이는 오버로드가 필요한 경우 :

object Util { 
    class Tapper[A](tapMe: A) { 
    def tap(f: A => Unit): A = { 
     f(tapMe) 
     tapMe 
    } 

    def tap(f0: A => Unit, f1: A => Unit, fs: (A => Unit)*): A = { 
     (Seq(f0, f1) ++ fs).foreach(_(tapMe)) 
     tapMe 
    } 
    } 

    implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap) 

    "".tap(_.toString) 
    "".tap(_.toString, _.toString) 
    "".tap(_.toString, _.toString, _.toString) 
} 
+0

우수한 아이디어, 감사합니다! 다르게 이름을 지어야한다고 생각했습니다. –

+3

당신은 빠르게 새 다니엘이되고 있습니다, 제이슨! –

+2

@oxbow 더 나은 점은, 그는 종종 스펙을 인용하는데, 이것은 좋은 것입니다. –