2012-10-11 8 views
5

Dlaczego nie mogę mieć parametrów typu w moich metodach fabrycznych poniżej?Scala Array map zwraca ArraySeq

import org.junit.runner.RunWith 
import org.scalatest.junit.JUnitRunner 
import org.scalatest.FunSuite 

@RunWith(classOf[JUnitRunner]) 
class WhyScalaNeverWillMakeIt extends FunSuite { 

    test("Array becomes ArraySeq when you least want it") { 
    val arr = Array("A", "B", "C") 
    def f: String => Dummy = new Dummy(_) 

    val bucket = new Bucket[Dummy](arr.map(f)) 
// val bucket2 = Bucket[String, Dummy](arr, f) 
// val bucket3 = Bucket[Dummy](arr, f) 
    val bucket4 = Bucket(arr, f) 
    } 

    class Bucket[T](val arr: Array[T]) {/* Loads of business logic */} 

    object Bucket { 
// def apply[T, U](arr: Array[T], f:T=>U):Bucket[U] = new Bucket[U](arr.map(b => f(b))) 
// def apply[T](arr: Array[String], f:String=>T):Bucket[T] = new Bucket[T](arr.map(b => f(b))) 
    def apply(arr: Array[String], f:String=>Dummy):Bucket[Dummy] = new Bucket[Dummy](arr.map(f)) 
    } 


    class Dummy(val name: String) 
} 

Gdybym odkomentowaniu metod fabrycznych w object Bucket uzyskać:

error: type mismatch; 
found : scala.collection.mutable.ArraySeq[T] 
required: Array[T] 
def apply[T](arr: Array[String], f:String=>T):Bucket[T] = new Bucket[T](arr.map(b => f(b))) 

jakiś kompilator Scala irytować (czy to ja ;-)?) Kiedy wprowadzono parametr typu T. Może Robię tutaj coś bardzo złego, ale nie rozumiem, dlaczego wprowadzenie parametru typu oznacza, że ​​funkcja map powinna zmienić typ zwracania z Array [T] na ArraySeq [T].

Wiem, że Array to po prostu wrapper wokół Java Array i że prawdopodobnie powinienem używać jednej z bardziej wymyślnych klas Scala, takich jak Seq lub List, ale to nadal nie wyjaśnia tego dziwnego zachowania.

Czy ktoś może wyjaśnić, dlaczego tak się dzieje, a może i jak to naprawić (nadal używając Array)?

Edycja: używam Scala 2.9.1

Odpowiedz

5

Wystarczy dodać ClassManifest kontekst związany:

def apply[T, U: ClassManifest](arr: Array[T], f: T => U): Bucket[U] = new Bucket[U](arr.map(b => f(b))) 
    def apply[T: ClassManifest](arr: Array[String], f: String => T): Bucket[T] = new Bucket[T](arr.map(b => f(b))) 

Szczegółowe sprawdzić this i this

+0

Ok, dzięki Sergey, że wystarczyły. Teraz muszę tylko przeczytać i zrozumieć linki, które dostarczyłeś. Może jest coś, co sprawi, że zaakceptuję brzydką składnię ++ za pomocą [T: ClassManifest]. – Jorgen

+1

Wiem, co może sprawić, że zaakceptujesz tę składnię, widząc, do czego się ona wyprowadza: def foo [T: Bar] staje się def foo [T] (niejawnie generatedName: Bar [T]) –

Powiązane problemy