2

Scala2.8コレクションの動作にかなり不満を感じています。ここに問題があります:私は数独ボードを作成しています。A1からI9までのセルにラベルを付けています(文字は行、数字は列です)。ボード上のユニットのリストを取得したいと思います。これは、9行、夜の列、および夜の象限です。

これが私のscalaクラスです:

class Square(val row:Char, val column:Int) extends Pair[Char, Int](row, column) {
    override def toString() = "" + row + column 
}

object Board {
    private val rows = "ABCDEFGHI"
    private val cols = 1 to 9
    private lazy val units = unitList(rows, cols)
    private def cross(rows:Iterable[Char], columns:Iterable[Int]):Iterable[Square] = {
        for (row <- rows; col <- columns)
            yield new Square(row, col)
    }

    private def unitList(rows:Iterable[Char], cols:Iterable[Int]) = {
        val u1 = (for (col <- cols) yield cross(rows, List(col)))
        val u2 = (for (row <- rows) yield cross(List(row), cols))
        val u3 = (for (cols <- List("ABC", "DEF", "GHI"); rows <- List(1 to 3, 4 to 6, 7 to 9)) yield cross(cols, rows))

        u1 :+ u2 :+ u3  // won't compile, reason: :+ is not a member of Iterable[Iterable[sudoku.Square]]
    }

    def run() {
        val u1 = (for (col <- cols) yield cross(rows, List(col)))
        val u2 = (for (row <- rows) yield cross(List(row), cols))
        val u3 = (for (cols <- List("ABC", "DEF", "GHI"); rows <- List(1 to 3, 4 to 6, 7 to 9)) yield cross(cols, rows))
        println(u1)
        println(u2)
        println(u3)
        val u4 = u1 :+ u2 :+ u3  // compiles
        println(u1 :+ u2 :+ u3)  // compiles and output correctly
    }
}

コード内のコメントを参照してください。具体的には、同じコードがunitListでコンパイルされず、run()で正常にコンパイルおよび実行されるのはなぜですか?

また、runメソッドの出力を観察すると、yieldキーワードによって返されるコレクションがVectorとListの間でランダムに切り替わっているようです。

Vector(Vector(A1, B1, C1, D1, E1, F1, G1, H1, I1), Vector(A2, B2, C2, D2, E2, F2, G2, H2, I2), Vector(A3, B3, C3, D3, E3, F3, G3, H3, I3), Vector(A4, B4, C4, D4, E4, F4, G4, H4, I4), Vector(A5, B5, C5, D5, E5, F5, G5, H5, I5), Vector(A6, B6, C6, D6, E6, F6, G6, H6, I6), Vector(A7, B7, C7, D7, E7, F7, G7, H7, I7), Vector(A8, B8, C8, D8, E8, F8, G8, H8, I8), Vector(A9, B9, C9, D9, E9, F9, G9, H9, I9))

Vector(List(A1, A2, A3, A4, A5, A6, A7, A8, A9), List(B1, B2, B3, B4, B5, B6, B7, B8, B9), List(C1, C2, C3, C4, C5, C6, C7, C8, C9), List(D1, D2, D3, D4, D5, D6, D7, D8, D9), List(E1, E2, E3, E4, E5, E6, E7, E8, E9), List(F1, F2, F3, F4, F5, F6, F7, F8, F9), List(G1, G2, G3, G4, G5, G6, G7, G8, G9), List(H1, H2, H3, H4, H5, H6, H7, H8, H9), List(I1, I2, I3, I4, I5, I6, I7, I8, I9))

List(Vector(A1, A2, A3, B1, B2, B3, C1, C2, C3), Vector(A4, A5, A6, B4, B5, B6, C4, C5, C6), Vector(A7, A8, A9, B7, B8, B9, C7, C8, C9), Vector(D1, D2, D3, E1, E2, E3, F1, F2, F3), Vector(D4, D5, D6, E4, E5, E6, F4, F5, F6), Vector(D7, D8, D9, E7, E8, E9, F7, F8, F9), Vector(G1, G2, G3, H1, H2, H3, I1, I2, I3), Vector(G4, G5, G6, H4, H5, H6, I4, I5, I6), Vector(G7, G8, G9, H7, H8, H9, I7, I8, I9))

