2012-07-15 15 views
7

Vedo ora che c'è una questione connessa chiedendo che cosa questi operatori (<: <, <% <, =: =) fanno qui:Quanto esattamente l'implementazione di Scala di <: <, <% <, =: = funziona nel compilatore?

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

ma io sono ancora confusi circa la loro attuazione. In particolare, suppongo che una volta inserito un parametro implicito che asserisce una particolare relazione, è possibile utilizzare le variabili come se fossero state automaticamente trasmesse correttamente, ad es. questo compila:

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

Ma come funziona effettivamente nel compilatore? C'è qualche supporto per il compilatore magico per questi operatori, e se no, qual è il meccanismo sottostante che gli permette di dedurre questo tipo di relazione dalla definizione? (Questo meccanismo è stato aggiunto in modo specifico per consentire a questi operatori di funzionare e quanto è specifico per questi particolari operatori?) Sembra un po 'magico che si possa inserire un parametro implicito extra come questo che in qualche modo modifica l'interpretazione del compilatore di un tipo.

+2

La fonte per loro https://github.com/scala/scala/blob/v2.9.2/src/library/scala/Predef.scala#L394 – pedrofurla

risposta

8

L'implementazione è un po 'complicata, ma nulla di magico.

C'è un metodo implicito in Predef che può fornire un valore di tipo A <:< A per qualsiasi A

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

Quando si tenta di richiamare il metodo, sembra per un valore implicito di tipo T <:< String. Il compilatore verificherà se conforms[T] è un valore valido. Diciamo che T è Nothing quindi ci sarà un valore implicito Nothing <:< Nothing nell'ambito che consentirà alla chiamata del metodo di compilare. A causa del modo <:< è definita

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

From è consentito di variare e To è consentito di variare in giù. Quindi un Nothing <:< Nothing è ancora valido Nothing <:< String poiché Nothing è un sottotipo di String. A String <:< String sarebbe anche un Nothing <:< String valido dal String è un supertipo di Nothing (ma il compilatore sembra scegliere sempre solo il primo tipo).

È possibile chiamare i metodi di String su di esso, perché <:< estende anche => alias Function1 e serve come una conversione implicita T-String, che finisce in pratica per fare un cast di sicurezza.

=:= è la stessa cosa tranne che è definito senza alcuna annotazione di varianza, quindi i tipi devono corrispondere esattamente.

<%< è definito come <:< ma il metodo implicito è un po 'diverso, si aggiunge un altro parametro per specificare una vista vincolato

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

È anche obsoleto.

+0

Grazie!Quanto segue è la chiave per spiegare come il compilatore ti permette di chiamare i metodi String (o qualsiasi altra cosa): _Si può chiamare metodi di String su di esso perché <: aka Function1 e serve come conversione implicita da T a String, che fondamentalmente finisce per fare un cast sicuro. –