2015-03-28 7 views
6

Recentemente ho iniziato la codifica con Akka/Scala, e ho incontrato il seguente problema:Utilizzando mapTo con i futures a Akka/Scala

Con una conversione implicita nel campo di applicazione, come ad esempio:

implicit def convertTypeAtoTypeX(a: TypeA): TypeX = 
    TypeX() // just some kinda conversion 

questo funziona:

returnsAFuture.mapTo[TypeX].map { x => ... } 

Ma questo non lo fa:

returnsAFuture.mapTo[TypeX].onComplete { ... } 

Quest'ultimo non riesce con un'eccezione di tipo cast. (Ad esempio, TypeA non può essere trasmesso a TypeX)

Molto confuso. Perché? Ho il sospetto che abbia qualcosa a che fare con la prova, ma non so abbastanza sia per indovinare in qualsiasi tipo di risposta :(

Grazie

risposta

7

Da doc:!

def mapTo[S](implicit tag: ClassTag[S]): Future[S] 
    Creates a new Future[S] which is completed with this Future's result if that conforms to S's erased type or a ClassCastException otherwise. 

Questa funzione potrebbe essere utilizzato solo per il cast tra oggetti che sono in una relazione di ereditarietà.Non si aspetta alcuna prova implicita da convertire da [T] a [S] (non sa nemmeno di T!)

Questa funzione è usato cioè in Akka dove chiedi un attore e ricevi in ​​risposta Fut ure [Qualsiasi]. Ma sai che un attore ti restituirà String in modo da poter scrivere in modo sicuro actor.ask(...).mapTo[String] e questo funzionerà perché Any può essere castato a tutto. Qui non vengono utilizzate conversioni implicite.

Ora stai dicendo che il tuo primo esempio funziona. Ma questa linea non è nemmeno calcolata in quanto non si richiede mai un risultato. Per visualizzare scala compilatore dice: bene fai una mappa (cambia da tipo X a tipo Y) un risultato di questo futuro, ma non usarla mai, quindi perché preoccuparti di eseguirla se non ti interessa?

Se aggiunto su Completato dopo la mappa nella prima riga vedresti la stessa ClassCastException.

Questo è probabilmente ora ciò che si vuole, ma questo è interessante:

returnsAFuture.map { x => x.fieldOnlyInTypeX } 

se si utilizza "x", come se fosse di tipo TypeX tutto funzionerà bene. Il compilatore Scala applicherà la conversione implicita a "x" per convertirlo in TypeX. Questo probabilmente non è quello che vuoi perché "x" è ancora di tipo TypeA e viene convertito implicitamente su ogni uso nella mappa.

~ Krzysiek

+0

Qualsiasi idea di che cosa è la performance di mapTo? – EugeneMi