如何在Scala中实现不可变的IndexedSeq,由Array支持

时间:2018-03-13 12:32:43

标签: scala scala-collections

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

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

此处的一个问题是IndexedSeq[Int]的效果(因为它们由scala.collection.Vector支持)。作为一个数字处理库,性能是一个很大的问题。我想将Vector支持的IndexedSeq换成Array支持的IndexedSeq

我想指出最好的方法是什么(除了从Scala集合中再现var file = File.ReadAllBytes(filepath); 的完整代码并更改相关部分之外。)谢谢。

2 个答案:

答案 0 :(得分:2)

这样就够了吗?

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 :(得分:2)

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

  1. 不要将data字段公开(即val),以便外部代码无法访问它
  2. 构造你自己的data数组,即在Tensor的构造函数中,以便在Tensor实例之外没有任何对数组的引用
  3. 例如:

    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会自动将Array包装到WrappedArray中。