summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-16 04:18:17 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-16 04:18:17 -0800
commiteaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d (patch)
tree17161703938ea0ea862ede41f4980fcd521468e1 /core/src
parent28dbe29a2ab566249642e81405a953f33507828a (diff)
downloadmill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.tar.gz
mill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.tar.bz2
mill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.zip
interpreter-based `Cross` seems to work
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/mill/define/Cross.scala75
-rw-r--r--core/src/test/scala/mill/CrossTests.scala71
2 files changed, 99 insertions, 47 deletions
diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala
index c84e9b3d..1f457096 100644
--- a/core/src/main/scala/mill/define/Cross.scala
+++ b/core/src/main/scala/mill/define/Cross.scala
@@ -1,18 +1,67 @@
package mill.define
+sealed trait Cross[T]{
+ def flatMap[V](f: T => Cross[V]): Cross[V] = new Cross.FlatMapping(this, f)
+ def map[V](f: T => V): Cross[V] = new Cross.Mapping(this, f)
+ def withFilter(f: T => Boolean): Cross[T] = new Cross.Filtering(this, f)
-case class Cross[+T](items: T*){
- def flatMap[V](f: T => Cross[V]): Cross[(T, V)] = {
- val flattened = for{
- i <- items
- k <- f(i).items
- } yield (i, k)
- Cross(flattened:_*)
- }
- def map[V](f: T => V): Cross[(T, V)] = {
- Cross(items.map(i => i -> f(i)):_*)
+}
+object Cross{
+ class Listing[T](val items: Seq[T]) extends Cross[T]
+ class Mapping[T, V](val parent: Cross[T], val f: T => V) extends Cross[V]
+ class FlatMapping[T, V](val parent: Cross[T], val f: T => Cross[V]) extends Cross[V]
+ class Filtering[T](val parent: Cross[T], val f: T => Boolean) extends Cross[T]
+
+ def apply[T](t: T*) = new Cross.Listing(t)
+
+ def evaluate[T](c: Cross[T]): List[(List[Any], T)] = c match{
+ case c: Listing[T] => c.items.map(i => List(i) -> i).toList
+ case c: Mapping[_, T] => evaluate(c.parent).map{case (l, v) => (l, c.f(v))}
+ case c: FlatMapping[_, T] =>
+ evaluate(c.parent).flatMap{
+ case (l, v) => evaluate(c.f(v)).map{case (l2, v2) => (l2 ::: l, v2)}
+ }
+ case c: Filtering[T] => evaluate(c.parent).filter(t => c.f(t._2))
}
- def withFilter(f: T => Boolean) = {
- Cross(items.filter(f):_*)
+ def test() = {
+ val example1 = evaluate(
+ for(a <- Cross(1, 2, 3))
+ yield a.toString
+ )
+ pprint.log(example1)
+
+ val example2 = evaluate(
+ for{
+ a <- Cross(1, 2, 3)
+ b <- Cross("A", "B", "C")
+ } yield b * a
+ )
+ pprint.pprintln(example2)
+
+ val example3 = evaluate(
+ for{
+ a <- Cross(1, 2, 3)
+ b <- Cross("A", "B", "C")
+ c <- Cross(true, false)
+ } yield b * a + c
+ )
+ pprint.log(example3)
+
+ val example4 = evaluate(
+ for{
+ a <- Cross(1, 2, 3)
+ b <- Cross("A", "B", "C")
+ if !(a == 2 && b == "B")
+ } yield b * a
+ )
+ pprint.log(example4)
+
+ val example5 = evaluate(
+ for{
+ (a, b) <- for(a <- Cross(1, 2, 3); b <- Cross("A", "B", "C")) yield (a, b)
+ c <- Cross(true, false)
+ } yield b * a + c
+ )
+ pprint.log(example5)
}
-}
+} \ No newline at end of file
diff --git a/core/src/test/scala/mill/CrossTests.scala b/core/src/test/scala/mill/CrossTests.scala
index ebf5d065..d39072c5 100644
--- a/core/src/test/scala/mill/CrossTests.scala
+++ b/core/src/test/scala/mill/CrossTests.scala
@@ -6,41 +6,44 @@ import utest._
object CrossTests extends TestSuite{
val tests = Tests{
- def assertEquals[T](value: Cross[T], value1: Cross[T]) = {
- assert(value == value1)
- }
- 'map - assertEquals(
- for(a <- Cross(1, 2, 3)) yield a.toString,
- Cross(1 -> "1", 2 -> "2", 3 -> "3")
- )
- 'flatMapFilter - assertEquals(
- for{
- a <- Cross(1, 2)
- b <- Cross("A", "B")
- if !(a == 2 && b == "B")
- } yield b * a,
- Cross(
- (1 -> ("A" -> "A")),
- (1 -> ("B" -> "B")),
- (2 -> ("A" -> "AA"))
- )
- )
- 'reuse - {
- val matrix = for{
- a <- Cross(1, 2)
- b <- Cross("A", "B")
- if !(a == 2 && b == "B")
- } yield ()
- assertEquals(
- for((a, (b, _)) <- matrix)
- yield b * a,
- Cross(
- (1 -> ("A" -> "A")),
- (1 -> ("B" -> "B")),
- (2 -> ("A" -> "AA"))
- )
- )
+ 'test - {
+ Cross.test()
}
+// def assertEquals[T](value: Cross[T], value1: Cross[T]) = {
+// assert(value == value1)
+// }
+// 'map - assertEquals(
+// for(a <- Cross(1, 2, 3)) yield a.toString,
+// Cross(1 -> "1", 2 -> "2", 3 -> "3")
+// )
+// 'flatMapFilter - assertEquals(
+// for{
+// a <- Cross(1, 2)
+// b <- Cross("A", "B")
+// if !(a == 2 && b == "B")
+// } yield b * a,
+// Cross(
+// (1 -> ("A" -> "A")),
+// (1 -> ("B" -> "B")),
+// (2 -> ("A" -> "AA"))
+// )
+// )
+// 'reuse - {
+// val matrix = for{
+// a <- Cross(1, 2)
+// b <- Cross("A", "B")
+// if !(a == 2 && b == "B")
+// } yield ()
+// assertEquals(
+// for((a, (b, _)) <- matrix)
+// yield b * a,
+// Cross(
+// (1 -> ("A" -> "A")),
+// (1 -> ("B" -> "B")),
+// (2 -> ("A" -> "AA"))
+// )
+// )
+// }
}