Hier sind einige Gründe, die wunderbar einfache Methode anzuwenden implicitly
.
Implizite Ansichten verstehen / Fehler beheben
Eine implizite Ansicht kann ausgelöst werden, wenn das Präfix einer Auswahl (z. B. the.prefix.selection(args)
enthält es kein Element selection
, auf das es anwendbar ist args
(auch nach dem Versuch, args
mit impliziten Ansichten zu konvertieren ). In diesem Fall sucht der Compiler nach impliziten Elementen, die lokal definiert sind In den aktuellen oder umschließenden Bereichen, geerbt oder importiert, handelt es sich entweder um Funktionen vom Typ dieses the.prefix
Typs zu einem Typ mit selection
definierten oder äquivalenten impliziten Methoden.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implizite Ansichten können auch ausgelöst werden, wenn ein Ausdruck nicht dem erwarteten Typ entspricht (siehe unten):
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Hier sucht der Compiler nach dieser Funktion:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Zugriff auf einen impliziten Parameter, der durch eine Kontextbindung eingeführt wird
Implizite Parameter sind wohl ein wichtigeres Merkmal von Scala als implizite Ansichten. Sie unterstützen das Typklassenmuster. Die Standardbibliothek verwendet dies an einigen Stellen - sehen Sie, scala.Ordering
wie es verwendet wird SeqLike#sorted
. Implizite Parameter werden auch zum Übergeben von Array-Manifesten und CanBuildFrom
-Instanzen verwendet.
Scala 2.8 ermöglicht eine Kurzsyntax für implizite Parameter, die als Kontextgrenzen bezeichnet wird. Kurz gesagt, eine Methode mit einem Typparameter A
, für den ein impliziter Parameter vom Typ erforderlich ist M[A]
:
def foo[A](implicit ma: M[A])
kann umgeschrieben werden als:
def foo[A: M]
Aber was bringt es, den impliziten Parameter zu übergeben, aber nicht zu benennen? Wie kann dies bei der Implementierung der Methode hilfreich sein foo
?
Oft muss auf den impliziten Parameter nicht direkt verwiesen werden, sondern er wird als implizites Argument zu einer anderen aufgerufenen Methode getunnelt. Wenn es benötigt wird, können Sie die knappe Methodensignatur mit dem Context Bound beibehalten und aufrufen, implicitly
um den Wert zu materialisieren:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Eine Teilmenge impliziter Parameter explizit übergeben
Angenommen, Sie rufen eine Methode auf, die eine Person mit einem typklassenbasierten Ansatz hübsch druckt:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
Was ist, wenn wir die Art und Weise ändern möchten, in der der Name ausgegeben wird? Wir können explizit PersonShow
eine Alternative aufrufen , explizit übergeben Show[String]
, aber wir möchten, dass der Compiler die übergibt Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Implicitly
ist in Scala 2.8 verfügbar und in Predef definiert als:Es wird häufig verwendet, um
T
zu überprüfen, ob ein impliziter Wert vom Typ verfügbar ist, und ihn zurückzugeben, wenn dies der Fall ist.Einfaches Beispiel aus der Präsentation von retronym :
quelle
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") )
, insbesondere um einen impliziten Parameter abzurufen, der durch eine Kontextbindung eingeführt wurde:def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
Eine Antwort " Bringen Sie das Fischen bei" besteht darin, den alphabetischen Mitgliederindex zu verwenden, der derzeit in den Scaladoc-Nachthemden verfügbar ist . Die Buchstaben (und die
#
für nicht alphabetische Namen) oben im Paket- / Klassenbereich sind Links zum Index für Mitgliedsnamen, die mit diesem Buchstaben beginnen (über alle Klassen hinweg). Wenn SieI
z. B. wählen , finden Sie denimplicitly
Eintrag mit einem Vorkommen inPredef
, den Sie über den dortigen Link besuchen können.quelle
implicit
scheint ein wichtiges Sprachmerkmal in Scala zu sein und verdient definitiv eine angemessene Erklärung. Der Gedanke, dass Dokumente, in denen nur die Anzahl der Typensignaturen angegeben ist, eher eine intellektuelle Selbstbefriedigung als eine echte Antwort sind. Sehen Sie sich die spezifischen Fragen des OP an - was ist das und wie wird es verwendet? Weder beantwortet noch in den nächtlichen Dokumenten, zu denen Sie nicht einmal einen tatsächlichen Link bereitstellen. scala-lang.org/files/archive/nightly/docs/library/… Dies lehrt nichts. Beispiele für Originaldokumente finden Sie unter Niklaus Wirth oder Turbo Pascal. -1implicit
undimplicitly
sind verwandt, aber ziemlich verschieden. Dasimplicit
Schlüsselwort ist Teil der Sprache.implicitly
wird in der Standardbibliothek in einfachem Scala-Code definiert. Da die Online-Dokumente Quelllinks enthalten, ist es meines Erachtens immer noch am besten, Fragesteller auf diese Dokumente und die verknüpfte Quelle zu verweisen.