Why is it impossible to specify the default value of a Scala varargs parameter?
Asked Answered
B

5

6

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.)

Bosk answered 20/8, 2013 at 7:10 Comment(0)
P
8

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.

Pelaga answered 20/8, 2013 at 13:9 Comment(3)
Why def foo(result: Int = 0, xs: String*) = ??? is not acceptable then? It is perfectly feasible for the compiler to recognize foo(0, "impossible to compile") as a legal construction.Krasnoyarsk
@om-nom-nom, not sure I follow you. I am answering why we may not want to support def foo(result: Int = 0, xs: String* = Seq("some", "default")) = ???.Pelaga
yep, but compiler puts the very same restriction in my case (at least gives us the same compile error), so I guess there might be some other reason that unifies those two casesKrasnoyarsk
A
6

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)
}
Availability answered 20/8, 2013 at 7:19 Comment(1)
It doesn't explains why it is so, just postulates such denial.Krasnoyarsk
A
3

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?

Anglice answered 20/8, 2013 at 7:15 Comment(1)
But you could atleast do values: Int* = (Array(42): Int* )Whisky
F
2

Another workaround is to make the Seq explicit:

class MyClass(values: Seq[Int] = Seq(42)) { }
Freemanfreemartin answered 20/8, 2013 at 7:20 Comment(0)
H
2

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.

Hamster answered 20/8, 2013 at 8:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.