Próbuję zrozumieć, co wydaje się dziwne zachowanie, gdy mamy do czynienia z wartościami null i adnotacje typu wewnątrz pojęcia for-understand.Wyjątek scala w zrozumieniu z adnotacją typu
Jako przykład:
def f(): String = null
for {
a <- Option("hello")
b = f()
} yield (a, b)
skutkuje oczekiwana:
//> res0: Option[(String, String)] = Some((hello,null))
jednak, jeśli dodać typ adnotacji do rodzaju b
def f(): String = null
for {
a <- Option("hello")
b: String = f()
} yield (a, b)
potem dostać wyjątek środowiska wykonawczego:
//> scala.MatchError: (hello,null) (of class scala.Tuple2)
Dlaczego tak się dzieje? Czy w pierwszym przykładzie nie jest to typ ? Co zmienia adnotacja typu jawnego w drugim przykładzie?
(Uwaga, przykłady przeprowadzono w Scala 2.11.4)
Drugi przykład kompiluje do meczu, jak widać z użyciem 'reify' w repl:' import scala.reflect.runtime.universe ._; reify {for {...}} '. Nie mogę ci powiedzieć, dlaczego. AIUI 'null' nie pasuje, ponieważ dopasowanie działa na typie (lub wartości) środowiska wykonawczego, nawet jeśli' b' ma typ "String" w czasie kompilacji; jest to w pewnym sensie dziura w systemie typów, a kod scala powinien zasadniczo unikać używania wartości null. – lmm
Nie jestem fanem zerowej wartości, wierz mi! W rzeczywistym kodzie, w którym natknąłem się na to, używałem 'Try's do integracji z jakimś starszym kodem java. Jednak null wydaje mi się tu incydentalny: aspekt, który uważam za dziwaczny (przerażający?) Polega na tym, że dodanie większej liczby specyficzności typów powoduje (nieintuicyjny) wyjątek środowiska wykonawczego. –
To dziwaczność języka, że umieszczanie typów w 'for' /' yield' powoduje dopasowanie wzorca; nie ma problemu, który wystąpiłby w przypadku wyrażeń "zwykłych". Wszystko, co mogę powiedzieć, to niefortunne, ale prawdopodobnie nie można tego zmienić na tym etapie; Z tego powodu staram się unikać podawania typu po lewej stronie// z tego powodu:/ – lmm