Rich
Rich

Reputation: 15448

Make constructor params implicitly available in class body

I would like to make the explicit constructor parameters of my class implicitly available in the class body.

I can mark the second and subsequent parameters as "implicit val", which works:

scala> class Foo(x: Int, implicit val y: String) {
     |   println(implicitly[String])
     | }
defined class Foo

scala> new Foo(1,"hello")
hello

but if I mark the first parameter as implicit, then Scala thinks I am marking the whole argument list as an implicit argument list, and adds an empty first argument list:

scala> class Bar(implicit val x: Int, y: String) {
     |   println(implicitly[Int])
     | }
defined class Bar

scala> new Bar(1,"hello")
<console>:9: error: too many arguments for constructor Bar: ()(implicit x: Int, implicit y: String)Bar
              new Bar(1,"hello")
              ^

Is there any way to make the first explicit constructor argument explicitly in scope?

Upvotes: 1

Views: 525

Answers (3)

csgero
csgero

Reputation: 2773

class Foo(x: Int, y: String) {
  implicit val xImp = x

  println(implicitly[Int])
}

Actually I would do it similarly for the first case too. This is a situation where I think that the lot more understandable code is worth a bit more verbosity:

class Foo(x: Int, y: String) {
  implicit val yImp = y

  println(implicitly[String])
}

Upvotes: 1

wingedsubmariner
wingedsubmariner

Reputation: 13667

You can make it implicitly available by using an implicit def inside:

class Foo(val x: Int, implicit val y: String) {
    implicit def ix = x
}

which is hideously verbose, but it doesn't look like there is another way to get around the ambiguity between implicit marking a parameter list implicit and implicit val marking an implicit field.

Upvotes: 1

som-snytt
som-snytt

Reputation: 39577

I would have said, Add other local modifiers:

scala> class Foo(@deprecated("","") private implicit val x: Int, val y: String) { println(implicitly[Int]) }
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
defined class Foo

scala> new Foo(42, "hi")
<console>:9: error: too many arguments for constructor Foo: ()(implicit x: Int, y: String)Foo
              new Foo(42, "hi")
              ^

Syntactically, that's different from the leading implicit keyword, so maybe it's a parser bug, or maybe it does distinguish an implicit param list from a leading param marked locally-implicit but doesn't use the difference.

Upvotes: 1

Related Questions