Mi piacerebbe ottenere in qualche modo al momento della compilazione il nome di un campo di una classe in un caso val (forse una stringa o un simbolo Singleton-digitato?).Come ottenere il nome di un campo di classe case come stringa/simbolo in fase di compilazione usando shapeless?
Qualcosa di simile a quanto segue:
import shapeless._
case class MyClass(field1: String, field2: Int)
val field1Lens = lens[MyClass] >> 'field1
// val name = field1Lens.name // it should be "field1", aka 'field1.name
non devo necessariamente utilizzare le lenti, qualsiasi tecnica che funziona va bene (qualcosa con LabelledGeneric
?). Mi piacerebbe avere qualcosa in cui posso ottenere il nome del campo della classe case senza specificarlo separatamente. In questo modo, se refactoring il nome del membro field1
nella classe, name
modifiche di conseguenza.
Ovviamente il seguente non funziona perché la macro non conosce al momento della compilazione del nome del simbolo:
val name = 'field1
val field1Lens = lens[MyClass] >> name // can't possibly work
ho provato lens[MyClass] >> name.narrow
ma non funziona nemmeno
Questo è quello che sto facendo attualmente, e naturalmente non mi piace:
// If I change the name of the field, compilation fails
// and I'm forced to check this line of code so I can change the string in the line below
protected val fieldNameCheck = lens[X].someField
val someField = "someField"
edit: Ok, ho dato uno sguardo a gabriele s' domanda, e utilizzando Keys
Sono in grado di ottenere una lista HL contenente i tasti (taggati) del record. Quello che mi serve però è ottenere un campo specifico, non un elenco che li contiene tutti.
che sto cercando di utilizzare select
per ottenere una chiave particolare, ma non sono riuscito finora
import shapeless._
import shapeless.syntax.singleton._
import shapeless.ops.record._
case class Foo(bar: String, baz: Boolean)
val labl = LabelledGeneric[Foo]
val keys = Keys[labl.Repr].apply
// the following doesn't work
// val bar = 'bar.narrow
// keys.select[bar.type]
// keys.get('bar)
Possibile duplicato di [Estrai valori etichetta da un'istanza LabelledGeneric] (http://stackoverflow.com/questions/27434302/extract-label-values-from-a-labelledgeneric-instance) –
Non credo di capire la motivazione: sembra che tu voglia scrivere il letterale "bar" in un punto del tuo codice in modo da non doverlo scrivere in un altro posto, e non sono sicuro di come ciò possa aiutare con il refactoring. Se sei preoccupato che i nomi dei membri cambino, i selettori posizionali potrebbero essere una scelta migliore. –
long story short: librerie di serializzazione.Non voglio essere costretto a scrivere serializzatori personalizzati per fare quello che le librerie già fanno (scrivendo oggetti JSON usando nomi di campi come chiavi, ecc.) Solo perché ho bisogno di avere il nome del campo in qualche altro posto (es. Quando si aggiorna parzialmente su elasticsearch). Scrivo solo una volta la barra letterale, ma se la classe case cambia, il codice viene comunque compilato. Avrei bisogno di un sacco di test solo per essere sicuro che per ogni ''bar' ho bisogno che ci sia un parametro della classe case' (bar: T) 'chiamato esattamente lo stesso: uno per ogni campo di ogni classe. –