2012-07-15 31 views
7

Ahora veo que hay una pregunta relacionada preguntando qué estos operadores (<: <, <% <, =: =) hacen aquí:¿Cómo funciona exactamente la implementación de Scala de <: <, <% <, =: = en el compilador?

What do <:<, <%<, and =:= mean in Scala 2.8, and where are they documented?

pero todavía estoy confundido acerca de su aplicación. En particular, supongo que una vez que ha colocado un parámetro implícito que afirma una relación particular, puede usar variables como si se hubieran lanzado correctamente, p. Ej. esto compilará:

class Foo[T](a: T) { 
    def splitit(implicit ev: T <:< String) = a split " " 
} 

Pero, ¿cómo funciona esto realmente en el compilador? ¿Existe algún soporte de compilador mágico para estos operadores, y si no, ¿cuál es el mecanismo subyacente que le permite inferir este tipo de relación a partir de la definición? (¿Este mecanismo se agregó específicamente para permitir que estos operadores funcionen, y cuán específico es para estos operadores particulares?) Parece un poco mágico que pueda colocar un parámetro implícito adicional como este que de alguna manera cambia la interpretación del compilador de un tipo.

+2

La fuente para ellos https://github.com/scala/scala/blob/v2.9.2/src/library/scala/Predef.scala#L394 – pedrofurla

Respuesta

8

La implementación es un poco complicada, pero nada mágico.

Hay un método implícito en Predef que puede proporcionar un valor de tipo A <:< A para cualquier A

implicit def conforms[A]: A <:< A 

Cuando intenta invocar el método, se busca un valor implícito del tipo T <:< String. El compilador verificará si conforms[T] es un valor válido. Digamos que T es Nothing, entonces habrá un valor implícito Nothing <:< Nothing en el alcance que permitirá compilar su llamada a método. Debido a la forma <:< se define

sealed abstract class <:<[-From, +To] 

From se le permite variar y se permite To para variar hacia abajo. Entonces, un Nothing <:< Nothing sigue siendo un Nothing <:< String válido, ya que Nothing es un subtipo de String. Un String <:< String también sería un Nothing <:< String válido ya que String es un supertipo de Nothing (pero el compilador siempre elige solo el primer tipo).

Puede llamar a los métodos de String en él porque <:< se extiende también conocido como =>Function1 y sirve como una conversión implícita de T a String, que básicamente termina haciendo un reparto seguro.

=:= es lo mismo, excepto que se define sin anotaciones de varianza, por lo que los tipos deben coincidir exactamente.

<%< se define como <:< pero el método implícito es un poco diferente, se añade otro parámetro para especificar una vista unido

implicit def conformsOrViewsAs[A <% B, B]: A <%< B 

También está en desuso.

+0

Gracias!La siguiente es la clave para explicar cómo el compilador le permite llamar a los métodos String (o lo que sea): _Puede llamar a los métodos de String porque <: aka Function1 y sirve como una conversión implícita de T a String, que básicamente termina haciendo un casting seguro. –