2014-07-09 7 views
7

Sto scrivendo codice generico per l'elaborazione di elenchi di istanze di case class, che raccolgono valori in ogni campo, combinandolo e quindi passandolo alla libreria.Come enumerare senza forma Registrare e accedere alle chiavi di campo in runtime?

Utilizzando le funzioni informi LabelledGeneric e polimorfi, sembra che questo:

object toNamedSingletonListOfValues extends Poly1 { 
    implicit def caseField[K,T] = 
    at[FieldType[K, T]](field => { field.key -> List[T](field) }) 
} 

val generic = LabelledGeneric[MyClass] 
val records = listOfMyClassInstances.map(generic.to) 
val values = records.map(_.map(toNamedSingletonListOfValues)) // Then combining and passing 

Tuttavia, ho bisogno di un modo di ottenere field.key perché la libreria ha bisogno i nomi dei parametri.

Ti dispiacerebbe suggerire la soluzione?

risposta

0

Trovato sporco hack è quello di rendere Poly assomigliare:

import scala.reflect.runtime.universe._ 

object toNamedSingletonListOfValues extends Poly1 { 
    implicit def caseField[K: TypeTag, T] = at[FieldType[K, T]] { field => 
    (typeOf[K] match { case TypeRef(_, _, args) => args }).last.toString.drop("java.lang.String(\"".size).dropRight(2) -> List[T]() 
    } 
} 

C'è una soluzione più bello in giro?

11

È possibile accedere alla chiave (che è noto al momento della compilazione) come valore di runtime attraverso un'istanza della classe Witness tipo:

object toNamedSingletonListOfValues extends Poly1 { 
    implicit def caseField[K, T](implicit wk: Witness.Aux[K]) = 
    at[FieldType[K, T]](field => { wk.value -> List[T](field) }) 
} 

Non c'è bisogno di riflessione runtime!

+0

Grazie! Ho alcune cose in più da riscrivere ora, ma in realtà mi ha permesso di progredire. A proposito, stavo cercando di usare Aux, tuttavia, non riuscivo a capire Aux da quale oggetto ho bisogno di usare. Nessun documento per gli Aux, ed è quasi impossibile dedurre questa conoscenza dal codice sorgente informe, poiché le definizioni Aux sono sparse su tutti i file di codice sorgente informi. –

+0

I tipi 'Aux' sono tutti abbinati a una classe di tipo specifica e sono progettati per promuovere un membro di tipo in un parametro di tipo. Si potrebbe scrivere con 'wk: Witness {type T = K}', ma la versione 'Aux' è più bella. –