2011-09-02 5 views
11

このファイル:このScalaパターンマッチのチェックされていない型引数についての警告?

Test.scala:6: warning: non variable type-argument A in type pattern Seq[A] 
is unchecked since it is eliminated by erasure 
    case Seq(1,2,3) => "first" 

Scalaのバージョン2.9.0.1:

object Test extends App { 
    val obj = List(1,2,3) : Object 
    val res = obj match { 
     case Seq(1,2,3) => "first" 
     case _ => "other" 
    } 
    println(res) 
} 

は、この警告を与えます。

マッチを実行するために消去されたタイプのパラメータがどのように必要かわかりません。

case strings : Seq[String] => ... 

:その最初のケース句はOBJが3つの1に等しい要素、2、及び3

と配列であれば、私のようなものを書いていた場合、私はこの警告を理解するだろう尋ねることを意図していますなぜ警告を受け取るのですか?それを消すための良い方法は何ですか?

ところで、私はオブジェクトの静的型で何かに一致したいと思います。実際のコードでは、Lispデータのようなものを解析しています。これは、文字列、データ配列、シンボル、数値などです。

+0

バージョン2.8.1ではこの警告は表示されません。 – thoredge

+0

@thoredge、私の推測では2.9.0の警告はおそらく改善と見なされていました。この特定のケースが予見されたかどうかはわかりません。 – huynhjl

答えて

5

ここでは、シーンの後ろで何が起こるかについてのいくつかの洞察があります。このコードを考えてみましょう:

class Test { 
    new Object match { case x: Seq[Int] => true } 
    new Object match { case Seq(1) => true } 
} 

あなたはscalac -Xprint:12 -uncheckedでコンパイルする場合は、あなただけの消去相(ID 13)の前にコードが表示されます。最初タイプのパターンについて、あなたのようなものが表示されます:Seq抽出パターンについては

<synthetic> val temp1: java.lang.Object = new java.lang.Object(); 
if (temp1.isInstanceOf[Seq[Int]]()) 

を、あなたのようなものが表示されます。どちらの場合も

<synthetic> val temp3: java.lang.Object = new java.lang.Object(); 
if (temp3.isInstanceOf[Seq[A]]()) { 
    <synthetic> val temp4: Seq[A] = temp3.asInstanceOf[Seq[A]](); 
    <synthetic> val temp5: Some[Seq[A]] = collection.this.Seq.unapplySeq[A](temp4); 
    // ... 
} 

を、タイプがありますオブジェクトがタイプSeqSeq[Int]およびSeq[A])であるかどうかを確認します。タイプ・パラメータは、消去段階中に除去される。したがって、警告。 2番目が予期せぬものであっても、オブジェクトがタイプSeqでなければ、その句が一致せず、JVMが次の句に進むことができるので、タイプをチェックすることは理にかなっています。タイプが一致する場合、オブジェクトはSeqにキャストし、unapplySeqを呼び出すことができます。


RE:タイプチェックにコメントを追加しました。私たちはさまざまなことを話しているかもしれません。私は単にそれを言っていた:キャストが行われたときにはクラス・キャスト例外がないように型チェックが使用されている

if (o.isInstanceOf[Seq[_]]) { // type check 
    val temp1 = o.asInstanceOf[Seq[_]] // cast 
    // verify that temp1 is of length 1 and println("seq " + temp1(0)) 
} else if (o.isInstanceOf[Array[_]]) { // type check 
    val temp1 = o.asInstanceOf[Array[_]] // cast 
    // verify that temp1 is of length 1 and println("array " + temp1(0)) 
} 

(o: Object) match { 
    case Seq(i) => println("seq " + i) 
    case Array(i) => println("array " + i) 
} 

は、次のようなものに変換されます。それは消去により除去されるので、型パターン配列[A]に警告非可変型引数Aがオフであるかどうか

は正当とも持つクラスキャスト例外が存在し得る場合が存在することになるかどうかでありますタイプチェック、私は知らない。

編集:ここでの例です:

object SeqSumIs10 { 
    def unapply(seq: Seq[Int]) = if (seq.sum == 10) Some(seq) else None 
} 

(Seq("a"): Object) match { 
    case SeqSumIs10(seq) => println("seq.sum is 10 " + seq) 
} 
// ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
+1

これはバグですか?この場合、型チェックは最適化に過ぎません。 – thoredge

+0

@thoredge、タイプチェックなしで、オブジェクトが 'Seq'型でない場合にClassCastException *を取得し、それ以降の句と照合しようとします。 – huynhjl

+0

オブジェクトをMap(1 - > 2、2 - > 3)、Map( "1" - > "2"、 "2" - > "3")に変更すると、ClassCaseExceptionが発生しません。または ""の場合 – thoredge

4

外少なくともそれが離れて行かせるマッチオブジェクトの宣言が、私はよく分からない理由:興味深いノート、スカラ座で

class App 
    object Test extends App { 
    val obj = List(1,2,3) : Object 
    val MatchMe = Seq(1,2,3) 
    val res = obj match { 
    case MatchMe => "first" 
    case _ => "other" 
    } 
    println(res) 
} 
+2

はい良い見つける。これは、この場合、安定した識別子パターン*を使用しているためであり、キャストは必要ありません(言語仕様ごとの)等価テストのみでコンパイルされます。あなたが変数をバインドしたい場合、あなたは運が悪いです。 – huynhjl

+0

わかりましたが、はい、私は変数をバインドする必要があります。 –

+1

タイプ(「Seq [Int]」など)と一致し、整数シーケンスが((1,2,3)だけでなく)有効な一致と見なされる場合はどうなりますか? – Ivan

関連する問題