Mec*_*ail 7 arrays collections types scala multidimensional-array
你如何在Scala中表示矩形的二维(或多维)数组数据结构?
也就是说,每行具有相同的长度,在编译时验证,但维度是在运行时确定的?
Seq[Seq[A]] 具有所需的接口,但它允许用户提供"参差不齐"的阵列,这可能导致运行时故障.
Seq[(A, A, A, A, A, A)] (和类似的)确认长度是相同的,但它也强制在编译时指定这个长度.
这是我的意思的示例界面(当然,内部维度不必是元组;它可以指定为列表或其他类型):
// Function that takes a rectangular array
def processArray(arr : RectArray2D[Int]) = {
// do something that assumes all rows of RectArray are the same length
}
// Calling the function (OK)
println(processArray(RectArray2D(
( 0, 1, 2, 3),
(10, 11, 12, 13),
(20, 21, 22, 23)
)))
// Compile-time error
println(processArray(RectArray2D(
( 0, 1, 2, 3),
(10, 11, 12),
(20, 21, 22, 23, 24)
)))
Run Code Online (Sandbox Code Playgroud)
这可以使用Shapeless库的大小类型:
import shapeless._
def foo[A, N <: Nat](rect: Seq[Sized[Seq[A], N]]) = rect
val a = Seq(Sized(1, 2, 3), Sized(4, 5, 6))
val b = Seq(Sized(1, 2, 3), Sized(4, 5))
Run Code Online (Sandbox Code Playgroud)
现在foo(a)编译,但foo(b)没有.
这允许我们编写非常接近您所需界面的内容:
case class RectArray2D[A, N <: Nat](rows: Sized[Seq[A], N]*)
def processArray(arr: RectArray2D[Int, _]) = {
// Run-time confirmation of what we've verified at compile-time.
require(arr.rows.map(_.size).distinct.size == 1)
// Do something.
}
// Compiles and runs.
processArray(RectArray2D(
Sized( 0, 1, 2, 3),
Sized(10, 11, 12, 13),
Sized(20, 21, 22, 23)
))
// Doesn't compile.
processArray(RectArray2D(
Sized( 0, 1, 2, 3),
Sized(10, 11, 12),
Sized(20, 21, 22, 23)
))
Run Code Online (Sandbox Code Playgroud)