การกำหนดฟังก์ชันที่มีอาร์กิวเมนต์โดยนัยหลายรายการใน Scala


95

ฉันจะกำหนดฟังก์ชันที่มีอาร์กิวเมนต์หลายนัยได้อย่างไร

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

3
ในข้อความคำถามคุณกำลังถามเกี่ยวกับฟังก์ชัน ในข้อมูลโค้ดของคุณคุณมีวิธีการ คุณกำลังถามเกี่ยวกับฟังก์ชันหรือวิธีการหรือไม่?
Jörg W Mittag

คำตอบ:


190

โดยทั้งหมดจะต้องอยู่ในรายการพารามิเตอร์เดียวและรายการนี้ต้องเป็นรายการสุดท้าย

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

1
ถ้าเป็นคลาสไวยากรณ์จะเป็นคลาส MyClass () (implicit p1: String, implicit p2: Int) {}
skjagini

2

มีวิธีการทำตามที่ 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" เป็นส่วนหนึ่งของประเภทฟังก์ชัน) รายการพารามิเตอร์โดยนัยหลายรายการกลายเป็นเรื่องง่ายที่จะใช้งานซึ่งเป็นไปได้ว่าภาษาจะรองรับโดยตรงแม้ว่าฉันจะไม่แน่ใจ


1

มีอีกวิธีหนึ่ง (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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.