1

私はScalaの 99 の問題のうちの問題 7 を解決しようとしていましたが、任意の型を含むことができるa の型を特定するのに苦労しましたList。だから私は答えを見て、それがList[Any]. 次のように実装をコーディングしました。

def flatten(lst: List[Any]): List[Any] = lst match {
    case Nil => Nil
    case x::xs =>
        (if (x.isInstanceOf[List[Any]]) { flatten(x) } else { List(x) }) :::
        flatten(xs)
}

ただし、これにより次のコンパイルエラーが発生します。

[error] <filename omitted>:<line number omitted>: type mismatch;
[error] found   : Any
[error] required: List[Any]
[error]                (if (x.isInstanceOf[Any]) { flatten(x) } else {List(x) })
[error]                                                    ^
[error] one error found

に変更isInstanceOf[List[Any]]するとisInstanceOf[List[_]]、同じコンパイル エラーが発生します。

短いグーグル検索とこのソリューションのコンサルティングの後、私はこれを実装しました:

def flatten(lst: List[Any]): List[Any] = lst match {
    case Nil => Nil
    case x::xs => x match {
        case x: List[_] => flatten(x) ::: flatten(xs)
        case _ => x :: flatten(xs)
    }
}

これは完全に正常に機能します。では、なぜ Scala コンパイラーは、そのブロック内に入るために を渡さなければならないのに、それxが型であると考えるのでしょうか? これはコンパイラのバグですか、それとも私が理解できない Scala の一部ですか?Anyx.isInstanceOf[Any]List[Any]

ありがとうございました!

4

3 に答える 3

3

あなたのコードでxは、 は a の頭ですList[Any]: それはAnyであるため、エラーメッセージが表示されます。にキャストする必要がありList[Any]ます。これにより、パターン マッチングを非常にエレガントに行うことができます。

def flatten(lst: List[Any]): List[Any] = lst match {
  case Nil               => Nil
  case (x:List[Any])::xs => flatten(x) ::: flatten(xs)
  case x::xs             => List(x) ::: flatten(xs)
}
于 2013-07-25T13:29:09.970 に答える
2

値が.isInstanceOfチェックに合格したからといって、その型が変わるわけではありません。それはまだAnyです。しかし、それはにキャストすることができますList[Any]

だから、私はあなたがする必要があると思います

(if (x.isInstanceOf[List[Any]]) { flatten(x.asInstanceOf[List[Any]]) } else { List(x) }) ::: flatten(xs)

よくわかりませんが、その理由は

case x: List[_] => flatten(x) ::: flatten(xs)

バージョンの機能は、チェックとキャストの両方を行うことです。

于 2013-07-25T13:26:07.240 に答える
1

これを行う場合:

case x::xs =>

xリストの先頭にバインドされます。したがって、リストに type がある場合、List[Any]もちろん head には type がありますAny( ではありませんList[Any])

于 2013-07-25T13:29:07.490 に答える