2012-10-11 24 views
5

¿Por qué no puedo tener parámetros de tipo en mis métodos de fábrica a continuación?El mapa Scala Array devuelve 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) 
} 

Si Descomentar los métodos de fábrica en object Bucket me sale:

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

De algún modo el compilador Scala se confundió (o soy yo ;-)?) Cuando introduje el parámetro de tipo T. Tal vez Aquí estoy haciendo algo muy malo, pero no veo por qué introducir un parámetro de tipo significa que la función de mapa debería cambiar el tipo de retorno de Array [T] a ArraySeq [T].

sé que la matriz es simplemente una envoltura alrededor de la matriz de Java y que probablemente debería utilizar una de las clases más elegantes Scala, tales como la SEC o la lista, pero que todavía no explica este comportamiento bastante extraño.

¿Alguien puede explicar por qué sucede esto y tal vez también cómo solucionarlo (aún usando matrices)?

Editar: Estoy usando Scala 2.9.1

Respuesta

5

Sólo tiene que añadir ClassManifest contexto obligado:

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

Para más detalles consultar this y this

+0

Bien, gracias Sergey, que hizo el truco. Ahora solo tengo que leer y comprender los enlaces que me proporcionó. Tal vez haya algo allí que me haga aceptar la fea sintaxis ++ con [T: ClassManifest]. – Jorgen

+1

Sé lo que puede hacerte aceptar esa sintaxis, viendo lo que desea: def foo [T: Bar] se convierte en def foo [T] (nombre generado implícito: Bar [T]) –