Jak mogę zdefiniować funkcję z wieloma niejawnymi argumentami.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Jak mogę zdefiniować funkcję z wieloma niejawnymi argumentami.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Odpowiedzi:
Wszystkie muszą znajdować się na jednej liście parametrów, a ta lista musi być ostatnią.
def myfun(arg:String)(implicit p1: String, p2:Int)={}
W rzeczywistości istnieje sposób na zrobienie dokładnie tego, czego wymaga PO. Trochę zawiłe, ale działa.
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
W Scali 3 (aka „Dotty”, chociaż jest to nazwa kompilatora) zamiast zwracać pomocniczy obiekt MyFunPart2 , możliwe jest bezpośrednie zwrócenie wartości funkcji z niejawnymi argumentami. Dzieje się tak, ponieważ Scala 3 obsługuje „Niejawne funkcje” (tj. „Niejawność parametrów” jest teraz częścią typów funkcji). Wiele niejawnych list parametrów staje się tak łatwe do zaimplementowania, że jest możliwe, że język będzie je obsługiwał bezpośrednio, chociaż nie jestem pewien.
Istnieje inny (prostszy i bardziej elastyczny IMO) sposób na osiągnięcie podobnego efektu:
// 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
Używanie krotki jako podstawowej reprezentacji parametrów nie jest dobrym pomysłem, ponieważ niejawne konwersje mogą kolidować z innymi zastosowaniami. W rzeczywistości niejawne konwersje na dowolny typ standardowy (w tym biblioteki) zwykle powodują problemy w każdej nietrywialnej aplikacji. Rozwiązaniem jest utworzenie dedykowanej klasy przypadku do przechowywania parametrów zamiast krotki. Ważną zaletą jest to, że można by nadać im nazwy znacznie bardziej znaczące niż _1 i _2.