Comment fonctionne "20 secondes" dans Scala?

130

Comment se compile ce qui suit:

import scala.concurrent.duration._

val time = 20 seconds

Que se passe-t-il réellement ici?

ripper234
la source

Réponses:

171

Il se passe plusieurs choses.

Premièrement, Scala permet d'omettre les points et les parens dans de nombreux appels de méthode, ce qui 20 secondséquivaut donc à 20.seconds()*.

Deuxièmement, une "conversion implicite" est appliquée. Puisque 20est une méthode Intet Intn'a pas de secondsméthode, le compilateur recherche une conversion implicite qui prend un Intet retourne quelque chose qui a une secondsméthode, la recherche étant limitée par la portée de votre appel de méthode.

Vous avez importé DurationInt dans votre scope. Puisque DurationIntest une classe implicite avec un Intparamètre, son constructeur définit une Int => DurationIntconversion implicite . DurationInta une secondsméthode, donc il satisfait tous les critères de recherche. Par conséquent, le compilateur réécrit votre appel en new DurationInt(20).seconds**.

* Je veux dire cela vaguement. 20.seconds()n'est en fait pas valide car la secondsméthode n'a pas de liste de paramètres et par conséquent, les parenthèses doivent être omises lors de l'appel de méthode.

** En fait, ce n'est pas tout à fait vrai car il DurationInts'agit d'une classe de valeur, donc le compilateur évitera d'encapsuler l'entier si possible.

Aaron Novstrup
la source
83
Toute technologie suffisamment avancée est indiscernable de la magie.
ripper234
4
Heureusement, la plupart des IDE sont capables de le distinguer! Les conversions implicites sont beaucoup utilisées dans Scala. Si vous ne faites que lire le fichier texte, cela peut être déroutant («d'où vient cette méthode») mais avec un support d'outils approprié, vous devriez être en mesure de trouver votre chemin, à quel point Scala peut être magnifiquement significatif et concis. (par exemple, 20 secondes est beaucoup plus lisible que new DurationInt(20).seconds()tant que vous savez comment cela fonctionne)
William Billingsley
1
Si vous vous retrouvez à utiliser des implicits, demandez-vous toujours s'il existe un moyen de réaliser la même chose sans leur aide. twitter.github.com/effectivescala/#Types and Generics-Implicits
oluies
4
En fait, la secondsméthode est définie sans parenthèses, donc l'appeler avec des parenthèses est une erreur.
Frank
1
@Frank C'est un bon point. Je ne voulais pas suggérer que vous puissiez écrire 20.seconds()en Scala, mais seulement que le compilateur traduit l'appel de cette façon. Il est intéressant de noter que Scala vous oblige à omettre les parens si la méthode correspondante n'a pas de liste de paramètres, comme dans ce cas.
Aaron Novstrup
7

La "magie" qui se passe là-bas est appelée "conversion implicite". Vous importez les conversions implicites et certaines d'entre elles gèrent la conversion entre Int (et Double) en Duration. C'est de cela que vous avez affaire.

Bruno Reis
la source
1
Une idée de la raison pour laquelle l'importation est import scala.concurrent.duration._résolue, 20 secondsmais pas l'importation du DurationConversionstrait? EDIT : Je viens de réaliser ce qu'ils importent réellement DurationInt. Je suppose que c'est parce que vous ne pouvez pas importer le trait réel? Seule une mise en œuvre concrète du trait?
franklin