goo
goo

Reputation: 2280

Setting a default param as the value of another param

In Scala, I can set default params:

case class Foo(a:String, b:String = "hey")

What I would like to do is something like this:

case class Foo(a:String, b:String = a)

But that would result in an error:

not found: value a

This would be very useful in cases like these:

case class User(createdAt:DateTime = DateTime.now, updatedAt:DateTime = createdAt)

case class User(id:Long, profileName:String = "user-" + id.toString)

Upvotes: 2

Views: 186

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170713

You can do it if they are in separate parameter lists:

case class Foo(a:String)(b:String = a)

Unfortunately, this works fine for methods and normal classes, but is not what you want for case classes: all methods defined automatically will only take first argument list into account!

scala> case class Foo(a:String)(b:String = a)
defined class Foo

scala> Foo("a")("b") == Foo("a")("c")
res0: Boolean = true

scala> Foo("a")("b")
res1: Foo = Foo(a)

However, you can define the apply method manually:

case class Foo(a:String, b:String)

object Foo {
  def apply(a:String)(b:String = a)(implicit d:DummyImplicit): Foo = new Foo(a, b)
}

scala> Foo("a")()
res2: Foo = Foo(a,a)

Upvotes: 1

Spectre
Spectre

Reputation: 658

Sadly Scala doesn't allow that kind of usage. A rather verbose way to achieve the desired result would be to resort to using overloaded constructors:

class User(createdAt: DateTime, updatedAt: DateTime) {

  // No argument constructor
  def this() = this(DateTime.now, DateTime.now)

  // One argument constructor
  def this(createdAt: DateTime) = this(createdAt, createdAt)
}

// If using a case class you would want to overload the apply method as well
object User {
  def apply() = new User(DateTime.now, DateTime.now)
  def apply(createdAt: DateTime) = new User(createdAt, createdAt)
  def apply(createdAt: DateTime, updatedAt: DateTime) = new User(createdAt, updatedAt)
}

// Usage
User()                 // Both createdAt and updatedAt are DateTime.now
User(myDate)           // Both createdAt and updatedAt are myDate
User(myDate1, myDate2) // createdAt is myDate1, updatedAt is myDate2

Overload constructors were the pre 2.8 method for having almost default parameters, and are also the way of providing them in Java.

Upvotes: 4

Related Questions