Consider the following REPL session:
@ def test[C[X] <: TraversableOnce[X]](implicit cbf: CanBuildFrom[C[Int], Int, C[Int]]) = cbf()
defined function test
@ test[List]
res32: collection.mutable.Builder[Int, List[Int]] = ListBuffer()
@ def test[C[X] <: TraversableOnce[X]] = implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
cmd33.sc:1: Cannot construct a collection of type C[Int] with elements of type Int based on a collection of type C[Int].
def test[C[X] <: TraversableOnce[X]] = implicitly[CanBuildFrom[C[Int], Int, C[Int]]]
^
Compilation Failed
The first definition of test function compiles and works, while the second one doesn't compile. The only difference between them is the way how the instance of CanBuildFrom is obtained. In first case it's declared as implicit parameter, requiring the compiler to find one. In second case it's invoked via implicitly function, which, in theory, should behave the same in terms of implicit search scope. What causes this behavior?
The definition of
implicitly(inPredef) is:It simply makes explicit to you an implicit already in scope (at the use site).
Now when you write this:
You are asking the caller to provide an implicit (at the call site).
When you write
You are asking the compiler with the call
implicitlyto look-up an implicit already in scope. But you are not having any implicit of the given type in scope! So the two definitions oftestare doing something entirely different.You use
implicitlynormally to get hold of an implicit to which you don't have the name, because it was specified using the context-bounds or type-class notation, likedef test[A: TypeClass]. You cannot use that notation here becauseCanBuildFromhas three type parameters and not one. So you cannot do much withimplicitlyhere.You could use
implicitlywith your first case:But then you already know that you have that implicit with name
cbf...Note that you can get hold of an implicit
CanBuildFromfor a known collection type:But this doesn't work if your collection type (
C[X]) is abstract.