2013-11-20 6 views
12

में Arrays को संयोजित करते समय दिलचस्प निष्कर्ष मुझे स्कैला में ऐरे संयोजन को समझने में कुछ परेशानी हो रही है।स्केल

ठीक निम्नलिखित काम करता है:

scala> Array('0', '1', '2') ++ Array('A', 'B', 'C') 
res0: Array[Char] = Array(0, 1, 2, A, B, C) 

लेकिन यह एक नहीं करता है:

scala> ('0' to '9').toArray 
res1: Array[Char] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> ('A' to 'Z').toArray 
res2: Array[Char] = Array(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) 

scala> res1 ++ res2 
res3: Array[Char] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) 

एक और दिलचस्प बिट मैंने पाया:

scala> ('0' to '9').toArray ++ ('A' to 'Z').toArray 
<console>:8: error: polymorphic expression cannot be instantiated to expected type; 
found : [B >: Char]Array[B] 
required: scala.collection.GenTraversableOnce[?] 
       ('0' to '9').toArray ++ ('A' to 'Z').toArray 
               ^

इसके अलावा, निम्नलिखित काम करने के लिए लगता है:

scala> (('0' to '9').toArray) ++ (('A' to 'Z').toArray[Char]) 
res4: Array[Char] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) 

मैं वास्तव में यह समझा नहीं सकता - क्या मुझे कुछ याद आ रही है?

+0

यह दोनों सीमाओं पर क्यों समय से पहले toArray द्वारा, वास्तविक प्रश्न का उत्तर नहीं है? नहीं होगा (('0' से '9') ++ ('ए' से 'ज़ेड'))। ToArray' इस समस्या को रोकें? – whaley

+0

मुझे लगता है कि यह इस प्रश्न से जुड़ा हुआ है http://stackoverflow.com/questions/6675419/in-scala-why-do-i-get-this-polymorphic-expression-cannot-be-instantiated-to-ex और प्रकार अनुमान –

+1

@waley मैं सिर्फ Arrays के साथ खेल रहा था और उस खोज में आया जो मैं समझा नहीं सकता था। मुझे पता है कि अंतिम परिणाम कैसे प्राप्त करें, लेकिन मैं वास्तव में समझा नहीं सकता कि क्यों '(' 0 'से' 9 ')। ToArray ++ (' ए 'से' Z ')। ToArray' काम नहीं करता है। @ डेविड मिचेलगैंग हाँ, यह वही त्रुटि जैसा दिखता है, लेकिन मैं वास्तव में समझ नहीं पा रहा हूं कि यह स्पष्टीकरण यहां कैसे लागू होता है। – argyakrivos

उत्तर

6

++ विधि ArrayOps में परिभाषित किया गया है:

def ++[B](that: GenTraversableOnce[B]): Array[B] 

से बाएं हन के तत्वों वाला एक नया म्यूटेबल अनुक्रमित अनुक्रम देता है डी ऑपरेंड दाएं हाथ से तत्वों के बाद ऑपरेंड। म्यूटेबल अनुक्रमित अनुक्रम का तत्व प्रकार सबसे विशिष्ट सुपरक्लास है जिसमें दो ऑपरेंड के तत्व प्रकार शामिल हैं।

ऐरे का प्रकार जिसमें परिणाम संग्रहीत किए जाते हैं, अनुमानित है।

('0' to '9').toArray ++ ('A' to 'Z').toArray 

('0' to '9').toArray अच्छा काम करता है, और हम वापस एक Array[Char] मिलता है।

8: materializing requested scala.reflect.type.ClassTag[Char] using `package` 
.this.materializeClassTag[Char]... 

विधि परिभाषा के अनुसार हम GenTraversableOnce[B] स्वीकार करते हैं। हमारे मामले में, हम GenTraversableOnce[Char] स्वीकार करते हैं।

यदि हम -Ytyper-debug विकल्प के साथ स्कैला चलाते हैं, तो हम कार्रवाई में प्रकार अनुमान देख सकते हैं।

//it tries to find the type of arg0 
typing '0'.to('1').toArray.$plus$plus('A'.to('B').toArray): pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode, silent=false, context.owner=value res1 
    typing '0'.to('1').toArray.$plus$plus: pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode BYVALmode POLYmode FUNmode, silent=true, context.owner=value res1 
     typing '0'.to('1').toArray: pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode POLYmode QUALmode, silent=true, context.owner=value res1 
      typing '0'.to('1'): pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode POLYmode QUALmode, silent=true, context.owner=value res1 
       typing '0'.to: pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode BYVALmode POLYmode FUNmode, silent=true, context.owner=value res1 
        typing '0': pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode POLYmode QUALmode, silent=true, context.owner=value res1 
        typed '0': Char('0') 
        adapted '0': Char to ?, 
//It succeeds. 
//Now it infers a scala type 
    infer implicit view { 
    tree   '0' 
    pt   Char('0') => ?{def to: ?} 

    } 
       new ImplicitSearch(floatWrapper) {...} 
       ... 
       new ImplicitSearch(charWrapper) {...} 

    } 

