在我的测试套件中,我经常编写如下代码
val Vector(socialSci, humanities, pureSci, pureApplSci) = foo(someValue)
foo
显然返回一个(短)向量,但我想为每个值提供名称。它并不总是四个项目长,但由于它是我的测试套件,所以正确的数字是已知的,并且如果长度不匹配,我完全可以抛出异常。
上面的代码可以工作——除了我得到一个编译器错误:
match may not be exhaustive.
有没有办法消除编译器警告?我在不同位置尝试过 @nowarn
和 @nocheck
但没有成功。
或者,是否有一种简洁的方法来编写此代码,这样它就不会首先引起警告?解决方案在Convert Vector to Tuple scala看起来很有希望,只是反射不适用于 ScalaJS。
def toTuple(seq: Seq[_]): Product = {
val clz = Class.forName("scala.Tuple" + seq.size)
clz.getConstructors()(0).newInstance(seq.map(_.asInstanceOf[AnyRef]): _*).asInstanceOf[Product]
}
有没有使用构建器或其他东西的方法?
更新:
感谢 Dmytro Mitin 提醒我检查我的编译器选项。是的,我完全忘记了这一点并启用了 -Xlint:valpattern
。关闭它会删除警告。
这解决了我眼前的问题。但作为一个挑战,有没有一种方法可以在不使用反射的情况下实现toTuple
?
最佳答案
您可以关闭-Xlint:valpattern
。
但是,如果您想保留 -Xlint:valpattern
并关闭此特定位置的警告 匹配可能不详尽
,您可以使用 @unchecked
def foo(): Vector[Int] = Vector(1, 2, 3, 4)
val Vector(socialSci, humanities, pureSci, pureApplSci) = foo() : @unchecked
如果 foo
返回的向量可以超过 4 个元素,您还可以使用 vararg 模式
val Vector(socialSci, humanities, pureSci, pureApplSci, _*) = ...
您还可以使用 Shapeless 将向量转换为元组。我看不到直接 Vector => Tuple
,所以我使用 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
与运行时反射相反,这主要在编译时起作用(我们静态指定4
,否则.get
将抛出java.util.NoSuchElementException : None.get
在运行时),所以这也应该在 ScalaJS 中工作
libraryDependencies += "com.chuusai" %%% "shapeless" % "2.3.10" // ScalaJS
关于scala - 从向量到各个变量的多重赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75870429/