问题
Let's consider the function:
def foo(implicit a:Int, b:String) = println(a,b)
.
Now, let us assume that there is an implicit String
and Int
(implicit val i1=1
) in scope but we want to pass an other, not implicit Int
(val i2=2
) explicitly to foo
.
How can we do that ? Is it possible? Thanks for reading.
回答1:
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])
回答2:
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 implicitly
for 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:
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 foo1
that uses these implicits:
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:
val i4 = new I4 {}
foo1(implicitly, implicitly, implicitly, i4, implicitly, implicitly)
Ugly!
With the following (should be placed in tight scope to method foo2
and perhaps renamed) wrapper for all implicits:
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
:
def foo2(implicit implicits: Implicits) = {
import implicits._
println(i1, i2, i3, i4, i5, i6)
}
you can now call foo2
instead of foo1
the following way:
locally {
foo2 // using implicit dummy objects I1, ..., I6 from above
// or with explicit I4:
val i4 = new I4 {}
foo2(Implicits(i4))
}
回答3:
- Explicitly call
foo(i2, s1)
but you loose the benefit of the use of theimplicit String
- Define
def foo1(a: Int)(implicit b: String)=foo(a,b)
and you callfoo1(i2)
回答4:
You can create a new inner scope and define a new implicit val
in 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:
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.
回答5:
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)
来源:https://stackoverflow.com/questions/22552985/scala-passing-one-implicit-parameter-implicitly-and-the-other-explicitly-is-it