Scala:隐式传递一个隐式参数,显式传递另一个。是否可以?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22552985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:07:23  来源:igfitidea点击:

Scala: Passing one implicit parameter implicitly and the other explicitly. Is it possible?

scalaimplicit

提问by jhegedus

Let's consider the function:

让我们考虑一下函数:

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

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

Now, let us assume that there is an implicit Stringand Int(implicit val i1=1) in scope but we want to pass an other, notimplicit Int(val i2=2) explicitly to foo.

现在,让我们假设在作用域中有一个隐式Stringand Int( implicit val i1=1) 但我们想将另一个而不是隐式Int( val i2=2) 显式传递给foo

How can we do that ? Is it possible? Thanks for reading.

我们怎么做?是否可以?谢谢阅读。

回答by Peter Schmitz

All I can add is:

我只能补充的是:

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

回答by Peter Schmitz

In case your method has many implicit parameters (I sometimes have in my projects) and you sometimes want to just specify one of them explicit and let the others been resolved implicitly you can write implicitlyfor every other parameter like showed in my other answer. But sometimes you will change the signature of that method or the explicit parameter is in the middle of that parameter list, then you can make more readable client code with the following construct:

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

Suppose you have some types and their implicit dummy objects:

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

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

Now you have your method foo1that uses these implicits:

现在您拥有foo1使用这些隐式的方法:

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

Now you often want to explicitly specify i4: I4. So you write:

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

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

Ugly!
With the following (should be placed in tight scope to method foo2and perhaps renamed) wrapper for all implicits:

丑陋的!
使用以下(应放置在方法的紧密范围内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)

and the related method foo2:

和相关方法foo2

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

you can now call foo2instead of foo1the following way:

您现在可以调用foo2而不是foo1以下方式:

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

回答by Bruno Grieder

  1. Explicitly call foo(i2, s1)but you loose the benefit of the use of the implicit String
  2. Define def foo1(a: Int)(implicit b: String)=foo(a,b)and you call foo1(i2)
  1. 显式调用,foo(i2, s1)但您失去了使用implicit String
  2. 定义def foo1(a: Int)(implicit b: String)=foo(a,b)并调用foo1(i2)

回答by Suma

You can create a new inner scope and define a new implicit valin it. The advantage is than when you have multiple function calls, this way you can override the one implicit for all of them in one place:

您可以创建一个新的内部作用域并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

}

Note: the new implicit must have the same variable name as the original one, so that it hides it, otherwise you will get a compiler error about ambiguous implicit values.

注意:新的隐式变量名必须与原始变量名相同,以便将其隐藏,否则您将收到关于不明确的隐式值的编译器错误。

回答by roterl

I know it's an old question but it still may be interesting. A nice way to do it is using implicitly as a default value:

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

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)