Question

I wrote a class which accepts a varargs as a parameter, and specify its default so that a user can often instantiate it without specifying a parameter:

class MyClass(values: Int* = 42) { }

However, the compiler and the REPL give me the following errors:

<console>:7: error: type mismatch;
 found   : Int(42)
 required: Int*
       class MyClass(values: Int* = 42) { }
                                ^
<console>:7: error: a parameter section with a `*'-parameter is not allowed to have default arguments
       class MyClass(values: Int* = 42) { }

As a workaround, I tried the following, but it didn't work either: (it's very ambiguous obviously.)

class MyClass(value: Int = 42, otherValues: Int*) { }

I wonder why it is unallowed to have the default for a varargs parameter. What is the reasoning or technical reason lying under here? (My guess is that specifying an empty varargs would require some special syntax or idiom, but I'm not sure if this is an enough reason.)

Was it helpful?

Solution

Thinking a bit about this, I think it is just a matter of not adding too much complexity, suppose you have

def f(a: A, xs: X* = Seq(x0, x1)) = ???

Now the caller uses like this: f(a).

How do we know if the caller intended to pass a zero-length list of X* or wanted to trigger the default arguments by not providing a X*? In your example you assume that the second alternative is the only case that will ever be and that the compiler needs to supply the default argument value. But an empty Seq() is already a perfectly valid value provided by the caller. I guess the caller could write f(a, Seq(): _*) but it is cumbersome.

OTHER TIPS

From scala specification (Section 4.6.2)

It is not allowed to define any default arguments in a parameter section with a repeated parameter

Maybe a workaround would help?

class MyClass(values: Int*) {
  def this() = this(5)
}

Varargs, not only in Scala, is an abstraction over a list of arguments, if i'm not mistaken it is desugared into Seq, a list of arguments. Deriving from this, what result do you expect from values: Int* = 42? And then, when you call this method, how arguments should be passed into this method?

Another workaround is to make the Seq explicit:

class MyClass(values: Seq[Int] = Seq(42)) { }

A default value to varargs just does not make sense, since you can not figure out how many arguments should be passed. This is not a limitation of scala, this is a logical limitation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top