如何在 Scala 中实现一个不可变的 IndexedSeq,由数组支持



我正在尝试在数值处理库中实现张量(多维数组(。张量实现的签名如图所示(减少签名的不相关部分(:

final class Tensor[V](val data: Array[V], val shape: IndexedSeq[Int])

这里的一个问题是IndexedSeq[Int]的性能(因为它们有scala.collection.Vector支持(。作为一个数值处理库,性能在这里是一个大问题。我想将默认的Vector支持的IndexedSeq换成Array支持的。

我想指出什么是最好的方法(除了从 Scala 集合中复制完整的IndexedSeq代码并更改相关部分。谢谢。

这就足够了吗?

final class FastVector[+T](a: Array[T]) extends IndexedSeq[T] {
  override def apply(idx: Int) = a(idx)
  override def length = a.length
}

然后,您将使用 FastVector 作为IndexedSeq类型。IndexedSeq的所有能力都是由该特质的具体方法提供的,因此mapfilter等也都可供您使用。

在您的示例中,您可以执行两项操作:

  1. 不要将data字段设为公共(即 val(,以便外部代码无法访问它
  2. 构造 data 数组 your-self,即在张量的构造函数中,这样在张量实例之外就没有任何对数组的引用

例如:

class Tensor[V] private (data: Array[V], shape: Array[Int])
object Tensor{
  def vector[V](input: Seq[V]) = new Tensor(input.toArray, Array(1))
  def matrix[V](input: Seq[V], w: Int, h: Int) = new Tensor(input.toArray, Array(w,h))
}
// example use
Tensor.vector(1 to 20)
Tensor.matrix(1 to 20, 5, 4)

此外,一般来说,Array 周围有一个包装器,它是一个 IndexedSeq:WrappedArray。你可以这样做,例如:val iSeq: IndexedSeq[Int] = Array(42)和 Scala 会自动将数组包装成一个包装数组。

相关内容

最新更新