ฉันจะกำหนดฟังก์ชันที่มีอาร์กิวเมนต์หลายนัยได้อย่างไร
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)={}
มีวิธีการทำตามที่ OP ต้องการจริงๆ ซับซ้อนเล็กน้อย แต่ได้ผล
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 รองรับ "Implicit Functions" (กล่าวคือตอนนี้ "parameter implicitness" เป็นส่วนหนึ่งของประเภทฟังก์ชัน) รายการพารามิเตอร์โดยนัยหลายรายการกลายเป็นเรื่องง่ายที่จะใช้งานซึ่งเป็นไปได้ว่าภาษาจะรองรับโดยตรงแม้ว่าฉันจะไม่แน่ใจ
มีอีกวิธีหนึ่ง (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 เป็นตัวแทนพื้นฐานสำหรับพารามิเตอร์ไม่ใช่ความคิดที่ดีเนื่องจากการแปลงโดยนัยอาจรบกวนการใช้งานอื่น ๆ ที่จริงแล้วการแปลงโดยปริยายเป็นประเภทมาตรฐานใด ๆ (รวมถึงไลบรารี) มักจะสร้างปัญหาในแอปพลิเคชันที่ไม่สำคัญ วิธีแก้ปัญหาคือสร้างคลาสเคสเฉพาะเพื่อเก็บพารามิเตอร์แทนทูเพิล ข้อได้เปรียบที่สำคัญคือสามารถตั้งชื่อให้มีความหมายมากกว่า _1 และ _2