web-dev-qa-db-fra.com

En Scala, existe-t-il un moyen simple de convertir une classe de cas en tuple?

Existe-t-il un moyen simple de convertir une classe de cas en un tuple?

Je peux, bien sûr, écrire facilement le code standard pour le faire, mais je veux dire sans le standard.

Ce que je recherche vraiment, c’est un moyen de créer facilement une classe de cas ordonnée lexicographiquement. Je peux atteindre l'objectif pour les n-uplets en important scala.math.Ordering.Implicits._, et le tour est joué, mes n-uplets ont un ordre défini pour eux. Mais les implications de scala.math.Ordering ne fonctionnent pas pour les classes de cas en général.

48
Douglas

Pourquoi ne pas appeler unapply().get() dans l'objet compagnon?

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

val (str, in) =  Foo.unapply(Foo("test", 123)).get()
68
S-C

Vous pouvez essayer d'étendre le trait ProductN, pour N = 1-22, qui TupleN s'étend. Cela vous donnera beaucoup de sémantique de Tuple, comme les méthodes _1, _2, etc. Selon votre utilisation des types, cela peut être suffisant sans créer de tuple réel. 

3
Dean Wampler

Shapeless fera cela pour vous.

  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)

Obtient

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

productElements transforme une classe de cas en une HList sans forme:

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

Et les HLists sont converties en n-uplets avec #tupled:

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

Les performances risquent d'être horribles, car vous convertissez en permanence. Vous voudriez probablement tout convertir au format tuplé, trier cela, puis le reconvertir en utilisant quelque chose comme (Fnord.apply _).tupled.

2
James Moore

Entré dans ce vieux fil en essayant de faire la même chose. J'ai finalement opté pour cette solution:

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
AnthonyShipman