2011-11-10 19 views
43

C'è un modo semplice per convertire una classe di case in una tupla?In Scala, c'è un modo semplice per convertire una classe di case in una tupla?

Posso, naturalmente, scrivere facilmente il codice boilerplate per farlo, ma voglio dire senza il boilerplate.

Quello che sto cercando è un modo per rendere facilmente classificabile in modo lessicografico l'ordine. Posso raggiungere l'obiettivo di tuple importando scala.math.Ordering.Implicits._ e voilà, le mie tuple hanno un Ordine definito per loro. Ma gli impliciti in scala.math.Ordering non funzionano per le case case in generale.

risposta

64

Che ne dici di chiamare unapply().get() nell'oggetto associato?

case class Foo(foo:String, bar:Int) 

val (str, in) = Foo.unapply(Foo("test", 123)).get() 
+3

grazie per i suggerimenti, nel REPL 2.9.0-1 ho dovuto rimuovere il() per "ottenere" – Tanjona

+0

molto bello! Non avevo idea di unpply –

+0

Cool, ha funzionato! Con il tuo suggerimento sono stato in grado di ottenere la mia classe del caso Ordinata in questo modo: 'val thisTuple: Ordered [(String, Int)] = Foo.unapply (this) .get; val thatTuple = Foo.unapply (that) .get; thisTuple confronta thatTuple'. Questa non è la cosa più carina del mondo, quindi sono ancora aperto a suggerimenti, ma la tua risposta sicuramente ha portato a termine il lavoro. Grazie! – Douglas

3

Si potrebbe provare a estendere il ProductN tratto, per N = 1-22, che si estende TupleN. Ti darà un sacco di semantica della Tupla, come i metodi _1, _2, ecc. A seconda di come usi i tuoi tipi, questo potrebbe essere sufficiente senza creare una Tupla effettiva.

+0

Non sono sicuro di come far funzionare questo approccio per me. Voglio che la mia casistica sia ordinata lessicograficamente o che abbia un ordinamento lessicografico, senza dover scrivere molte lettere. L'estensione di ProductN non sembra funzionare con gli impliciti in scala.math.Ordering che consentono di assegnare facilmente alle tuple un ordinamento lessicografico. – Douglas

0

Si è imbattuto in questo thread precedente mentre si tentava di fare la stessa cosa. Alla fine ho optato per questa soluzione:

case class Foo(foo: String, bar: Int) 

val testFoo = Foo("a string", 1) 

val (str, in) = testFoo match { case Foo(f, b) => (f, b) } 
0

Shapeless farà questo per voi.

import shapeless._ 
    import shapeless.syntax.std.product._ 

    case class Fnord(a: Int, b: String) 

    List(Fnord(1, "z - last"), Fnord(1, "a - first")).sortBy(_.productElements.tupled) 

Gets

res0: List[Fnord] = List(Fnord(1,a - first), Fnord(1,z - last)) 

productElements trasforma una classe case in un informe HList:

scala> Fnord(1, "z - last").productElements 
res1: Int :: String :: shapeless.HNil = 1 :: z - last :: HNil 

E HLists vengono convertiti in tuple con #tupled:

scala> Fnord(1, "z - last").productElements.tupled 
res2: (Int, String) = (1,z - last) 

prestazioni è probabile che sia horri ble, dal momento che stai costantemente convertendo. Probabilmente converti tutto in una forma tupla, riordinala, quindi riconvertila usando qualcosa come (Fnord.apply _).tupled.

Problemi correlati