Inférence implicite dans Scala

De nombreux développeurs débutants et non Scala considÚrent les implicites comme une fonctionnalité modérément utile. L'utilisation est généralement limitée au passage ExecutionContext



 Ă  Future



. D'autres évitent l'implicite et considÚrent l'opportunité comme nuisible.





Un code comme celui-ci fait peur Ă  beaucoup de gens:





implicit def function(implicit argument: A): B
      
      



Mais je pense que ce mécanisme est un avantage important de la langue, voyons pourquoi.





En bref sur les implicites

En général, implicits est un mécanisme de complétion automatique du code lors de la compilation:





  • pour les arguments implicites, la valeur est automatiquement substituĂ©e





  • pour les conversions implicites, la valeur est automatiquement encapsulĂ©e dans un appel de mĂ©thode





Je n'entrerai pas dans ce sujet, qui sont intéressés à regarder cette vidéo du créateur de la langue . En bref, ce mécanisme est utilisé dans plusieurs cas différents (et dans Scala 3 sera divisé en plusieurs fonctionnalités distinctes):





  1. Passer un contexte implicite (comme ExecutionContext



    )





  2. Conversions implicites (obsolĂštes)





  3. Méthodes d'extension (sucre syntaxique pour ajouter des méthodes à des types existants)





  4. Classes de type et résolution implicite





Classes de type et inférence implicite

En elles-mĂȘmes, les classes de types n'apportent aucune nouveautĂ© ou rĂ©volution - elles sont simplement l'implĂ©mentation de mĂ©thodes "pour" le type, et non "dans" le type lui-mĂȘme, c'est comme la diffĂ©rence entre Comparable



 & Ordering



( Comparator



 en Java):





Comparable



  :





class Person(age: Int) extends Comparable[Person] {
  override def compareTo(o: Person): Int = age compareTo o.age
}
def max[T <: Comparable[T]](xs: Iterable[T]): T = xs.reduce[T] {
  case (a, b) if (a compareTo b) < 0 => b
  case (a, _) => a
}
      
      



Ordering



  , :





case class Person(age: Int)

implicit object ByAgeOrdering extends Ordering[Person] {
  override def compare(o1: Person, o2: Person): Int = o1.age compareTo o2.age
}
def max[T: Ordering](xs: Iterable[T]): T = xs.reduce[T] {
  case (a, b) if Ordering[T].lt(a, b) => b
  case (a, _) => a
}
// is syntactic sugar for
def max[T](xs: Iterable[T])(implicit evidence: Ordering[T]): T = ...
      
      



.





. :





implicit val value: A = ???
implicit def definition: B = ???
implicit def conversion(argument: C): D = ???
implicit def function(implicit argument: E): F = ???
      
      



? conversion



, , : value



, definition



 & function



  . : val



 , def



  . – .





– , , .





– , – , :





implicit def pairOrder[A: Ordering, B: Ordering]: Ordering[(A, B)] = {
  case ((a1, b1), (a2, b2)) if Ordering[A].equiv(a1, a2) => Ordering[B].compare(b1, b2)
  case ((a1,  _), (a2,  _)) => Ordering[A].compare(a1, a2)
}
// again, just syntactic sugar for:
implicit def pairOrder[A, B](implicit a: Ordering[A], b: Ordering[B]): Ordering[(A, B)] = ...
      
      



, :





val values = Seq(
  (Person(30), ("A", "A")),
  (Person(30), ("A", "B")),
  (Person(20), ("A", "C"))
)
max(values) // => (Person(30),(A,B))
      
      



Seq[(Person, (String, String))]



  Ordering



  :





max(values)(
  pairOrder(
    ByAgeOrdering, 
    pairOrder(Ordering.String, Ordering.String)
  )
)
      
      



Ainsi, l'infĂ©rence implicite vous permet de dĂ©crire des rĂšgles d'infĂ©rence gĂ©nĂ©rales et de demander au compilateur de combiner ces rĂšgles ensemble et d'obtenir une implĂ©mentation spĂ©cifique de la classe de type. L'ajout de votre propre type ou de vos propres rĂšgles n'a pas besoin de tout dĂ©crire depuis le dĂ©but - le compilateur combinera tout lui-mĂȘme pour obtenir l'objet souhaitĂ©.





Et surtout, si le compilateur échoue, vous recevrez une erreur de compilation, pas une erreur d'exécution, et vous pourrez résoudre le problÚme immédiatement. Bien que, bien sûr, il y ait une mouche dans la pommade dans la pommade - si le compilateur a échoué, vous ne savez pas quel lien dans la chaßne manquait - il n'est pas toujours facile de déboguer cela.





Espérons que l'implicite est maintenant un peu plus explicite.








All Articles