2016-05-04 33 views
5

Ho usato questo tipo di linea per testare i miei impliciti rendendola implicita da un incidente di copia-incolla. Mi c'è voluto un po 'di tempo per capire, perché questo compila nonostante non mi aspettavo di compilare:scala implicit che si completa?

> console 
[info] Starting scala interpreter... 
[info] 
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66). 
... skipped some comment lines ... 

scala> case object Foo 
defined object Foo 

scala> object Bar { implicit val f: Foo.type = implicitly[Foo.type] } 
defined object Bar 

scala> val x = Bar.f 
x: Foo.type = null 

scala> 

mi aspetterei Bar a fallire la compilazione, perché non c'è val implicita di tipo Foo.type (l'oggetto caso è NON dichiarato implicito).

Per me sembra che il compilatore usi la dichiarazione di f (lato sinistro) per completare la sua implementazione (lato destro).

È davvero questo il comportamento previsto? A runtime ciò comporta un comportamento imprevisto con i valori null (principalmente NPE per me).

risposta

3

Questo sta accadendo perché f è dichiarato come implicit. Quindi in un certo senso il lato destro di implicit val f: Foo.type = implicitly[Foo.type] risolve il valore implicito val f stesso!

Se si rimuove lo implicit da quella riga, la compilazione non verrà eseguita. Quello che mi chiedo è perché stai usando una tale linea però.

Questo è sicuramente un problema per me. Qualcuno sembra che abbia già preso nota l'anno scorso.

Enhancement Request

+0

il problema indicato è etichettato come "miglioramento". Lo considererei un bug. Qualche possibilità di aumentare la sua importanza? – sthielo

+0

sono d'accordo è un problema. Penso che tu possa andare avanti e registrare un problema con loro. O magari aggiungere un commento a quella richiesta di 'miglioramento'. lo farei anche io –

+3

Se si tratta di un bug, è nelle specifiche, non nel codice. La definizione val appartiene allo scope esterno implicitamente, quindi è valida come candidato per la ricerca. Una soluzione comune consiste nel non annotare il valore di destinazione, "implicito val f = implicitamente [Foo.type]" funzionerebbe, come nel caso in cui non si riesce a compilare, poiché il compilatore non sa che 'f' sarà del tipo desiderato. – knutwalker