Come funzionano '20 secondi 'in Scala?


130

Come viene compilata la seguente:

import scala.concurrent.duration._

val time = 20 seconds

Cosa sta realmente succedendo qui?

Risposte:


171

Ci sono alcune cose che stanno succedendo.

Innanzitutto, Scala consente di omettere punti e parentesi da molte chiamate di metodo, quindi 20 secondsequivale a 20.seconds()*.

In secondo luogo, viene applicata una "conversione implicita". Poiché 20è un Inte Intnon ha alcun secondsmetodo, il compilatore cerca una conversione implicita che accetta Inte restituisce qualcosa che ha un secondsmetodo, con la ricerca vincolata dall'ambito della chiamata del metodo.

Hai importato DurationInt nel tuo ambito. Poiché DurationIntè una classe implicita con un Intparametro, il suo costruttore definisce una Int => DurationIntconversione implicita . DurationIntha un secondsmetodo, quindi soddisfa tutti i criteri di ricerca. Pertanto, il compilatore riscrive la chiamata come new DurationInt(20).seconds**.

* Lo dico liberamente. 20.seconds()non è effettivamente valido poiché il secondsmetodo non ha un elenco di parametri e pertanto i parentesi devono essere omessi nella chiamata del metodo.

** In realtà, questo non è del tutto vero perché DurationIntè una classe di valore, quindi il compilatore eviterà di racchiudere l'intero se possibile.


83
Qualsiasi tecnologia sufficientemente avanzata è indistinguibile dalla magia.
ripper234,

4
Fortunatamente la maggior parte degli IDE è in grado di distinguerlo! Le conversioni implicite vengono utilizzate molto in Scala. Se stai solo leggendo il file di testo, potrebbe essere confuso ("da dove proviene quel metodo") ma con il supporto di strumenti appropriati dovresti essere in grado di orientarti, a quel punto Scala può essere meravigliosamente significativo e conciso. (ad esempio 20 secondi è molto più leggibile di new DurationInt(20).seconds()quanto tu sappia come lo fa)
William Billingsley,

1
Se ti ritrovi a utilizzare impliciti, chiediti sempre se esiste un modo per ottenere la stessa cosa senza il loro aiuto. twitter.github.com/effectivescala/#Types e Generics-Implicits
oluies

4
In realtà il secondsmetodo è definito senza parentesi, quindi chiamarlo con parentesi è un errore.
Frank S. Thomas,

1
@Frank Questo è un buon punto. Non intendevo suggerire che puoi scrivere 20.seconds()in Scala, solo che il compilatore sta traducendo la chiamata in quel modo. Vale la pena sottolineare che Scala richiede di omettere le parentesi se il metodo corrispondente non ha un elenco di parametri, come in questo caso.
Aaron Novstrup,

7

La "magia" che sta succedendo lì si chiama "conversione implicita". Stai importando le conversioni implicite e alcune gestiscono la conversione tra Int (e Double) in Duration. Ecco di cosa hai a che fare.


1
Qualche idea sul perché l'importazione si import scala.concurrent.duration._risolva 20 secondsma l'importazione del tratto DurationConversionsnon lo fa? EDIT : ho appena capito cosa stanno realmente importando DurationInt. Immagino che sia perché non puoi importare il tratto reale? Solo un'implementazione concreta del tratto?
Franklin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.