2010-10-18 15 views
11

Qualcuno potrebbe spiegarmi in seguito alla situazione con il meccanismo di conversioni implicite di Scala. C'è un codice:Domanda sulle conversioni implicite di Scala Regola di non ambiguità

object Main { 
    implicit val x:Int => String = v => "val" 
    implicit def y(v:Int) = "def" 

    def p(s:String) = print(s) 

    def main(args: Array[String]): Unit = { 
     p(1) 
    } 
} 

Questo codice stampa "val". Ma quando io commento seconda linea:

//implicit val x:Int => String = v => "val" 

stampe codice "def".

Quindi entrambe le conversioni implicite (xey) sono possibili in questa situazione. C'è una Regola di non ambiguità - una conversione implicita viene inserita solo se non c'è altra conversione possibile da inserire. Secondo questa regola questo codice non dovrebbe essere compilato affatto. Ma il codice viene compilato ed eseguito con successo. Cosa non capisco?

Grazie.

risposta

9

Il motivo è indicato nella sezione 6.26.2 delle specifiche della lingua di Scala.

Prima che il metodo possa essere considerato come una funzione, è necessario convertirlo in uno eseguendo l'espansione eta. Quindi si dovrebbe applicare una conversione implicita in più e viene scelto lo val.

UPDATE: esempio errato rimosso.

La valutazione di un metodo senza parametri viene sempre eseguita implicitamente.

+0

Ciao Moritz. Grazie per la risposta. Quindi, quando il compilatore Scala vede un'espressione il cui tipo non corrisponde a un tipo previsto, cerca conversioni implicite di tipo T => F, se tali conversioni non vengono trovate, il compilatore tenta di eseguire Eta Expansion o Empty Application sulle espressioni di metodo disponibili (il la parola "Altrimenti" in Scala Language Specification indica che questa azione verrà eseguita dopo). Se ho capito tutto? –

+0

Ma nel tuo esempio se commento // implicit val t = "World", il codice non verrebbe compilato. Sembra che l'applicazione vuota non sia presa in considerazione dal compilatore di Scala qui. –

+0

L'applicazione vuota è AFAICT in realtà non utilizzata quando il compilatore cerca conversioni implicite ma solo per il riempimento di altri parametri impliciti. Se scrivi 'implicit def i2s(): Int => String = _.toString' questo non sarà considerato come candidato per una conversione da' String' a 'Int'. A parte questo, è corretto: le conversioni nella lista in 6.26.2 vengono provate dall'alto verso il basso se il valore non può essere valutato direttamente. – Moritz

Problemi correlati