mirror of https://github.com/sbt/sbt.git
Reduce allocation of Action.Mapped
For a tuple (t1, t2, ..., tn) of tasks we instantiate a unique Mapped instead of many Mapped(t1, Mapped(t2, Mapped(...))
This commit is contained in:
parent
57db671073
commit
31710c0879
|
|
@ -308,10 +308,11 @@ trait Cont:
|
|||
tupleMapRepr.asType match
|
||||
case '[tupleMap] =>
|
||||
'{
|
||||
given Applicative[F] = $applicativeExpr
|
||||
import TupleMapExtension.*
|
||||
${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] }
|
||||
.mapN(${ lambda.asExprOf[inputTypeTpe & Tuple => A1] })
|
||||
$applicativeExpr.mapN(
|
||||
${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] }
|
||||
)(
|
||||
${ lambda.asExprOf[inputTypeTpe & Tuple => A1] }
|
||||
)
|
||||
}
|
||||
eitherTree match
|
||||
case Left(_) =>
|
||||
|
|
|
|||
|
|
@ -347,14 +347,10 @@ object Scoped:
|
|||
protected def onTask[A2](f: Task[A1] => Task[A2]): Initialize[Task[A2]] =
|
||||
init.apply(f)
|
||||
|
||||
def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] =
|
||||
onTask(_.result flatMap (f compose successM))
|
||||
def map[A2](f: A1 => A2): Initialize[Task[A2]] =
|
||||
onTask(_.result map (f compose successM))
|
||||
def andFinally(fin: => Unit): Initialize[Task[A1]] =
|
||||
onTask(_ andFinally fin)
|
||||
def doFinally(t: Task[Unit]): Initialize[Task[A1]] =
|
||||
onTask(_ doFinally t)
|
||||
def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] = onTask(_.flatMap(f))
|
||||
def map[A2](f: A1 => A2): Initialize[Task[A2]] = onTask(_.map(f))
|
||||
def andFinally(fin: => Unit): Initialize[Task[A1]] = onTask(_.andFinally(fin))
|
||||
def doFinally(t: Task[Unit]): Initialize[Task[A1]] = onTask(_.doFinally(t))
|
||||
def ||[T >: A1](alt: Task[T]): Initialize[Task[T]] = onTask(_ || alt)
|
||||
def &&[T](alt: Task[T]): Initialize[Task[T]] = onTask(_ && alt)
|
||||
def tag(tags: Tag*): Initialize[Task[A1]] = onTask(_.tag(tags: _*))
|
||||
|
|
@ -842,4 +838,4 @@ class TupleWrap[Tup <: Tuple](value: Tuple.Map[Tup, Taskable]):
|
|||
type InitTask[A2] = Initialize[Task[A2]]
|
||||
lazy val initTasks = value.transform[InitTask]([a] => (t: Taskable[a]) => t.toTask)
|
||||
def mapN[A1](f: Tup => A1): Def.Initialize[Task[A1]] =
|
||||
initTasks.mapN[A1](f)(using std.FullInstance.initializeTaskMonad)
|
||||
std.FullInstance.initializeTaskMonad.mapN(initTasks)(f)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ object InitializeInstance:
|
|||
|
||||
override def pure[A1](a: () => A1): Initialize[A1] = Def.pure(a)
|
||||
override def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] = in(f)
|
||||
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Initialize])(f: A1 => A2): Initialize[A2] =
|
||||
Def.app(t)(f)
|
||||
override def ap[A1, A2](ff: Initialize[A1 => A2])(fa: Initialize[A1]): Initialize[A2] =
|
||||
Def.ap[A1, A2](ff)(fa)
|
||||
override def flatMap[A1, A2](fa: Initialize[A1])(f: A1 => Initialize[A2]) =
|
||||
|
|
@ -63,6 +65,10 @@ object FullInstance:
|
|||
override def map[A1, A2](fa: Initialize[Task[A1]])(f: A1 => A2): Initialize[Task[A2]] =
|
||||
F1F2.map(fa)(f)
|
||||
|
||||
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, [a] =>> Initialize[Task[a]]])(
|
||||
f: A1 => A2
|
||||
): Initialize[Task[A2]] = F1F2.mapN(t)(f)
|
||||
|
||||
override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])(
|
||||
fa: Initialize[Task[A1]]
|
||||
): Initialize[Task[A2]] =
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ object Task:
|
|||
}
|
||||
|
||||
override def map[A1, A2](in: Task[A1])(f: A1 => A2): Task[A2] = in.map(f)
|
||||
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Task])(f: A1 => A2): Task[A2] = t.mapN(f)
|
||||
override def flatMap[A1, A2](in: F[A1])(f: A1 => F[A2]): F[A2] = in.flatMap(f)
|
||||
override def flatten[A1](in: Task[Task[A1]]): Task[A1] = in.flatMap(identity)
|
||||
end Task
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@
|
|||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal
|
||||
package util
|
||||
|
||||
import sbt.util.Applicative
|
||||
package sbt.internal.util
|
||||
|
||||
object TupleMapExtension:
|
||||
extension [Tup <: Tuple, F1[_]](tuple: Tuple.Map[Tup, F1])
|
||||
|
|
@ -54,14 +51,4 @@ object TupleMapExtension:
|
|||
case _ => scala.runtime.TupleXXL.fromIterator(tuple.iterator.map(f(_)))
|
||||
// format: on
|
||||
res.asInstanceOf[Tuple.Map[Tup, F2]]
|
||||
|
||||
def traverse[F2[_]](f: [a] => F1[a] => F2[a])(using app: Applicative[F2]): F2[Tup] =
|
||||
val fxs: F2[List[Any]] = tuple.iterator
|
||||
.foldRight[F2[List[Any]]](app.pure(() => Nil))((x, xs) =>
|
||||
app.map(app.product(f(x), xs))((h, t) => h :: t)
|
||||
)
|
||||
app.map(fxs)(xs => Tuple.fromArray(xs.toArray).asInstanceOf[Tup])
|
||||
|
||||
def mapN[A1](f: Tup => A1)(using app: Applicative[F1]): F1[A1] =
|
||||
app.map(tuple.traverse[F1]([a] => (f: F1[a]) => f))(f)
|
||||
end TupleMapExtension
|
||||
|
|
|
|||
|
|
@ -10,6 +10,18 @@ package sbt.util
|
|||
trait Applicative[F[_]] extends Apply[F]:
|
||||
def pure[A1](x: () => A1): F[A1]
|
||||
|
||||
def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, F])(f: A1 => A2): F[A2] =
|
||||
import sbt.internal.util.TupleMapExtension.*
|
||||
val g = (l: List[Any]) => f(Tuple.fromArray(l.toArray).asInstanceOf[A1])
|
||||
map(
|
||||
t.iterator.foldLeft(pure(() => g))((g, head) =>
|
||||
ap(map(head)(h => (f: List[Any] => A2) => (tail: List[Any]) => f(h :: tail)))(g)
|
||||
)
|
||||
)(_.apply(Nil))
|
||||
|
||||
def map2(t: (F[Int], F[String]))(f: (Int, String) => Boolean): F[Boolean] =
|
||||
ap(ap(pure(() => f.curried))(t._1))(t._2)
|
||||
|
||||
override def map[A1, A2](fa: F[A1])(f: A1 => A2): F[A2] =
|
||||
ap(pure(() => f))(fa)
|
||||
end Applicative
|
||||
|
|
@ -25,6 +37,8 @@ object Applicative:
|
|||
override def pure[A1](x: () => A1): F1[F2[A1]] = F1.pure(() => F2.pure(x))
|
||||
override def map[A1, A2](fa: F1[F2[A1]])(f: A1 => A2): F1[F2[A2]] =
|
||||
F1.map(fa)(f2 => F2.map(f2)(f))
|
||||
override def mapN[A1 <: Tuple, A2](t1: Tuple.Map[A1, F])(f: A1 => A2): F1[F2[A2]] =
|
||||
F1.mapN(t1.asInstanceOf[Tuple.Map[Tuple.Map[A1, F2], F1]])(t2 => F2.mapN(t2)(f))
|
||||
override def ap[A1, A2](f1f2f: F1[F2[A1 => A2]])(f1f2a: F1[F2[A1]]): F1[F2[A2]] =
|
||||
F1.ap(F1.map(f1f2f) { (f2f: F2[A1 => A2]) => (f2a: F2[A1]) => F2.ap(f2f)(f2a) })(f1f2a)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@ package sbt.util
|
|||
|
||||
trait Apply[F[_]] extends Functor[F]:
|
||||
def ap[A1, A2](ff: F[A1 => A2])(fa: F[A1]): F[A2]
|
||||
|
||||
def product[A1, A2](fa: F[A1], fb: F[A2]): F[(A1, A2)] =
|
||||
ap(map(fa)(a => (b: A2) => (a, b)))(fb)
|
||||
end Apply
|
||||
|
||||
object Apply:
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
package sbt.internal.util
|
||||
|
||||
import verify.BasicTestSuite
|
||||
|
||||
object TupleMapExtensionTest extends BasicTestSuite:
|
||||
val tuple: Tuple.Map[(Int, String), Option] = ((Option(1), Option("foo")))
|
||||
|
||||
test("tuple.mapN") {
|
||||
val f = (arg: (Int, String)) => arg._1.toString + "|" + arg._2
|
||||
val actual = TupleMapExtension.mapN[(Int, String), Option](tuple)(f)
|
||||
assert(actual == Option("1|foo"))
|
||||
}
|
||||
Loading…
Reference in New Issue