2010-04-28 7 views
14

이 코드는 컴파일에 실패하지만 표시된 줄의 주석을 제거 할 때 성공적으로 컴파일되는 이유는 무엇입니까? (나는 스칼라 2.8을 매일 사용하고있다.) 명시 적으로 string2Wrapper을 호출하면 해당 지점에서 암시 적으로 사용될 수 있습니다.이 스칼라 메서드를 명시 적으로 호출하면 암시 적으로 해결 될 수 있습니까?

class A { 
    import Implicits.string2Wrapper 
    def foo() { 
    //string2Wrapper("A") ==> "B" // <-- uncomment 
    } 
    def bar() { 
    "A" ==> "B" 
    "B" ==> "C" 
    "C" ==> "D" 
    } 
    object Implicits { 
    implicit def string2Wrapper(s: String) = new Wrapper(s) 
    class Wrapper(s: String) { 
     def ==>(s2: String) {} 
    } 
    } 
} 

편집는 : 마틴 오더 스키의 의견에 대한 포인터를 포함 지금까지 답변에 대한 감사,

"명시 적 결과 유형이없는 암시 적 변환은 다음과 같은 텍스트 에서 볼 수의 그렇게하면 순환 참조 오류는 피할 수 있습니다. "

"순환 참조 오류"의 위험은 무엇입니까? 2) 명시 적 호출이 어떤 차이를 만드는 이유는 무엇입니까?

답변

19

string2Wrapper의 반환 유형을 명시 적으로 정의하면 문제가 해결됩니다.

class A { 
    import Implicits._ 

    def bar() {  
    "A" ==> "B" 
    "B" ==> "C" 
    "C" ==> "D" 
    } 
    object Implicits { 
    implicit def string2Wrapper(s: String): Wrapper = new Wrapper(s) 
    class Wrapper(s: String) { 
     def ==>(s2: String) {} 
    } 
    } 
} 

Implicits도 작동 bar 전에 정의 : 현재 범위 내에서 아래 정의 된 암시 적 변환에 의존해야하는 경우

class A { 
    object Implicits { 
    implicit def string2Wrapper(s: String) = new Wrapper(s) 
    class Wrapper(s: String) { 
     def ==>(s2: String) {} 
    } 
    } 

    import Implicits._ 

    def bar() {  
    "A" ==> "B" 
    "B" ==> "C" 
    "C" ==> "D" 
    } 
} 

, 당신은 그것의 반환 형식에 주석을 확인하십시오. 이전에 메일 링리스트에 올랐으며 버그가 아닌 예상되는 동작 일 수 있습니다. 하지만 지금은 찾을 수 없습니다. foo의 명시 적 호출은 bar의 내용을 입력 할 때 유효한 bar의 반환 유형의 유추를 트리거합니다.

UPDATE

순환 참조 오류의 위험은 무엇입니까?

암시 적 메서드의 본문은 암시 적 변환이 필요한 메서드를 호출 할 수 있습니다. 이 두 가지 모두 유추 된 반환 유형이 있으면 어려움에 처하게됩니다. 이 예제는 예제에는 적용되지 않지만 컴파일러는이를 감지하지 않습니다.

왜 명시 적 호출이 다른 점이 있습니까?

명시 적 호출은 암시 적 메서드의 반환 형식에 대한 유추를 트리거합니다. 당신이 넣으면 https://lampsvn.epfl.ch/trac/scala/ticket/3373

+0

(예정)입니다. Paulp는 최근까지 그런 범위까지 티켓을 발굴했습니다. 내가 그것을 찾을 수없는 경우에 보자 ... –

+5

여기 : https://lampsvn.epfl.ch/trac/scala/ticket/801 –

3

object Implicits 먼저 작동 : 여기 Implicits.isValid

sym.isInitialized || 
     sym.sourceFile == null || 
     (sym.sourceFile ne context.unit.source.file) || 
     hasExplicitResultType(sym) || 
     comesBefore(sym, context.owner) 

업데이트 2

이 최근 버그가 관련 모양의 논리입니다. 이것은 여러 컴파일러 패스를 작성하는 논리에서 나에게 버그처럼 보입니다. bar을 컴파일하면 string2Wrapper을 알지 못해 도망 갈 수 있다고 가정합니다.내 생각 엔 당신이 그것을 사용한다면 string2Wrapper가 실제로 무엇인지 알지 못해서 실제로는 Implicits을 컴파일 한 다음 ==>이 String에 암묵적으로 정의되어 있다는 것을 깨닫는다는 것입니다.

편집 : 어떤 Retronym이 게시했는지에 따라, 아마도 "버그"가 아닌 "기능"일 것입니다. 아직도 나에게 짜증나는 것처럼 보인다!

12

어쨌든 밤늦게 나왔다면 어제 추가 한 오류 메시지를 보았을 것입니다.

<console>:11: error: value ==> is not a member of java.lang.String 
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type 
      "A" ==> "B" 
     ^
<console>:12: error: value ==> is not a member of java.lang.String 
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type 
      "B" ==> "C" 
     ^
<console>:13: error: value ==> is not a member of java.lang.String 
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type 
      "C" ==> "D" 
     ^
관련 문제