2013-03-03 49 views
1

假設我有一個例如二維數組,並存儲一些索引在元組中:在Scala中對多維數組進行uncurrying/tupling?

val testArray = Array.ofDim[Double](3, 4) 
val ixs = (1,2) 

我想直接使用這些元組, testArray(ixs)。但是,Function.tupled(testedArray _)返回「_必須遵循方法;不能跟隨Array [Array [Double]]」。

這是因爲Array實際上不是Function3的子類型嗎? 如果是這樣,怎麼繞過這個限制?我是否應該使用implicits來擴展ArrayOps或類似的東西?目前,我將數據存儲在Map中作爲解決方法。

回答

2

陣列陣列沒有給予特殊處理;他們只是(某物)的數組。因此,沒有特殊的方法通過元組來訪問它們。但正如你所建議的那樣,你可以創建這樣一種方式。

可以

implicit class ArrayOps2D[@specialized T](xss: Array[Array[T]]) { 
    def apply(ij: (Int, Int)) = xss(ij._1)(ij._2) 
    def apply(i: Int, j: Int) = xss(i)(j) 
    def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t } 
    def update(i: Int, j: Int, t: T) { xss(i)(j) = t } 
} 

你可能認爲這樣做

implicit class ArrayOps2D[T](val xss: Array[Array[T]]) extends AnyVal { 
    def apply(ij: (Int, Int)) = xss(ij._1)(ij._2) 
    def apply(i: Int, j: Int) = xss(i)(j) 
    def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t } 
    def update(i: Int, j: Int, t: T) { xss(i)(j) = t } 
} 

,但這並不在我看來正常工作。由於實現的限制,你不能專門化AnyVal。此外,前者可能更好,如果你使用原語很多,因爲它避免裝箱原語(並且JVM可以處理避免對象創建),而後者更有效,如果大多數時候你有非原語的話例如字符串),因爲你沒有(正式)創建一個對象。但你的例子使用基元。在任何情況下,如果你這樣做,你就會有元組和一對參數的無縫雙索引尋址(就像我寫的那樣)。不過不能完全無縫地使用更新方法!他們將主要工作,但他們將不會自動提升數字類型。所以,如果你有雙打,並且你寫a(1,2) = 3它會失敗,因爲它找不到update(Int, Int, Int)方法,並且不認爲使用update(Int, Int, Double)。但是你可以通過轉換來解決這個問題(或者在這種情況下編寫3d)。

+0

感謝您對這兩種方法之間權衡的全面討論。 – 2013-03-04 09:48:46

+0

此外,你現在可以(Scala 2.10+)「專門化」AnyVal的值類,儘管在實現方面,它不像[簡單的「子類化」](http://docs.scala-lang.org/overviews/芯/值-classes.html)。 – 2013-05-01 21:39:02

+0

@TheTerribleSwiftTomato - 我不確定你的意思。在2.10中你實際上不能使用'專業化'關鍵字,而且我已經在「你可能認爲要做的」一節中介紹了通用的unboxed-array-boxed-elements版本。 – 2013-05-01 21:53:50

相關問題