Come posso definire una funzione con più argomenti impliciti.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Come posso definire una funzione con più argomenti impliciti.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Risposte:
Devono essere inseriti tutti in un elenco di parametri e questo elenco deve essere l'ultimo.
def myfun(arg:String)(implicit p1: String, p2:Int)={}
In realtà c'è un modo per fare esattamente ciò che richiede l'OP. Un po 'contorto, ma funziona.
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
In Scala 3 (noto anche come "Dotty", sebbene questo sia il nome del compilatore) invece di restituire un oggetto MyFunPart2 ausiliario , è possibile restituire direttamente un valore di funzione con argomenti impliciti. Questo perché Scala 3 supporta le "funzioni implicite" (cioè "il parametro implicito" ora fa parte dei tipi di funzione). Più elenchi di parametri impliciti diventano così facili da implementare che è possibile che il linguaggio li supporti direttamente, anche se non ne sono sicuro.
C'è un altro modo (IMO più semplice e più flessibile) per ottenere un effetto simile:
// 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
Usare una tupla come rappresentazione sottostante per i parametri non è una buona idea perché le conversioni implicite potrebbero interferire con altri usi. In realtà, le conversioni implicite a qualsiasi tipo standard (comprese quelle di libreria) di solito creano problemi in qualsiasi applicazione non banale. La soluzione è creare una classe case dedicata per contenere i parametri invece di una tupla. Un vantaggio importante è che potrebbero essere assegnati nomi molto più significativi di _1 e _2.