Case class does not have copy method!

This code works fine in both Scala 2.13.16 and Scala 3.7.0:

case class Node( s: String, seq: Seq[Int])
val n = Node( "once", Seq( 9) )
val ncp = n.copy( s = "twice")

However, if I change the type of the second parameter, seq, from Seq[Int] to Int* (see the code below) I get the following error in the last sentence: “value copy is not a member of Node”.
This error happens in both Scala 2 and Scala 3.

case class Node( s: String, seq: Int*)
val n = Node( "once", Seq(9)* )     // Scala 3
val n = Node( "once", Seq(9): _* )  // Scala 2
val ncp = n.copy( s = "twice")

Is there any reason why case class Node has no copy method when the second parameter is of type Int*?

As specified:

A method named copy is implicitly added to every case class, unless the class already has a member with that name, whether directly defined or inherited. The copy method is also omitted if the class is abstract, or if the class has a repeated parameter.

There is an old ticket where the issue seems to have crossed with whether copy supports case classes with multiple parameter lists.

I assume the reason is that you would have to awkwardly supply a Seq.

Inside a method, a repeating parameter is a Seq, but this detail is not visible outside, except in the signature of unapplySeq, or when a method is eta-expanded.

I don’t know whether that is an excellent reason.

A similar feature restriction that was relaxed in Scala 3 is by-name repeated parameters:

scala> def f(i: => Int*) = i.sum
def f(i: => Int*): Int

I guess that is a by-name Seq and not a Seq of by-names (functions). That detail is probably why it was not implemented for so long.

For copy, would it replace all the repeated args? (Probably)

k.copy(i = 42)

But Scala 3 is experimenting with creative use of braces (now that code is braceless), so maybe the syntax could be

k.copy(i = { 42, 27 })

or brackets, I meant brackets

k.copy(i = [ 42, 27 ])

Or, since Scala 3 aims for simplicity, it’s simpler to disallow it.

Additionally, it was a year ago this month that Scala 2 got copy with by-name parameters in the signature (under -Xsource:3-cross):

Welcome to Scala 2.13.16 -Xsource:3.0.0 (OpenJDK 64-Bit Server VM, Java 23.0.2).
Type in expressions for evaluation. Or try :help.

scala> case class C(i: Int)(j: => Int) { def total = i + j }
class C

scala> val c = C(42)(27)
val c: C = C(42)

scala> c.copy()(j = 1).total
val res0: Int = 43
2 Likes