Comment puis-je définir une fonction avec plusieurs arguments implicites.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Comment puis-je définir une fonction avec plusieurs arguments implicites.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Réponses:
Il existe en fait un moyen de faire exactement ce que le PO exige. Un peu alambiqué, mais ça marche.
class MyFunPart2(arg: String, /*Not implicit!*/ p1: String) {
def apply(implicit p2: Int) = {
println(arg+p1+p2)
/* otherwise your actual code */
}
}
def myFun(arg: String)(implicit p1: String): MyFunPart2= {
new MyFunPart2(arg, p1)
}
implicit val iString= " world! "
implicit val iInt= 2019
myFun("Hello").apply
myFun("Hello")(" my friend! ").apply
myFun("Hello")(" my friend! ")(2020)
// Output is:
// Hello world! 2019
// Hello my friend! 2019
// Hello my friend! 2020
Dans Scala 3 (alias "Dotty", bien que ce soit le nom du compilateur) au lieu de renvoyer un objet MyFunPart2 auxiliaire , il est possible de renvoyer directement une valeur de fonction avec des arguments implicites. Ceci est dû au fait que Scala 3 prend en charge les «fonctions implicites» (c'est-à-dire que le paramètre implicitness fait désormais partie des types de fonction). Plusieurs listes de paramètres implicites deviennent si faciles à implémenter qu'il est possible que le langage les supporte directement, bien que je ne sois pas sûr.
Il existe un autre moyen (IMO plus simple et plus flexible) d'obtenir un effet similaire:
// Note the implicit is now a Tuple2
def myFun(arg: String)(implicit p: (String, Int) ): Unit = {
println(arg + p._1 + p._2)
/*otherwise your actual code*/
}
// These implicit conversion are able to produce the basic implicit (String,Int) Tuples
implicit def idis(implicit is: String, ii: Int): (String,Int)= (is,ii)
implicit def idi(s: String)(implicit ii: Int): (String,Int)= (s,ii)
// The basic implicit values for both underlying parameters
implicit val iString = " world! "
implicit val iInt = 2019
myFun("Hello")
myFun("Hello")(" my friend! ")
myFun("Hello")(" my friend! ",2020)
// Output is:
// Hello world! 2019
// Hello my friend! 2019
// Hello my friend! 2020
// If we add the following implicit,
implicit def ids(i: Int)(implicit is: String)= (is,i)
// we can even do
myFun("Hello")(2020)
// , and output is:
// Hello world! 2020
L'utilisation d'un Tuple comme représentation sous-jacente des paramètres n'est pas une bonne idée car les conversions implicites peuvent interférer avec d'autres utilisations. En fait, les conversions implicites vers n'importe quel type standard (y compris ceux de bibliothèque) créent généralement des problèmes dans toute application non triviale. La solution consiste à créer une classe de cas dédiée pour contenir les paramètres au lieu d'un Tuple. Un avantage important est qu'ils pourraient recevoir des noms beaucoup plus significatifs que _1 et _2.