2014-07-09 1 views
7

Ich schreibe generischen Code für die Verarbeitung von Listen von Fallklasseninstanzen, sammelt Werte in jedem Feld, kombiniert und dann an die Bibliothek übergeben.Wie zum Auflisten von formlosen Record und Zugriff Feldschlüssel in der Laufzeit?

Mit formlos LabelledGeneric und polymorphe Funktionen, sieht es wie folgt aus:

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 

Ich brauche aber einen Weg field.key zu bekommen, weil die Bibliothek die Parameternamen muss.

Würde es Ihnen etwas ausmachen, die Lösung vorzuschlagen?

Antwort

0

Gefunden schmutziger Hack zu Poly wie aussehen:

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]() 
    } 
} 

Gibt es eine schönere Lösung um?

11

Sie können den Schlüssel zugreifen als Laufzeitwert durch eine Instanz der Witness Typklasse (die zum Zeitpunkt der Kompilierung bekannt ist):

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

zur Laufzeit Reflexion Keine Notwendigkeit!

+0

Vielen Dank! Ich habe jetzt ein paar Dinge neu zu schreiben, aber es hat tatsächlich Fortschritte für mich ermöglicht. BTW, ich habe versucht, Aux'es zu verwenden, aber ich konnte Aux nicht herausfinden, welches Objekt ich verwenden muss. Keine Dokumente für die Aux'es, und es ist fast unmöglich, dieses Wissen aus dem formlosen Quellcode abzuleiten, da Aux-Definitionen über alle formlosen Quellcodedateien verstreut sind. –

+0

Die 'Aux'-Typen sind alle mit einer bestimmten Typklasse gepaart und sollen einen Typmember zu einem Typparameter befördern. Du könntest das mit 'wk: Witness {type T = K}' schreiben, aber die 'Aux'-Version ist schöner. –

Verwandte Themen