org.specs2.matcher.DataTable.scala Maven / Gradle / Ivy
package org.specs2
package matcher
import execute._
import ResultExecution._
import text.{Trim, TextTable, NotNullStrings}
import Trim._
import NotNullStrings._
import ResultLogicalCombinators._
/**
* This trait provides implicit definitions and types to create DataTables.
*
* A DataTable has a header defining column names and rows holding values.
* It is possible to apply a function taking the row values and returning a MatchResult.
*
* A TableHeader is defined by separating the column names with '|':
* ` "a" | "b" | "c"`
*
* A DataRow is defined by separating the row values with '!':
* ` 1 ! 2 ! 3`
*
* Note that the '!' method can conflict with the creation of Examples when the value is a
* string. In that case it is possible to use the '!!! method to disambiguate:
*
* `"1" !! "2" ! "3"`
*
* In that case the first column of the header can also be defined with '||' for pure
* symmetry reasons:
*
* `"a" || "b" | "c"`
* `"1" !! "2" ! "3"`
*
* @see org.specs2.matcher.DataTablesSpec for examples
*/
trait DataTables extends Expectations {
/** @return a TableHeader with one heading only */
implicit def toTableHeader(a: String) = new TableHeader(List(a))
/** @return a DataRow with one value only */
implicit def toDataRow[T](a: T) = DataRow1(a)
/**
* A DataTable with its header
*
* Children of this class are parametrized with the types of values that their rows can
* hold.
*/
abstract class Table(val titles: List[String], val execute: Boolean = false) {
/**
* Collect the results of each row
* @param results list of (row description, row execution result)
* @return an aggregated Result from a list of results
*/
protected def collect[R : AsResult](results: List[(Seq[String], R)]): DecoratedResult[DataTable] = {
val result = allSuccess(results)
val decorated =
DecoratedResult(DataTable(titles, results), result.updateMessage {
TextTable("" +: titles :+ "", results.map { case (line, r) => resultLine(line, AsResult(r)) }:_*).show
})
checkResultFailure(decorated)
decorated
}
/** @return the logical and combination of all the results */
private def allSuccess[R : AsResult](results: List[(Seq[String], R)]): Result = {
results.foldLeft(Success("", results.size): Result)((res, cur) => res and AsResult(cur._2))
}
/** @return the status of the row + the values + the failure message if any */
private def resultLine(line: Seq[String], result: Result): Seq[String] = {
val message = if (result.isSuccess) "" else result.message
result.status +: line :+ message
}
}
/** GENERATED */
case class TableHeader(titles: List[String]) {
def ||(title: String) = copy(titles = this.titles :+ title)
def |(title: String) = copy(titles = this.titles :+ title)
def |[T1](row: DataRow1[T1]) = new Table1(titles, List(row))
def |>[T1](row: DataRow1[T1]) = new Table1(titles, List(row), execute = true)
def |[T1, T2](row: DataRow2[T1, T2]) = new Table2(titles, List(row))
def |>[T1, T2](row: DataRow2[T1, T2]) = new Table2(titles, List(row), execute = true)
def |[T1, T2, T3](row: DataRow3[T1, T2, T3]) = new Table3(titles, List(row))
def |>[T1, T2, T3](row: DataRow3[T1, T2, T3]) = new Table3(titles, List(row), execute = true)
def |[T1, T2, T3, T4](row: DataRow4[T1, T2, T3, T4]) = new Table4(titles, List(row))
def |>[T1, T2, T3, T4](row: DataRow4[T1, T2, T3, T4]) = new Table4(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5](row: DataRow5[T1, T2, T3, T4, T5]) = new Table5(titles, List(row))
def |>[T1, T2, T3, T4, T5](row: DataRow5[T1, T2, T3, T4, T5]) = new Table5(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6](row: DataRow6[T1, T2, T3, T4, T5, T6]) = new Table6(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6](row: DataRow6[T1, T2, T3, T4, T5, T6]) = new Table6(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1, T2, T3, T4, T5, T6, T7]) = new Table7(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1, T2, T3, T4, T5, T6, T7]) = new Table7(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) = new Table8(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) = new Table8(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) = new Table9(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) = new Table9(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) = new Table10(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) = new Table10(titles, List(row), execute = true)
}
case class Table1[T1](override val titles: List[String], rows: List[DataRow1[T1]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |(row: DataRow1[T1]) = Table1(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow1[T1]) => (d.showCells, AsResult(f(d.t1)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table2[T1, T2](override val titles: List[String], rows: List[DataRow2[T1, T2]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2](row: DataRow2[S1, S2]) = Table2(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow2[T1, T2]) => (d.showCells, AsResult(f(d.t1,d.t2)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table3[T1, T2, T3](override val titles: List[String], rows: List[DataRow3[T1, T2, T3]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3](row: DataRow3[S1, S2, S3]) = Table3(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow3[T1, T2, T3]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table4[T1, T2, T3, T4](override val titles: List[String], rows: List[DataRow4[T1, T2, T3, T4]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4](row: DataRow4[S1, S2, S3, S4]) = Table4(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow4[T1, T2, T3, T4]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table5[T1, T2, T3, T4, T5](override val titles: List[String], rows: List[DataRow5[T1, T2, T3, T4, T5]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5](row: DataRow5[S1, S2, S3, S4, S5]) = Table5(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow5[T1, T2, T3, T4, T5]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table6[T1, T2, T3, T4, T5, T6](override val titles: List[String], rows: List[DataRow6[T1, T2, T3, T4, T5, T6]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6](row: DataRow6[S1, S2, S3, S4, S5, S6]) = Table6(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5, T6) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5, T6) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5, T6) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow6[T1, T2, T3, T4, T5, T6]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5,d.t6)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table7[T1, T2, T3, T4, T5, T6, T7](override val titles: List[String], rows: List[DataRow7[T1, T2, T3, T4, T5, T6, T7]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7](row: DataRow7[S1, S2, S3, S4, S5, S6, S7]) = Table7(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow7[T1, T2, T3, T4, T5, T6, T7]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5,d.t6,d.t7)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table8[T1, T2, T3, T4, T5, T6, T7, T8](override val titles: List[String], rows: List[DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8](row: DataRow8[S1, S2, S3, S4, S5, S6, S7, S8]) = Table8(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow8[T1, T2, T3, T4, T5, T6, T7, T8]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5,d.t6,d.t7,d.t8)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table9[T1, T2, T3, T4, T5, T6, T7, T8, T9](override val titles: List[String], rows: List[DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9](row: DataRow9[S1, S2, S3, S4, S5, S6, S7, S8, S9]) = Table9(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5,d.t6,d.t7,d.t8,d.t9)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
case class Table10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](override val titles: List[String], rows: List[DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], override val execute: Boolean = false) extends Table(titles, execute) { outer =>
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9, S10 >: T10](row: DataRow10[S1, S2, S3, S4, S5, S6, S7, S8, S9, S10]) = Table10(titles, outer.rows :+ row, execute)
def |[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) = executeRow(f, execute)
def |>[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) = executeRow(f, true)
def executeRow[R : AsResult](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec)
collect(rows map { (d: DataRow10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) => (d.showCells, AsResult(f(d.t1,d.t2,d.t3,d.t4,d.t5,d.t6,d.t7,d.t8,d.t9,d.t10)).execute) })
else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success("ok"))
}
}
abstract class DataRow[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Product {
def show = productIterator.mkString("|", "|", "|")
def showCells = productIterator.map(_.notNull).toSeq
}
case class DataRow1[T1](t1: T1) extends DataRow[T1, Any, Any, Any, Any, Any, Any, Any, Any, Any] {
def ![S2](t2: S2) = DataRow2(t1, t2)
def !![S2](t2: S2) = DataRow2(t1, t2)
}
case class DataRow2[+T1, +T2](t1: T1, t2: T2) extends DataRow[T1, T2, Any, Any, Any, Any, Any, Any, Any, Any] {
def ![S3](t3: S3) = DataRow3(t1, t2, t3)
def !![S3](t3: S3) = DataRow3(t1, t2, t3)
}
case class DataRow3[+T1, +T2, +T3](t1: T1, t2: T2, t3: T3) extends DataRow[T1, T2, T3, Any, Any, Any, Any, Any, Any, Any] {
def ![S4](t4: S4) = DataRow4(t1, t2, t3, t4)
def !![S4](t4: S4) = DataRow4(t1, t2, t3, t4)
}
case class DataRow4[+T1, +T2, +T3, +T4](t1: T1, t2: T2, t3: T3, t4: T4) extends DataRow[T1, T2, T3, T4, Any, Any, Any, Any, Any, Any] {
def ![S5](t5: S5) = DataRow5(t1, t2, t3, t4, t5)
def !![S5](t5: S5) = DataRow5(t1, t2, t3, t4, t5)
}
case class DataRow5[+T1, +T2, +T3, +T4, +T5](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) extends DataRow[T1, T2, T3, T4, T5, Any, Any, Any, Any, Any] {
def ![S6](t6: S6) = DataRow6(t1, t2, t3, t4, t5, t6)
def !![S6](t6: S6) = DataRow6(t1, t2, t3, t4, t5, t6)
}
case class DataRow6[+T1, +T2, +T3, +T4, +T5, +T6](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) extends DataRow[T1, T2, T3, T4, T5, T6, Any, Any, Any, Any] {
def ![S7](t7: S7) = DataRow7(t1, t2, t3, t4, t5, t6, t7)
def !![S7](t7: S7) = DataRow7(t1, t2, t3, t4, t5, t6, t7)
}
case class DataRow7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7) extends DataRow[T1, T2, T3, T4, T5, T6, T7, Any, Any, Any] {
def ![S8](t8: S8) = DataRow8(t1, t2, t3, t4, t5, t6, t7, t8)
def !![S8](t8: S8) = DataRow8(t1, t2, t3, t4, t5, t6, t7, t8)
}
case class DataRow8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, Any, Any] {
def ![S9](t9: S9) = DataRow9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
def !![S9](t9: S9) = DataRow9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
}
case class DataRow9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, T9, Any] {
def ![S10](t10: S10) = DataRow10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
def !![S10](t10: S10) = DataRow10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
}
case class DataRow10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9, t10: T10) extends DataRow[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {
}
}
case class DataTable(titles: Seq[String], rows: Seq[DataTableRow]) {
def isSuccess = rows.forall(_.isSuccess)
def show = TextTable(titles, rows.map(row => row.cells.map(_.toString))).show
}
object DataTable {
def apply[R : AsResult](titles: Seq[String], results: Seq[(Seq[String], R)]): DataTable = DataTable(titles, results.collect { case (v, r) => DataTableRow(v, AsResult(r)) })
}
case class DataTableRow(cells: Seq[String], result: Result) {
def isSuccess = result.isSuccess
}
object DataTableRow {
def apply[R : AsResult](values: String, result: R): DataTableRow = DataTableRow(values.trimEnclosing("|").splitTrim("\\|"), AsResult(result))
}
private[specs2]
object DataTables extends DataTables
/**
private object DataTablesGenerator {
def main(args: Array[String]) = {
println(all(10))
}
def all(n: Int) = {
List(tableHeader(n),
tableClasses(n),
dataRowClass(n),
dataRowClasses(n)).mkString("\n\n").replace("\n", "\n ")
}
def tableHeader(n: Int) = {
"case class TableHeader(titles: List[String]) {\n"+
" def |(title: String) = copy(titles = this.titles :+ title)\n"+
(1 to n).flatMap { i =>
val addRow = types(i)+"(row: "+dataRow(i)+") = new "+table(i)+"(titles, List(row)"
val addRowStill = "def |"+addRow
val addRowExecute = "def |>"+addRow
List(addRowStill, addRowExecute+", execute = true").map(_+")")
}.mkString(" ", "\n ", "\n") +
"}"
}
def tableClasses(n: Int) = {
(1 to n).map { i =>
List("case class Table"+i+types(i)+"(override val titles: List[String], rows: List["+dataRow(i)+"], override val execute: Boolean = false) extends "+
"Table(titles, execute) { outer =>",
" def |[st(i)](row: "+dataRow(i, letter=\"S\")+") = "+table(i)+"(titles, outer.rows :+ row, execute)",
" def |[R : AsResult](f: "+typesTuple(i)+" => R) = executeRow(f, execute)",
" def |>[R : AsResult](f: "+typesTuple(i)+" => R) = executeRow(f, true)",
" def executeRow[R : AsResult](f: "+typesTuple(i)+" => R, exec: Boolean): DecoratedResult[DataTable] = {",
" if (exec)",
" collect(rows map { (d: "+dataRow(i)+") => (d.showCells, AsResult(f("+(1 to i).map("d.t"+_).mkString(",")+")).execute) })",
" else DecoratedResult(DataTable(titles, Seq[DataTableRow]()), Success(\"ok\"))",
" }",
"}").mkString("\n")
}.mkString("\n")
}
def dataRowClass(n: Int) = {
"abstract class DataRow"+types(n)+" extends Product {\n"+
" def show = productIterator.mkString(\"|\", \"|\", \"|\")\n"+
"}"
}
def dataRowClasses(n: Int) = {
(1 to n).map { i =>
List(
"case class "+dataRow(i)+parametersList(i)+" extends DataRow["+typesList(i, n)+"] {",
if (i < n) " def ![S"+(i+1)+"](t"+(i+1)+": S"+(i+1)+") = "+"DataRow"+(i+1)+parameters(i+1) else "",
if (i < n) " def !![S"+(i+1)+"](t"+(i+1)+": S"+(i+1)+") = "+"DataRow"+(i+1)+parameters(i+1) else "",
"}").mkString("\n")
}.mkString("\n")
}
def parametersList(i: Int) = (1 to i).map(j => "t"+j+": T"+j).mkString("(",", ", ")")
def parameters(i: Int) = (1 to i).map("t"+_).mkString("(",", ", ")")
def variantTypes(i: Int, letter: String = "T") = typesAsList(i, letter).map("+"+_).mkString("[",", ", "]")
def types(i: Int) = typesAsList(i).mkString("[",", ", "]")
def st(i: Int) = (1 to i).map(j => "S"+j+" >: T"+j).mkString("[",", ", "]")
def typesAsList(i: Int, letter: String = "T"): String = (1 to i).map(letter+_)
def typesList(i: Int): String = typesAsList(i).mkString(", ")
def typesList(i: Int, n: Int): String = (List(typesList(i)) ::: (i+1 to n).map(t => "Any").toList).mkString(", ")
def typesTuple(i: Int) = typesAsList(i).mkString("(",", ", ")")
def dataRow(i: Int, letter: String = "T") = "DataRow"+i+variantTypes(i, letter)
def table(i: Int) = "Table"+i
}
*/
© 2015 - 2025 Weber Informatics LLC | Privacy Policy