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?
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:valpattern
and switch off the warning match may not be exhaustive
in this specific place you can use @unchecked
def foo(): Vector[Int] = Vector(1, 2, 3, 4)
val Vector(socialSci, humanities, pureSci, pureApplSci) = foo() : @unchecked
If a vector returned by foo
can be longer than 4 elements you can additionally use vararg pattern
val Vector(socialSci, humanities, pureSci, pureApplSci, _*) = ...
You can also transform a vector into a tuple with Shapeless. I can't see direct Vector => Tuple
, so I'm using Vector => HList => Tuple
import shapeless.syntax.std.traversable._ // libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.10"
val (socialSci, humanities, pureSci, pureApplSci) = foo().toSizedHList(4).get.tupled
On contrary to runtime reflection, this mostly works at compile time (we're specifying 4
statically, otherwise .get
will throw java.util.NoSuchElementException: None.get
at runtime), so this should work in ScalaJS too
libraryDependencies += "com.chuusai" %%% "shapeless" % "2.3.10" // ScalaJS