2011-09-02 9 views
11

इस फ़ाइल:इस स्कैला पैटर्न मिलान में एक अनचेक प्रकार तर्क के बारे में चेतावनी?

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" 

स्काला संस्करण 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) 
} 

यह चेतावनी देता है।

मुझे नहीं लगता कि मैच को करने के लिए एक मिटा प्रकार पैरामीटर की आवश्यकता है। यही कारण है कि पहले मामले खंड अगर obj 1, 2 बराबर 3 तत्वों के साथ एक Seq है पूछना करने के लिए है, और 3.

मैं इस चेतावनी की तरह कुछ समझ अगर मैं लिखा था:

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

मुझे चेतावनी क्यों मिलती है, और इसे दूर करने का एक अच्छा तरीका क्या है?

वैसे, मैं स्थिर प्रकार के ऑब्जेक्ट के साथ कुछ के खिलाफ मिलान करना चाहता हूं। असली कोड में मैं एक लिस्प डैटम की तरह कुछ पार्स कर रहा हूं - यह एक स्ट्रिंग, डेटाम, प्रतीक, संख्या इत्यादि का अनुक्रम हो सकता है।

+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 साथ संकलन हैं, तो आप सिर्फ विलोपन चरण (आईडी 13) से पहले कोड देखेंगे। पहले प्रकार पैटर्न के लिए, आप की तरह कुछ देखेंगे:

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

Seqनिकालने पैटर्न के लिए, आप की तरह कुछ देखेंगे:

<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); 
    // ... 
} 

दोनों ही मामलों में, वहाँ एक प्रकार है यह देखने के लिए जांच करें कि क्या वस्तु Seq (Seq[Int] और Seq[A]) है। टाइप पैरामीटर मिटा चरण के दौरान समाप्त हो जाएगा। इस प्रकार चेतावनी। भले ही दूसरा अप्रत्याशित हो, लेकिन इस प्रकार की जांच करने के लिए यह समझ में आता है कि यदि ऑब्जेक्ट Seq प्रकार नहीं है, तो खंड मेल नहीं करेगा और JVM अगले खंड पर जा सकता है। यदि प्रकार मेल खाता है, तो ऑब्जेक्ट को Seq और unapplySeq पर जाया जा सकता है।


आरई: प्रकार की जांच पर थोरज टिप्पणी। हो सकता है कि हम अलग-अलग चीजों के बारे में बात कर रहे हों। मैं केवल कि कह रहे थे:

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

की तरह कुछ करने के लिए अनुवाद:

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)) 
} 

प्रकार की जांच प्रयोग किया जाता है तो जब कलाकारों से किया जाता है कि कोई वर्ग डाली अपवाद नहीं है।

चाहे चेतावनी गैर वैरिएबल प्रकार तर्क एक प्रकार पैटर्न में Seq [एक] अनियंत्रित है, क्योंकि यह विलोपन से निकाल दिया जाता है उचित है और क्या वहाँ मामलों में जहां वहाँ के साथ वर्ग डाली अपवाद भी हो सकता है हो सकता है चेक टाइप करें, मुझे नहीं पता।

संपादित करें: यहाँ एक उदाहरण है:

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' प्रकार के प्रकार के विपरीत खंडों के विरुद्ध मिलान करने की कोशिश नहीं कर रहा है। – huynhjl

+0

मुझे क्लाससेज़ अपवाद नहीं मिलता है अगर मैं ऑब्जेक्ट को मानचित्र (1 -> 2, 2 -> 3) में बदलता हूं, मानचित्र ("1" -> "2", "2" -> "3"); या उस मामले के लिए " – 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

हाँ अच्छा खोज। ऐसा इसलिए है क्योंकि इस मामले में, यह एक * स्थिर पहचानकर्ता पैटर्न * का उपयोग कर रहा है, और जो केवल समानता परीक्षण (भाषा spec प्रति) के लिए संकलित करते हैं, कोई कास्टिंग आवश्यक नहीं है। यदि आप चर को बांधना चाहते हैं, तो आप भाग्य से बाहर हैं। – huynhjl

+0

जानना अच्छा है, लेकिन हाँ, मुझे चर बाध्य करने की आवश्यकता है। –

+1

यदि मैं किसी प्रकार के विरुद्ध मिलान करता हूं (जैसे 'सेक [Int] ') और किसी भी पूर्णांक अनुक्रम को वैध मिलान माना जाना चाहिए (केवल (1 2, 3) नहीं)? – Ivan

संबंधित मुद्दे