Zim-Zam O'Pootertoot
Zim-Zam O'Pootertoot

Reputation: 18148

Type-safe way to divide a tuple into multiple tuples

We have a trait that among other things contains an execute[T <: Record](Seq[(Session) => T]): Seq[T] method, where Record is the supertrait of all traits that we're retrieving from the database

trait DbTrait {
  val threadCount: Int
  val db: Database
  protected def getGroupSize(size: Int, threadCount: Int) {
    (size / threadCount) + if(size % threadCount == 0) 0 else 1
  }
  def execute[T <: Record](funs: Seq[(Session) => T]): Seq[T]
}

trait DbTraitSingle extends DbTrait {
  val threadCount = 1
  def execute[T <: Record](funs: Seq[(Session) => T]): Seq[T] =
    db.withSession{session: Session => funs.map(f => f(session))}
}

trait DbTraitMulti extends DbTrait {
  val threadCount = 4
  def execute[T <: Record](funs: Seq[(Session) => T): Seq[T] =
    funs.grouped(getGroupSize(funs.size, threadCount)).map(funs => Future {
      db.withSession{session: Session => funs.map(f => f(session))}
    }.toList.flatten
}

and so on. Ideally we'd like to be able to create something like a

def executePoly2[T1 <: Record, T2 <: Record]
  (tuple: Tuple2[(Session) => T1, (Session) => T2]): Tuple2[T1, T2]

for arbitrary tuples (i.e. an executePoly3, executePoly4, etc), but there are two problems:

  1. Is there a way to reduce the amount of boilerplate here, or would we be stuck creating 22 different method signatures?
  2. Is there a type-safe way to split up a tuple similar to the seq.grouped method call, or are we stuck having special cases for all of the different threadCount values (which at present doesn't exceed 4)?

Upvotes: 3

Views: 312

Answers (1)

wheaties
wheaties

Reputation: 35970

You can get to something very easy to use using the Shapeless library by Miles Sabin. See what they can do with a Tuple. Specifically abstracting over arity.

 import syntax.std.tuple._
 import poly._

 var myProducedTuple = myTuple map (_(session))

Upvotes: 1

Related Questions