//The interesting bit... 
    typedImplicit1 charWrapper, pt=Char('0') => ?{def to: ?}, from implicit charWrapper:(c: Char)scala.runtime.RichChar 
    Implicit search yielded: SearchResult(scala.this.Predef.charWrapper,) 
      typed scala.this.Predef.charWrapper('0').to('1'): scala.collection.immutable.NumericRange.Inclusive[Char] 
      adapted scala.this.Predef.charWrapper('0').to('1'): scala.collection.immutable.NumericRange.Inclusive[Char] to ?, 
     typed scala.this.Predef.charWrapper('0').to('1').toArray: [B >: Char](implicit evidence$1: scala.reflect.ClassTag[B])Array[B] 

//repeat the process 
Infer implicit { 
tree   scala.this.Predef.charWrapper('0').to('1').toArray[Char] 
    pt   scala.reflect.ClassTag[Char] 
    undetparams 
}  

अनुमान प्रक्रिया को दोहराता है, और प्रकार है कि प्रकार है, जो ++ है पर विधि कॉल से आगे अनुमानित है। ('0' to '1').toArray ++ का प्रकार अंत में ArrayOps होने का हल हो गया है।

Implicit search yielded: SearchResult(scala.this.Predef.charArrayOps,) 

adapted this.charArrayOps(charWrapper('0').to('1').toArray[Char](ClassTag.Char)).++: [B >: Char, That](that: scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[Array[Char],B,That])That to ?, undetparams=type B, type That 

स्कैला फिर हमारे दूसरे तर्क टाइप करता है ...

typed scala.this.Predef.charWrapper('A').to('B'): scala.collection.immutable.NumericRange.Inclusive[Char] 
     adapted scala.this.Predef.charWrapper('A').to('B'): scala.collection.immutable.NumericRange.Inclusive[Char] to ?, 
    typed scala.this.Predef.charWrapper('A').to('B').toArray: [B >: Char](implicit evidence$1: scala.reflect.ClassTag[B])Array[B] 

अंत में, हम देखते हैं अगर हमारे Array[B]GenTraversableOnce विशेषता है।

infer implicit view { 
tree   <empty> 
    pt   Array[?B] => scala.collection.GenTraversableOnce[?] 
    undetparams 
} 
बेशक

, ऐसा नहीं है और हम पाते हैं:

typing private[this] val res1: <error> = '0'.to('1').toArray.$plus$plus('A'.to('B').toArray): pt = ?: undetparams=, implicitsEnabled=true, enrichmentEnabled=true, mode=EXPRmode BYVALmode, silent=false, context.owner=object $iw 
       typed private[this] val res1: <error> = scala.this.Predef.charArrayOps(scala.this.Predef.charWrapper('0').to('1').toArray[Char](ClassTag.Char)).++[B, That]('A'.to('B').toArray): <notype> 

के बारे में क्यों यह मामला है जानकारी के लिए https://stackoverflow.com/a/6124177/2823715 देखें।

समाधान ++ उपयोग करने के लिए है:

def ++:[B >: T, That](that: collection.Traversable[B])(implicit bf: CanBuildFrom[Array[T], B, That]): That 

यह अलग है सही संकार्य ++ से में है कि बाईं एक परिणामस्वरूप संग्रह के बजाय के प्रकार निर्धारित करता है। स्मारक: कोलोन नए संग्रह प्रकार के पक्ष में है।

यह Arrays से ArrayOps भी बनाता है, इसलिए आपको इसकी आवश्यकता है।

यह हमारे टाइपिंग डिबग आउटपुट द्वारा की पुष्टि की है:

typing { 
    <synthetic> val x$1 = '0'.to('1').toArray; 
    'A'.to('B').toArray.$plus$plus$colon(x$1) 
}: 
... 
typed scala.this.Predef.charWrapper('0').to('1').toArray: [B >: Char](implicit evidence$1: scala.reflect.ClassTag[B])Array[B] 
... 
typing scala.this.Predef.charArrayOps(scala.this.Predef.charWrapper('A').to('B').toArray(ClassTag.Char())).++:(scala.this.Predef.wrapCharArray(x$1), scala.this.Array.canBuildFrom(ClassTag.Char())): pt = Array[Char]: undetparams=, implicitsEnabled=false, enrichmentEnabled=false, mode=EXPRmode BYVALmode, silent=false, context.owner=value res2 
... 
<synthetic> val x$1: Array[Char] = new runtime.RichChar(scala.this.Predef.charWrapper('0')).to(scala.Char.box('1')).toArray(ClassTag.Char()).$asInstanceOf[Array[Char]](); 
    scala.this.Predef.charArrayOps(new runtime.RichChar(scala.this.Predef.charWrapper('A')).to(scala.Char.box('B')).toArray(ClassTag.Char()).$asInstanceOf[Array[Char]]()).++:(scala.this.Predef.wrapCharArray(x$1), scala.this.Array.canBuildFrom(ClassTag.Char())).$asInstanceOf[Array[Char]]() 
2

से संबंधित लगता है: https://issues.scala-lang.org/browse/SI-2394

शायद यह सिर्फ एक सीमा/unfixable Array रों से संबंधित बग है। ,

('0' to '9').toArray ++ ('A' to 'Z').toArray[Char] 

यह काम करने के लिए प्राप्त करने के लिए, जबकि आप के साथ प्रकार पैरामीटर की जरूरत नहीं है:: आप एक प्रकार पैरामीटर जोड़ सकते हैं

('0' to '9').toList ++ ('A' to 'Z').toList