2010-10-18 23 views
11

¿Alguien podría explicarme la siguiente situación con el mecanismo de conversiones implícitas de Scala? Hay un código:Pregunta sobre conversiones implícitas de Scala Regla de no ambigüedad

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) 
    } 
} 

Este código imprime "val". Pero cuando comento la segunda línea:

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

El código imprime "def".

Por lo tanto, ambas conversiones implícitas (x e y) son posibles en esta situación. Hay una regla de no ambigüedad - una conversión implícita solo se inserta si no hay otra conversión posible para insertar. De acuerdo con esta regla, este código no debe compilarse en absoluto. Pero el código se compila y ejecuta con éxito. Lo que no entiendo?

Gracias.

Respuesta

9

La razón para esto se indica en la Especificación de idioma de Scala, sección 6.26.2.

Antes de que el método se pueda tratar como una función, se debe convertir a uno realizando la expansión eta. Por lo tanto, se debería aplicar una conversión implícita más, por lo que se elige val.

ACTUALIZACIÓN: eliminado ejemplo defectuoso.

La evaluación de un método sin parámetros siempre se realiza implícitamente.

+0

Hola Moritz. Gracias por una respuesta. Entonces, cuando el compilador de Scala ve expresiones cuyo tipo no coincide con un tipo esperado, busca conversiones implícitas de tipo T => F, si tales conversiones no se encuentran, el compilador intenta realizar Expansión Eta o Aplicación vacía en expresiones de métodos disponibles (el la palabra "De lo contrario" en Scala Language Specification indica que esta acción se realizará después). Si lo entendí todo? –

+0

Pero en su ejemplo si comento // implicit val t = "World", el código no se compilará. Parece que el compilador de Scala no tiene en cuenta la aplicación vacía aquí. –

+0

La aplicación vacía AFAICT en realidad no se utiliza cuando el compilador busca conversiones implícitas, pero solo para completar otros parámetros implícitos. Si escribe 'imp i2s(): Int => String = _.toString', esto no se considerará como candidato para una conversión de' String' a 'Int'. Aparte de eso, es correcto: las conversiones en la lista en 6.26.2 se prueban de arriba a abajo si el valor no se puede evaluar directamente. – Moritz

Cuestiones relacionadas