Scala:隐式传递一个隐式参数,另一个显式传递。可能吗?

时间:2014-03-21 07:43:46

标签: scala implicit

让我们考虑一下这个功能:

def foo(implicit a:Int, b:String) = println(a,b)

现在,让我们假设范围内存在隐式StringIntimplicit val i1=1),但我们希望传递另一个隐式Intval i2=2)明确指向foo

我们怎么能这样做?可能吗? 谢谢你的阅读。

5 个答案:

答案 0 :(得分:30)

我可以添加的是:

def foo(implicit a: Int, b: String) = println(a, b)
implicit val i1 = 1
implicit val s = ""
val i2 = 2
foo(i2, implicitly[String])

答案 1 :(得分:5)

如果您的方法有很多隐式参数(我有时会在我的项目中),并且您有时只想明确指定其中一个参数并隐式解析其他参数,您可以为其他每个参数编写implicitly在我的另一个答案中显示。但有时您会更改该方法的签名或显式参数位于该参数列表的中间,然后您可以使用以下构造生成更具可读性的客户端代码:

假设您有一些类型及其隐式虚拟对象:

trait I1; implicit object I1 extends I1
trait I2; implicit object I2 extends I2
trait I3; implicit object I3 extends I3
trait I4; implicit object I4 extends I4
trait I5; implicit object I5 extends I5
trait I6; implicit object I6 extends I6

现在您的方法foo1使用了这些含义:

def foo1(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) {
  println(i1, i2, i3, i4, i5, i6)
}

现在您经常要明确指定i4: I4。所以你写道:

val i4 = new I4 {}
foo1(implicitly, implicitly, implicitly, i4, implicitly, implicitly)

难看!
使用以下内容(应该放在方法foo2的紧密范围内,并且可能已重命名)包含所有含义:

object Implicits {
  def apply(i4: I4)(implicit i1: I1, i2: I2, i3: I3, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
  implicit def applying(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
}
class Implicits(val i1: I1, val i2: I2, val i3: I3, val i4: I4, val i5: I5, val i6: I6)

以及相关方法foo2

def foo2(implicit implicits: Implicits) = {
  import implicits._
  println(i1, i2, i3, i4, i5, i6)
}

您现在可以通过以下方式拨打foo2而不是foo1

locally {
  foo2 // using implicit dummy objects I1, ..., I6 from above
  // or with explicit I4:
  val i4 = new I4 {}
  foo2(Implicits(i4))
}

答案 2 :(得分:4)

  1. 明确致电foo(i2, s1),但您放弃了使用implicit String
  2. 的好处
  3. 定义def foo1(a: Int)(implicit b: String)=foo(a,b),然后致电foo1(i2)

答案 3 :(得分:2)

您可以创建新的内部范围并在其中定义新的implicit val。优点是当你有多个函数调用时,这样你就可以在一个地方覆盖所有函数调用的隐含函数:

def foo(implicit a:Int, b:String) = println(a,b).

implicit val i = 1
implicit val s = ""

foo // call with original implicits

{
  implicit val i = 2

  foo // call with a new Int implicit

  foo // call with a new Int implicit again

}

注意:新的隐式变量必须与原始变量名具有相同的变量名,因此它会隐藏它,否则您将收到有关模糊隐式值的编译器错误。

答案 4 :(得分:-1)

我知道这是一个古老的问题,但它仍然可能很有趣。 一个很好的方法是隐式使用默认值:

scala> def foo(a: Int = implicitly[Int], b: String = implicitly[String]) = println(a,b)

scala> foo()
(10,boo)

scala> foo(50)
(50,boo)

scala> foo(b="bar")
(10,bar)