17

How can a parameter's default value reference another parameter? If it cannot, how to work around that?

case class A(val x:Int, val y:Int = x*2)

Error (reasonably enough):

scala> case class B(val x:Int, val y:Int = x*2)
<console>:7: error: not found: value x
   case class B(val x:Int, val y:Int = x*2)
                                       ^
Dominykas Mostauskis
  • 7,797
  • 3
  • 48
  • 67

2 Answers2

25

This requires that you use multiple parameter lists:

case class A(x: Int)(y: Int = x*2)

Default values can only refer to parameters in preceding lists.

Be careful however with case classes, because their equality only takes into the account the first parameter list, therefore:

A(1)() == A(1)(3)  // --> true!!
0__
  • 66,707
  • 21
  • 171
  • 266
  • 2
    Nice answer. That's quite a gotcha when using case classes, and it's still not fixed as of 2.11.6. – Brent Faust Jun 02 '15 at 18:12
  • 2
    Actually, I consider it a useful feature to be able define parameters that do not participate in equality and hash. – 0__ Jun 03 '15 at 10:12
10

Since you asked for the work-around, if it's not obvious how to preserve caseness:

scala> :pa
// Entering paste mode (ctrl-D to finish)

case class Foo(x: Int, y: Int)
object Foo {
  def apply(x: Int): Foo  = apply(x, 2*x)
}

// Exiting paste mode, now interpreting.

defined class Foo
defined object Foo

scala> Foo(5,6)
res45: Foo = Foo(5,6)

scala> Foo(5)
res46: Foo = Foo(5,10)
som-snytt
  • 39,429
  • 2
  • 47
  • 129