Why can the case class contain more parameters than it declares?

See code

case class Wrapped[A](elem: A)(implicit ordering: Ordering[A]) extends Ordered[Wrapped[A]] { def compare(that: Wrapped[A]): Int = ordering.compare(this.elem, that.elem) } 

I define a case class here.

and then call

Wrapped(1,2,2,4) .

To my surprise, even Wrapped(1,2,3,4,5) (any number of parameters) can work fine without compiling the error.

+7
scala
source share
2 answers

It was called auto-tupling.

The compiler will try to fill in additional arguments by wrapping them all in a tuple.

 Wrapped(1,2,3,4) 

automatically turns into

 Wrapped((1,2,3,4)) 

By the way, this is an annoying and amazing feature, and I really hope that this will end up being obsolete. Meanwhile, you have two compiler options available:

  • -Ywarn-adapted-args , which warns in case of auto-tuning
  • -Yno-adapted-args , which gives an error under the same circumstances

Example with a warning:

 scala -Ywarn-adapted-args scala> case class Foo[A](a: A) scala> Foo(1, 2) <console>:10: warning: Adapting argument list by creating a 2-tuple: this may not be what you want. signature: Foo.apply[A](a: A): Foo[A] given arguments: 1, 2 after adaptation: Foo((1, 2): (Int, Int)) Foo(1, 2) ^ res1: Foo[(Int, Int)] = Foo((1,2)) 

Error example:

 scala -Yno-adapted-args scala> case class Foo[A](a: A) defined class Foo scala> Foo(1, 2) <console>:10: warning: No automatic adaptation here: use explicit parentheses. signature: Foo.apply[A](a: A): Foo[A] given arguments: 1, 2 after adaptation: Foo((1, 2): (Int, Int)) Foo(1, 2) ^ <console>:10: error: too many arguments for method apply: (a: (Int, Int))Foo[(Int, Int)] in object Foo Foo(1, 2) ^ 
+12
source share

Look closer to your code:

 Wrapped(1,2,3,4,5) res0: Wrapped[(Int, Int, Int, Int, Int)] = Wrapped((1,2,3,4,5)) 

Parameters are compressed into a Tuple object. So instead of Wrapped[Int] you have Wrapped[(Int, Int, Int, Int, Int)] .

+1
source share

All Articles