Scala Puzzlers, des pièges avec Scala ?
Quelques petites bizarreries ou astuces, issues de mon expérience. Je vous encourage à réfléchir un
peu avant de tester dans le REPL. Et j’en profite pour vous donner une petite astuce que je viens de
découvrir : :paste
permet de coller plusieurs lignes dans le REPL.
Division par zéro
Commençons par une venant de Java :
0/0
0d/0
Qu’affichent ces deux lignes ?
La première ligne lève une java.lang.ArithmeticException
alors que la deuxième affiche NaN
. Cela
peut paraitre étrange mais c’est conforme au standard IEEE
754 pour la représentation des nombres à virgule flottante.
NaN est le résultat d’une opération invalide.
Pattern matching
Considérons la méthode suivante :
def f(a: Any) = a match {
case ints: List[Int] => println("int")
case strs: List[String] => println("string")
}
Qu’affiche le code suivant ?
f(List(42))
f(List("scala.io"))
Les deux lignes affichent int
. Le pattern matching est fait à l’exécution, l’information de type
n’est donc plus disponible en raison du type erasure de la JVM.
Pattern matching
case class A(x: Int, y: Int)
def f: A => Int = { a => a.x + a.y }
def g: A => Int = { case A(x, y) => x + y }
Qu’affiche le code suivant ?
f(A(21, 21))
g(A(21, 21))
Même si la syntaxe de la deuxième méthode est surprenante, les deux méthodes sont équivalentes. Scala permet d’utiliser le pattern matching, et donc la déstructuration pour les paramètres d’entrée d’une fonction anonyme.
Un pattern courant
object Action { def apply(f: String => Int) = { s: String => println("s = " + f(s)) } }
val f = Action { _.length }
val g = Action { _.toInt }
Qu’affiche le code suivant ?
f("42")
g("42")
Cette astuce combine l’appel implicite de la méthode apply
du companion object, qui est une HOF
car elle retourne une méthode. Cela permet d’implémenter élégamment le design pattern Template
method.
Collection
Que renvoie le code suivant ?
Array(42) == new Array(42)
Et oui, cela renvoie false
. À gauche, cela appelle la méthode apply
du companion object de
Array
, qui créé un Array[Int]
avec un seul élément. À droite, ça appelle le constructeur de
Array
qui créé un tableau de taille 42.
Collection
Que font ces deux lignes ?
val l : List[Any] = List[Int]()
val a : Array[Any] = Array[Int]()
La première ligne ne pose pas de problème. En revanche, la deuxième ligne ne compile pas car le type
Array
est invariant.
PS: Les plus attentifs auront surement remarqué une publicité subliminale.