2012-07-27 4 views
7

tengo método de biblioteca tomando lista de argumentos variable y la producción de datosScala implícita con la lista de argumentos variable

class Data 
def process(elems: String*): Data = new Data 

y quiero que mis cadenas que se convierten implícitamente a Data

implicit def strToData(ts: String): Data = process(t) 

para que pueda escribir algo como

val data: Data = "one" 

pero quiero que las tuplas de cadenas sean impli citly convertido también. He añadido otra implícita

implicit def strsToData(ts: String*): Data = process(ts: _*) 

que compila bien, pero la conversión falla

val data: Data = ("one", "two") 
val dat3: Data = ("one", "two", "three") 
val dat4: Data = ("one", "two", "three", "four") 

con

found : Seq[java.lang.String] 
required: this.Data 
val data: Data = Seq("one", "two") 

¿Hay alguna manera de convertir tuplas implícitamente, o una razón por la que puede ¿ser logrado?

Actualización: Las tuplas pueden ser de cualquier tipo.

+2

¿Estás seguro de que las Tuplas pueden ser de algún otro tipo? Creo que max es 22 (ver http://www.scala-lang.org/api/current/scala/Tuple23.html vs http://www.scala-lang.org/api/current/scala/Tuple22.html) – Martijn

Respuesta

3

Si bien todas las advertencias en @ respuesta de NikitaVolkov aplican en doble fuerza, que puede escribir una versión que acepta cualquier aridad de tupla, así como cualquier clase de caso:

implicit def prod2data(Product p): process((p.productIterator.toSeq):_*) 
+1

¡Gracias, exactamente lo que estaba buscando! – lambdas

2

Usted tendría que crear una conversión implícita de una tupla a Data:

implicit def strTplToData(ts:(String, String)) = process(ts._1, ts._2) 

entonces se podría hacer:

val data: Data = ("one", "two") 
+1

¿Existe alguna otra solución que escribir funciones para cada tupla? – lambdas

+1

No creo que haya una manera elegante de lograr eso simplemente. –

5
  1. ts: String* no es una tupla, sino una Iterable. No puede convertir iterable en tupla, porque tuple es un tipo estático y su arity se resuelve en tiempo de compilación. Emil H respondió cómo puedes hacer una conversión implícita de tupla.
  2. Las conversiones implícitas transparentes de un tipo a otro tipo son una trampa común y se desaconsejan en gran medida. En su lugar debe aplicar un enfoque de "envoltura", o use "clases de valores", ya Scala 2.10:

    En Scala 2.9:

    implicit def stringStringTupleExtender (ts : (String, String)) = 
        new { 
        def data = process(ts) 
        } 
    

    En Scala 2.10:

    implicit class StringStringTupleExtender (val ts : (String, String)) extends AnyVal { 
        def data = process(ts) 
    } 
    

    entonces te usarlo de esta manera:

    val data : Data = ("sdf", "lsdfj").data 
    val data1 : Data = "sdf".data // if you do the same for String 
    
  3. Si usted está buscando para resolver dinámicamente cualquier colección de entrada y, a continuación, conjetura qué, debes usar una colección, no una tupla.

    En Scala 2.9

    implicit def seqExtender (ts : Seq[String]) = 
        new { 
        def data = process(ts) 
        } 
    

    Uso:

    val data : Data = Seq("sdf", "lsdkfjsdl", "ldsfjk").data 
    
Cuestiones relacionadas