103 votes

Définir une fonction avec plusieurs arguments implicites en Scala

Comment puis-je définir une fonction avec plusieurs arguments implicites.

def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work

3 votes

Dans le texte de la question, vous posez une question sur une fonction. Dans votre extrait de code, vous avez une méthode. S'agit-il d'une fonction ou d'une méthode ?

202voto

missingfaktor Points 44003

Ils doivent tous être placés dans une liste de paramètres, et cette liste doit être la dernière.

def myfun(arg:String)(implicit p1: String, p2:Int)={}

1 votes

Si c'était une classe, la syntaxe serait la suivante : class MyClass ()(implicit p1 : String, implicit p2 : Int) { }

4voto

Mario Rossi Points 4527

Il existe en fait un moyen de faire exactement ce que le PO demande. C'est un peu compliqué, 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

En Scala 3 (alias "Dotty", bien que ce soit le nom du compilateur), au lieu de renvoyer un auxiliaire MyFunPart2 il est possible de retourner directement une valeur de fonction avec des arguments implicites. En effet, Scala 3 prend en charge les "fonctions implicites" (c'est-à-dire que l'implicite des paramètres fait désormais partie des types de fonctions). Les listes de paramètres implicites multiples deviennent si faciles à implémenter qu'il est possible que le langage les supporte directement, bien que je n'en sois pas sûr.

1voto

Mario Rossi Points 4527

Il existe un autre moyen (plus simple et plus souple, selon l'OMI) 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

Utiliser un Tuple comme représentation sous-jacente des paramètres n'est pas une bonne idée car les conversions implicites pourraient interférer avec d'autres utilisations. En fait, les conversions implicites vers n'importe quel type standard (y compris ceux des bibliothèques) 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 que l'on peut leur donner des noms beaucoup plus significatifs que _1 et _2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X