summaryrefslogtreecommitdiff
path: root/core/src/main
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/main
parent28dbe29a2ab566249642e81405a953f33507828a (diff)
downloadmill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.tar.gz
mill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.tar.bz2
mill-eaba6c7ed4b1dc29c3b0d05be58f1bfd122f369d.zip
interpreter-based `Cross` seems to work
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/scala/mill/define/Cross.scala75
1 files changed, 62 insertions, 13 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