在 SBT 0.13 中惯用地定义动态任务? [英] Idiomatically defining dynamic tasks in SBT 0.13?
问题描述
我正在将 SBT 插件从 0.12
移至 0.13
.在我的插件的不同点,我将一组动态任务安排到 SBT 构建图上.
I'm moving an SBT plugin from 0.12
over to 0.13
. At various points in my plugin I schedule a dynamic set of tasks onto the SBT build graph.
下面是我的旧代码.这仍然是表达这一点的惯用方式,还是可以利用宏使一切更漂亮?
Below is my old code. Is this still the idiomatic way to express this, or is it possible to leverage the macros to make everything prettier?
import sbt._
import Keys._
object Toplevel extends Build
{
lazy val ordinals = taskKey[Seq[String]]("A list of things")
lazy val times = taskKey[Int]("Number of times to list things")
lazy val inParallel = taskKey[Seq[String]]("Strings to log in parallel")
lazy val Foo = Project( id="Foo", base=file("foo"),
settings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
ordinals := Seq( "First", "Second", "Third", "Four", "Five" ),
times := 3,
inParallel <<= (times, ordinals, streams) flatMap
{ case (t, os, s) =>
os.map( o => toTask( () =>
{
(0 until t).map( _ => o ).mkString(",")
} ) ).join
}
)
)
}
为完全人为的例子道歉!
Apologies for the entirely contrived example!
编辑
因此,考虑到 Mark 的建议,我有以下更整洁的代码:
So, taking Mark's advice into account I have the following tidier code:
import sbt._
import Keys._
object Toplevel extends Build
{
lazy val ordinals = taskKey[Seq[String]]("A list of things")
lazy val times = taskKey[Int]("Number of times to list things")
lazy val inParallel = taskKey[Seq[String]]("Strings to log in parallel")
def parTask = Def.taskDyn
{
val t = times.value
ordinals.value.map(o => ordinalTask(o, t)).join
}
def ordinalTask(o: String, t: Int) = Def.task
{
(0 until t).map(_ => o).mkString(",")
}
lazy val Foo = Project( id="Foo", base=file("foo"),
settings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
ordinals := Seq( "First", "Second", "Third", "Four", "Five" ),
times := 3,
inParallel := parTask.value
)
)
}
这似乎快到了,但构建失败:
This seems to be nearly there, but fails the build with:
[error] /home/alex.wilson/tmp/sbt0.13/project/build.scala:13: type mismatch;
[error] found : sbt.Def.Initialize[Seq[sbt.Task[String]]]
[error] required: sbt.Def.Initialize[sbt.Task[?]]
[error] ordinals.value.map(o => ordinalTask(o, t)).join
推荐答案
您可以使用 Def.taskDyn
,它为 flatMap
提供了新的语法.与 Def.task
的区别在于预期的返回类型是任务 Initialize[Task[T]]
而不仅仅是 T
.翻译你的例子,
You can use Def.taskDyn
, which provides the new syntax for flatMap
. The difference from Def.task
is that the expected return type is a task Initialize[Task[T]]
instead of just T
. Translating your example,
inParallel := parTask.value
def parTask = Def.taskDyn {
val t = times.value
ordinals.value.map(o => ordinalTask(o, t)).joinWith(_.join)
}
def ordinalTask(o: String, t: Int) = Def.task {
(0 until t).map(_ => o).mkString(",")
}
这篇关于在 SBT 0.13 中惯用地定义动态任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!