Wie funktioniert '20 Sekunden 'in Scala?


130

Wie wird folgendes kompiliert:

import scala.concurrent.duration._

val time = 20 seconds

Was ist hier eigentlich los?

Antworten:


171

Es sind ein paar Dinge los.

Erstens erlaubt Scala, dass Punkte und Parens in vielen Methodenaufrufen weggelassen werden, 20 secondswas 20.seconds()* entspricht.

Zweitens wird eine "implizite Konvertierung" angewendet. Da 20es sich um eine Intund Intkeine secondsMethode handelt, sucht der Compiler nach einer impliziten Konvertierung, die eine Methode mit einer Methode Intzurückgibt , wobei die Suche durch den Umfang Ihres Methodenaufrufs eingeschränkt wird.seconds

Sie haben DurationInt in Ihren Bereich importiert . Da DurationIntes sich um eine implizite Klasse mit einem IntParameter handelt, definiert der Konstruktor eine implizite Int => DurationIntKonvertierung. DurationInthat eine secondsMethode, die alle Suchkriterien erfüllt. Daher schreibt der Compiler Ihren Aufruf als new DurationInt(20).seconds** neu.

* Ich meine das locker. 20.seconds()ist tatsächlich ungültig, da die secondsMethode keine Parameterliste hat und daher die Parens beim Methodenaufruf weggelassen werden müssen .

** Tatsächlich ist dies nicht ganz richtig, da DurationIntes sich um eine Wertklasse handelt, sodass der Compiler das Umschließen der Ganzzahl nach Möglichkeit vermeidet.


83
Jede ausreichend fortschrittliche Technologie ist von Magie nicht zu unterscheiden.
Ripper234

4
Glücklicherweise können die meisten IDEs dies unterscheiden! Implizite Konvertierungen werden in Scala häufig verwendet. Wenn Sie nur die Textdatei lesen, kann dies verwirrend sein ("Woher kommt diese Methode?"), Aber mit der entsprechenden Toolunterstützung sollten Sie in der Lage sein, sich zurechtzufinden. An diesem Punkt kann Scala sehr aussagekräftig und präzise sein. (zB 20 Sekunden ist viel besser lesbar als new DurationInt(20).seconds()solange Sie wissen, wie es geht)
William Billingsley

1
Wenn Sie implizite Dinge verwenden, fragen Sie sich immer, ob es einen Weg gibt, dasselbe ohne deren Hilfe zu erreichen. twitter.github.com/effectivescala/#Types and Generics-Implicits
oluies

4
Tatsächlich ist die secondsMethode ohne Parens definiert, daher ist das Aufrufen mit Parens ein Fehler.
Frank S. Thomas

1
@ Frank Das ist ein guter Punkt. Ich wollte nicht vorschlagen, dass Sie 20.seconds()in Scala schreiben können , nur, dass der Compiler den Aufruf auf diese Weise übersetzt. Es ist erwähnenswert, dass Scala erfordert Sie Pars wegzulassen , wenn das entsprechende Verfahren keine Parameterliste hat, wie in diesem Fall.
Aaron Novstrup

7

Die "Magie", die dort vor sich geht, heißt "implizite Konvertierung". Sie importieren die impliziten Konvertierungen, und einige von ihnen übernehmen die Konvertierung zwischen Int (und Double) in Duration. Damit haben Sie es zu tun.


1
Irgendeine Idee, warum das Importieren aufgelöst wird, import scala.concurrent.duration._das 20 secondsImportieren des DurationConversionsMerkmals jedoch nicht? EDIT : Ich habe gerade festgestellt, was sie tatsächlich importieren DurationInt. Ich vermute, das liegt daran, dass Sie das eigentliche Merkmal nicht importieren können. Nur eine konkrete Umsetzung des Merkmals?
Franklin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.