Scala-lang reference 5.5.1 and 6.6.1 gave me the impression that a default parameter would be able to refer to a previously evaluated one:
class Test(val first: String, val second: String = first)
but from experimenting it seems the only way to do this is to use the form:
class Test(val first: String)(val second: String = first)
and then define an auxiliary constructor or a creational companion class to avoid specifying the second set of brackets when creating. I don't really understand how this second constructor works, it looks like a curried function so I might guess that it is necessary to evaluate first
independently of second
, is this correct? Is this form necessary or is there some syntatic sugar I can use to tweak the first constructor into doing what I want?
As Travis Brown points out, you can indeed only refer to a previous argument in a default expression when it is from a previous argument list (so you do need to currify).
Now, regarding your particular use case, default arguments and method overloading are sometimes two ways of achieving the same thing.
I think the simplest solution to your scenario is simply to define Test
as follows:
class Test(val first : String, val second : String) {
def this(f : String) = this(f, f)
}
If you want to make it more complicated, an alternative way, using a companion object:
class Test(val first : String)(val second : String = first)
object Test {
def apply(f : String) = new Test(f)
def apply(f : String, s : String) = new Test(f)(s)
}
(A small difference is that now you create objects without new
.)
What you cannot do, is define it as:
class Test(val first : String)(val second : String = first) {
def this(f : String, s : String) = this(f)(s)
}
...because the curried version gets translated into (among other things) a method with the same signature as the overloaded contructor.