Voici quelques raisons d'utiliser la méthode délicieusement simple implicitly
.
Pour comprendre / dépanner les vues implicites
Une vue implicite peut être déclenchée lorsque le préfixe d'une sélection (par exemple, the.prefix.selection(args)
ne contient pas de membre selection
applicable à args
(même après avoir tenté de convertir args
avec des vues implicites). Dans ce cas, le compilateur recherche des membres implicites, définis localement dans les étendues actuelles ou englobantes, héritées ou importées, qui sont soit des fonctions du type de celui-ci the.prefix
vers un type avec des selection
méthodes implicites définies, soit équivalentes.
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
Les vues implicites peuvent également être déclenchées lorsqu'une expression n'est pas conforme au type attendu, comme ci-dessous:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Ici, le compilateur recherche cette fonction:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Accès à un paramètre implicite introduit par un contexte lié
Les paramètres implicites sont sans doute une fonctionnalité plus importante de Scala que les vues implicites. Ils prennent en charge le modèle de classe de type. La bibliothèque standard l'utilise à quelques endroits - voyez scala.Ordering
et comment elle est utilisée dans SeqLike#sorted
. Les paramètres implicites sont également utilisés pour transmettre des manifestes Array et des CanBuildFrom
instances.
Scala 2.8 permet une syntaxe abrégée pour les paramètres implicites, appelée Contexte Bounds. En bref, une méthode avec un paramètre de type A
qui nécessite un paramètre implicite de type M[A]
:
def foo[A](implicit ma: M[A])
peut être réécrit comme:
def foo[A: M]
Mais à quoi ça sert de passer le paramètre implicite sans le nommer? Comment cela peut-il être utile lors de la mise en œuvre de la méthode foo
?
Souvent, le paramètre implicite n'a pas besoin d'être référencé directement, il sera acheminé en tant qu'argument implicite vers une autre méthode appelée. Si nécessaire, vous pouvez toujours conserver la signature de méthode laconique avec le Contexte Bound et appeler implicitly
pour matérialiser la valeur:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passer un sous-ensemble de paramètres implicites explicitement
Supposons que vous appeliez une méthode qui imprime assez une personne, en utilisant une approche basée sur une classe de type:
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)
Et si nous voulons changer la façon dont le nom est affiché? Nous pouvons appeler PersonShow
explicitement, passer explicitement une alternative Show[String]
, mais nous voulons que le compilateur passe le Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Implicitly
est disponible dans Scala 2.8 et est défini dans Predef comme:Il est couramment utilisé pour vérifier si une valeur implicite de type
T
est disponible et la renvoyer si tel est le cas.Exemple simple de la présentation de retronym :
la source
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") )
, notamment pour récupérer un paramètre implicite introduit par un Contexte Bound:def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
Une réponse «apprenez-vous à pêcher» est d'utiliser l'index alphabétique des membres actuellement disponible dans les nightlies Scaladoc . Les lettres (et le
#
, pour les noms non alphabétiques) en haut du volet package / classe sont des liens vers l'index des noms de membres commençant par cette lettre (dans toutes les classes). Si vous choisissezI
, par exemple, vous trouverez l'implicitly
entrée avec une occurrence, dansPredef
, que vous pouvez visiter à partir du lien.la source
implicit
semble être une caractéristique importante du langage dans Scala, et certainement digne d'une explication appropriée. Penser que les documents ne détaillant qu'un nombre de signatures de type ressemble plus à une auto-satisfaction intellectuelle qu'à une véritable réponse. Voir les questions spécifiques posées par le PO - qu'est-ce que c'est et comment est-il utilisé? Ni répondu par cela, ni dans les documents nocturnes auxquels vous ne fournissez même pas de lien réel. scala-lang.org/files/archive/nightly/docs/library/… Cela n'apprend rien. Voir Niklaus Wirth ou Turbo Pascal pour des exemples de documents authentiques. -1implicit
etimplicitly
sont liés, mais assez distincts. Leimplicit
mot-clé fait partie de la langue.implicitly
est défini en code Scala simple dans la bibliothèque standard. Étant donné que les documents en ligne incluent des liens sources, je pense qu'il est toujours préférable de renvoyer les personnes interrogées vers ces documents et la source liée.