In my test suite I am frequently writing code such as
val Vector(socialSci, humanities, pureSci, pureApplSci) = foo(someValue)
foo obviously returns a (short) Vector but I'd like to have names for each of the values. It's not always four items long, but since it's my test suite the correct number is known and I'm perfectly fine with an exception being thrown if there is a length mismatch.
The above code works -- except that I get a compiler error:
match may not be exhaustive.
Is there a way to get rid of the compiler warning? I've tried @nowarn and @nocheck in various positions with no luck.
Alternatively, is there a succinct way to write this so it doesn't cause a warning in the first place? The solution at Convert Vector to Tuple scala looks promising except that reflection isn't available for ScalaJS.
def toTuple(seq: Seq[_]): Product = {
val clz = Class.forName("scala.Tuple" + seq.size)
clz.getConstructors()(0).newInstance(seq.map(_.asInstanceOf[AnyRef]): _*).asInstanceOf[Product]
}
Is there an approach using a builder or something?
Update:
Thanks to Dmytro Mitin for reminding me to check my compiler options. Yes, I had completely forgotten about that and had -Xlint:valpattern enabled. Turning that off removes the warning.
That solves my immediate problem. But as a challenge, is there a way to implement toTuple without using reflection?
You can switch off
-Xlint:valpattern.But if you want to keep
-Xlint:valpatternand switch off the warningmatch may not be exhaustivein this specific place you can use@uncheckedIf a vector returned by
foocan be longer than 4 elements you can additionally use vararg patternYou can also transform a vector into a tuple with Shapeless. I can't see direct
Vector => Tuple, so I'm usingVector => HList => TupleOn contrary to runtime reflection, this mostly works at compile time (we're specifying
4statically, otherwise.getwill throwjava.util.NoSuchElementException: None.getat runtime), so this should work in ScalaJS too