scala 从向量到单个变量的多重赋值

hts6caw3  于 2023-03-30  发布在  Scala
关注(0)|答案(1)|浏览(136)

在我的测试套件中,我经常编写这样的代码

val Vector(socialSci, humanities, pureSci, pureApplSci) = foo(someValue)

foo显然返回了一个(短)Vector,但我希望每个值都有名称。它并不总是四项长,但因为它是我的测试套件,正确的数字是已知的,如果有长度不匹配,我完全可以抛出异常。
上面的代码可以工作--除了我得到一个编译器错误:

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

m2xkgtsf

m2xkgtsf1#

您可以关闭-Xlint:valpattern
但是如果您想保留-Xlint:valpattern并在此特定位置关闭警告match may not be exhaustive,则可以使用@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

相关问题