Як я можу визначити функцію з кількома неявними аргументами.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Як я можу визначити функцію з кількома неявними аргументами.
def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work
Відповіді:
Усі вони повинні входити до одного списку параметрів, і цей список повинен бути останнім.
def myfun(arg:String)(implicit p1: String, p2:Int)={}
Насправді існує спосіб робити саме те, що вимагає ОП. Трохи перекручений, але це працює.
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
У Scala 3 (він же "Dotty", хоча це ім'я компілятора) замість повернення допоміжного об'єкта MyFunPart2 можливо повернути значення функції з неявними аргументами безпосередньо. Це тому, що Scala 3 підтримує "Неявні функції" (тобто "неявність параметрів" зараз є частиною типів функцій). Кілька неявних списків параметрів стають настільки простими для реалізації, що можливо, мова буде підтримувати їх безпосередньо, хоча я не впевнений.
Існує ще один (більш простий і гнучкий) режим IMO для досягнення подібного ефекту:
// 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
Використання Tuple як основного подання для параметрів не є гарною ідеєю, оскільки неявні перетворення можуть заважати іншим способам використання. Насправді неявні перетворення в будь-який стандартний тип (включаючи бібліотечні) зазвичай створюють проблеми в будь-якому нетривіальному додатку. Рішення полягає у створенні виділеного класу випадків, щоб утримувати параметри замість Tuple. Важливою перевагою є те, що їм можна було назвати набагато більш значущі імена, ніж _1 та _2.