If statement SBT TaskKey If语句

If statement SBT TaskKey If语句,if-statement,sbt,If Statement,Sbt,我用的是SBT 0.13。我遇到了一个问题,如下玩具示例所示: lazy val nativeOne = TaskKey[Unit]( "nativeOne", "One" ) lazy val nativeTwo = TaskKey[Unit]( "nativeTwo", "Two" ) lazy val testProj = Project( id = "testProj", base = file( "." ), settings = Defaults.defau

我用的是SBT 0.13。我遇到了一个问题,如下玩具示例所示:

lazy val nativeOne = TaskKey[Unit]( "nativeOne", "One" )
lazy val nativeTwo = TaskKey[Unit]( "nativeTwo", "Two" )

lazy val testProj = Project(
    id = "testProj",
    base = file( "." ),
    settings = Defaults.defaultSettings ++ Seq(
        scalaVersion := "2.10.2",
        nativeOne :=
        {
            println( "Native one"
        },  
        nativeTwo :=
        {
            if ( true )
            {
                println( "Native two" )
            }
            else
            {
                val n1 = nativeOne.value
            }
        }
    )
)
如果我进入sbt并运行
nativeTwo

> nativeTwo
Native one
Native two
为什么会这样?为什么要评估
false
分支?不允许在TaskKey中进行分支吗?

在sbt中,所有依赖项都是在任务运行之前并行计算的。如果你要构建一个你所拥有的图表,它将是:

nativeOne
   ^
   |
nativeTwo
你要做的是安排任务。在sbt中,我们尝试促进返回其他任务直接使用的结果的任务,因此使用
.value
。这不是直接运行任务,而是说“给我其他任务的结果”

理解sbt语法的最好方法是模仿scala异步项目。您的代码类似于以下异步代码:

nativeOne = async {
  println( "Native one")
}
nativeTwo = async {
  if(true) println("Native Two")
  else await(nativeOne)
}
在这里,更明显的是,您只是说“如果尚未计算,请等待值”

如果您想选择性地执行任务,则需要在sbt的
任务[\u]
层执行,这一层更为详细。我们使用的是“动态任务”。它选择在运行时实际运行哪些任务

因此,您需要使用
Def.taskDyn
方法,该方法允许您按照定义的顺序组合任务。您将使用
TaskKey
s的
toTask
方法处理任务本身。这不是处理任务生成的值。下面是一个示例
build.sbt

val taskOne = taskKey[Int]("test")

val taskTwo = taskKey[Int]("test2")

val taskThree = taskKey[Int]("test3")

val switchEm = settingKey[Boolean]("switch 'em")

switchEm := true

taskOne := { println("taskOne"); 1 }

taskTwo := { println("taskTwo"); 2 }

taskThree := Def.taskDyn({
  if(switchEm.value) taskTwo.toTask
  else taskOne.toTask
}).value
然后在sbt控制台中:

> reload
[info] Loading project definition from /home/jsuereth/projects/sbt/test-projects/project
[info] Set current project to test-projects (in build file:/home/jsuereth/projects/sbt/test-projects/)
> taskThree
2
另外请注意,您不会在inspect命令中看到已更正的依赖项,因为这些依赖项是动态添加的:

>检查任务三
[信息]任务:Int
[信息]说明:
[信息]测试3
[信息]提供人:
[info]{file:/home/jsuereth/projects/sbt/test projects/}test projects/*:tasktree
[信息]定义于:
[info]/home/jsuereth/projects/sbt/testprojects/build.sbt:15
[信息]依赖项:
[信息]*:switchEm
[info]*:在sbt中设置数据在任务运行之前,所有依赖项都是并行计算的。如果要构建一个您拥有的图形,它将是:

nativeOne
   ^
   |
nativeTwo
您试图做的是对任务进行排序。在sbt中,我们尝试提升返回其他任务直接使用的结果的任务,从而得到
.value
。这样做的目的不是直接运行任务,而是说“给我其他任务的结果”

理解sbt语法的最佳方法是模仿scala异步项目。您的代码类似于以下异步代码:

nativeOne = async {
  println( "Native one")
}
nativeTwo = async {
  if(true) println("Native Two")
  else await(nativeOne)
}
在这里,更明显的是,您只是说“如果尚未计算,请等待值”

如果您希望选择性地执行任务,则需要在sbt的
Task[\u]
层执行,这一层更为详细。我们使用的是“动态任务”。它选择在运行时实际运行哪些任务

因此,您需要使用
Def.taskDyn
方法,该方法允许您按照定义的顺序组合任务。您将使用
TaskKey
s的
toTask
方法处理任务本身。这不是在处理任务产生的值。下面是一个示例
build.sbt

val taskOne = taskKey[Int]("test")

val taskTwo = taskKey[Int]("test2")

val taskThree = taskKey[Int]("test3")

val switchEm = settingKey[Boolean]("switch 'em")

switchEm := true

taskOne := { println("taskOne"); 1 }

taskTwo := { println("taskTwo"); 2 }

taskThree := Def.taskDyn({
  if(switchEm.value) taskTwo.toTask
  else taskOne.toTask
}).value
然后在sbt控制台中:

> reload
[info] Loading project definition from /home/jsuereth/projects/sbt/test-projects/project
[info] Set current project to test-projects (in build file:/home/jsuereth/projects/sbt/test-projects/)
> taskThree
2
另外请注意,您不会在inspect命令中看到已更正的依赖项,因为这些依赖项是动态添加的:

>检查任务三
[信息]任务:Int
[信息]说明:
[信息]测试3
[信息]提供人:
[info]{file:/home/jsuereth/projects/sbt/test projects/}test projects/*:tasktree
[信息]定义于:
[info]/home/jsuereth/projects/sbt/testprojects/build.sbt:15
[信息]依赖项:
[信息]*:switchEm

[info]*:settingsData我想这是因为有一种宏魔法(在编译时)可以发现nativeOne.value的访问并添加任务依赖项。在一般情况下,宏无法知道计算if的哪个路径,因此它必须始终添加依赖项。那么解决方案是什么?您可以动态(在运行时)将节点添加到生成图中。有一个咒语使用Def.taskDyn。这里有一个与此相关的例子:我认为这是因为有一种宏魔法(在编译时)可以发现nativeOne.value的访问,并添加一个任务依赖项。在一般情况下,宏无法知道计算if的哪个路径,因此它必须始终添加依赖项。那么解决方案是什么?您可以动态(在运行时)将节点添加到生成图中。有一个咒语使用Def.taskDyn。这里有一个切向相关的示例: