错误消息
`value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
val x = version.value
^
明确指出如何解决问题,例如,使用:=
val x = settingKey[String]("")
x := version.value
sbt uses macros heavily状态下的说明
value
方法本身实际上是一个宏,如果您调用它,该宏在另一个宏的上下文之外,将导致编译时间错误,确切的错误消息是...您会看到为什么,因为sbt设置完全是声明性的,所以您无法通过键访问任务的值,这没有任何意义为此。
但是我很困惑,原因是sbt的declarative性质意味着什么。例如,从直觉上来说,我认为以下的Scala原始片段在语义上与sbt相似
def version: String = ???
lazy val x = s"Hello $version" // ok
trait Foo {
def version: String
val x = version // ok
}
由于这是合法的,显然,Scala代码段在语义上不等同于sbt代码段。我想知道是否有人可以详细说明为什么value
无法在宏外部使用?原因纯粹是语法与宏语法有关,还是我缺少有关sbt性质的基本知识?
另外一句话说
定义sbt的任务引擎是通过为sbt提供一系列设置来完成的,每个设置都声明一个任务实现。 sbt然后按顺序执行这些设置。可以通过多种设置多次声明任务,最后一项执行获胜。
所以在此刻线
val x = version.value
将被执行(如果允许的话!),整个程序仍在设置中,SBT不知道version
的最终定义。
程序在什么意义上仍在设置中?
SBT的操作顺序基本上是(可能遗漏了一些东西:]:
[version.value
仅在步骤4之后可用,但是val x = version.value
在步骤1上运行。
懒惰的评估会解决吗?
嗯,当您写val x = ...
时,没有惰性评估。但是lazy val x = ...
也在步骤1上运行。