null을 사용하고 이해를 위해 입력 주석을 처리 할 때 이상한 동작이 무엇인지 이해하려고합니다. 예를 들어형식 주석이있는 이해를위한 스칼라 예외
는 :에
def f(): String = null
for {
a <- Option("hello")
b = f()
} yield (a, b)
결과 예상 :
//> res0: Option[(String, String)] = Some((hello,null))
그러나, 그때 내가 할 b
def f(): String = null
for {
a <- Option("hello")
b: String = f()
} yield (a, b)
의 종류에 유형 약어를 추가하는 경우 런타임 예외 :
//> scala.MatchError: (hello,null) (of class scala.Tuple2)
왜 이런 일이 발생합니까? 어쨌든 b
은 암시 적으로 첫 번째 예제에서 String
유형입니까? 두 번째 예제의 명시 적 유형 주석은 어떻게 변경됩니까?
(참고, 예 스칼라 2.11.4에서 실행 된)
당신이 REPL에서'reify'를 사용하여 볼 수있는 두 번째 예는, 일치로 컴파일 :'수입 scala.reflect.runtime.universe ._; reify {for {...}}'. 왜 당신에게 말할 수는 없지만. AIUI'null'은 일치하지 않습니다. 왜냐하면'b'는'String'의 컴파일 타임 타입을 가지고 있습니다. 이것은 어떤 의미에서는 타입 시스템의 구멍이며, scala 코드는 일반적으로 null을 사용하지 않아야합니다. – lmm
나는 nulls의 팬이 아니다, 나를 믿어 라! 실제 코드에서 나는 이것을 우연히 발견했는데'Try's를 사용하여 일부 레거시 Java 코드와 통합했습니다. 그러나 null은 나에게 부수적 인 것처럼 보입니다 : 기괴한 (무서운 것)이라는 측면은 (보다 직관적이지 않은) 런타임 예외에 더 많은 유형 지정 결과를 추가하는 것입니다. –
'for// yield'형식을 사용하면 패턴 일치가 발생한다는 것은 이상한 언어입니다. 표현식에서 "일반"유형으로 발생하는 문제는 아닙니다. 내가 말할 수있는 것은 불행한 일이지만,이 단계에서는 아마도 바뀔 수 없다. 나는 이런 이유로 왼쪽/오른쪽에 타입을주는 것을 피하는 경향이있다./ – lmm