Vector(Vector(A1, B1, C1, D1, E1, F1, G1, H1, I1), Vector(A2, B2, C2, D2, E2, F2, G2, H2, I2), Vector(A3, B3, C3, D3, E3, F3, G3, H3, I3), Vector(A4, B4, C4, D4, E4, F4, G4, H4, I4), Vector(A5, B5, C5, D5, E5, F5, G5, H5, I5), Vector(A6, B6, C6, D6, E6, F6, G6, H6, I6), Vector(A7, B7, C7, D7, E7, F7, G7, H7, I7), Vector(A8, B8, C8, D8, E8, F8, G8, H8, I8), Vector(A9, B9, C9, D9, E9, F9, G9, H9, I9), Vector(List(A1, A2, A3, A4, A5, A6, A7, A8, A9), List(B1, B2, B3, B4, B5, B6, B7, B8, B9), List(C1, C2, C3, C4, C5, C6, C7, C8, C9), List(D1, D2, D3, D4, D5, D6, D7, D8, D9), List(E1, E2, E3, E4, E5, E6, E7, E8, E9), List(F1, F2, F3, F4, F5, F6, F7, F8, F9), List(G1, G2, G3, G4, G5, G6, G7, G8, G9), List(H1, H2, H3, H4, H5, H6, H7, H8, H9), List(I1, I2, I3, I4, I5, I6, I7, I8, I9)), List(Vector(A1, A2, A3, B1, B2, B3, C1, C2, C3), Vector(A4, A5, A6, B4, B5, B6, C4, C5, C6), Vector(A7, A8, A9, B7, B8, B9, C7, C8, C9), Vector(D1, D2, D3, E1, E2, E3, F1, F2, F3), Vector(D4, D5, D6, E4, E5, E6, F4, F5, F6), Vector(D7, D8, D9, E7, E8, E9, F7, F8, F9), Vector(G1, G2, G3, H1, H2, H3, I1, I2, I3), Vector(G4, G5, G6, H4, H5, H6, I4, I5, I6), Vector(G7, G8, G9, H7, H8, H9, I7, I8, I9)))

私はここで完全に迷っています。

4

3 に答える 3

8

for 内包表記の yield の結果は、最初のジェネレーターの型から派生します。メソッドでは、パラメーターの型を制限しているため、:+ メソッドが失われます。

//The type of 1 to 9 is show below
scala> 1 to 9
res0: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)


//If you cast it to Iterable[Int] it doens't have the :+ method
scala> (res0:Iterable[Int]) :+ 1
<console>:7: error: value :+ is not a member of Iterable[Int]
       (res0:Iterable[Int]) :+ 1
       ^

//But if you don't, you have it
scala> res0 :+ 1                
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 1)

//And to prove that for comprehensions yield derives the type of the first generator:

scala> for(a <- res0) yield a
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> for(a <- (res0:Iterable[Int])) yield a
res8: Iterable[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9)
于 2010-07-20T17:26:52.217 に答える
3

本当に奇妙な振る舞いにもかかわらず、:+あなたが望むオペレーターになることはおそらくありません. の戻り値の型に注釈を付けてunitListいないので、何を期待していたのかわかりません。Iterable[Square]またはのいずれかを返したいと思いますIterable[Iterable[Square]]:+それでは、それらを取得する方法と、なぜ間違っているのかを見てみましょう。

まず第一にu1u2u3はすべてIterable[Iterable[Square]]ですが、正確なサブタイプは異なります。これは理解しやすいはずです: をcross返します。Iterable[Square]crossIterable[Iterable[Square]]

次に、 を考えてみましょう:+。このメソッドはコレクションに要素を追加します。したがって、u1isIterable(a, b, c)の場合、a、b、c はIterable[Square]u1 :+ u2ありIterable(a, b, c, u2)、その型は になりますIterable[X]。ここで、 は(a、b、c の型) と(の型)Xの統一です)。最終結果は.Iterable[Square]Iterable[Iterable[Square]]u2Iterable[Iterable[AnyRef]]

との型は本質的に同じなので、u1おそらく正しい操作は次のとおりです。u2u3

u1 ++ u2 ++ u3

どちらが返されIterable[Iterable[Square]]ます。ここで、ネストを削除して returnIterable[Square]にしたい場合は、これをフラット化できます。

(u1 ++ u2 ++ u3).flatten

この 2 つのうちの 1 つは、おそらくあなたが望むものです。

さて、「ランダムな」切り替えに関しては、ランダムなことは何もありません。それぞれの場合に、2 つの for 内包表記があり、結果のコレクションの実際の実装は、元のコレクションの実装に依存します。だから、それを考えてみましょう:

  • u1: 外側の型は から派生しRange、内側の型はString(交差する最初のパラメーター)から派生します。
  • u2: 外側の型は から派生しString、内側の型はList(交差する最初のパラメーター)から派生します。
  • u3: 外側の型は から派生しList、内側の型はString(交差する最初のパラメーター)から派生します

Stringしたがって、 ( WrappedString, 実際には)に対する for-comprehensions は になり、 for-comprehensions に対するRange結果は になることが容易に推測できます。VectorListList

于 2010-07-20T22:32:47.963 に答える
2

は(したがって):+のメンバーであり、 のメンバーではないため、コンパイラ エラーが発生します。fromの戻り値を変更するとIndexedSeqListIterableunitList

u1 :+ u2 :+ u3

List(u1) :+ u2 :+ u3

それはうまくコンパイルされます。

于 2010-07-20T17:34:22.313 に答える