【问题标题】:Defining a function with multiple implicit arguments in Scala在 Scala 中定义具有多个隐式参数的函数
【发布时间】:2019-08-11 20:29:14
【问题描述】:

如何定义具有多个隐式参数的函数。

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

【问题讨论】:

  • 在问题文本中,您询问的是一个函数。在您的代码 sn-p 中,您有一个方法。你问的是函数还是方法?

标签: scala


【解决方案1】:

它们都必须放在一个参数列表中,并且这个列表必须是最后一个。

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

【讨论】:

  • 如果它是一个类,语法应该是 class MyClass ()(implicit p1: String,implicit p2: Int) { }
【解决方案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 支持“隐式函数”(即“参数隐式”现在是函数类型的一部分)。多个隐式参数列表变得非常容易实现,以至于语言可能会直接支持它们,尽管我不确定。

【讨论】:

    【解决方案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
    

    使用元组作为参数的底层表示不是一个好主意,因为隐式转换可能会干扰其他用途。实际上,对任何标准类型(包括库类型)的隐式转换通常会给任何非平凡的应用程序带来麻烦。解决方案是创建一个专用案例类来保存参数而不是元组。一个重要的优势是它们可以被赋予比 _1 和 _2 更有意义的名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多