为什么不能在宏外部使用值方法?

问题描述 投票:1回答:1

错误消息

`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性质的基本知识?

scala sbt scala-macros
1个回答
3
投票

另外一句话说

定义sbt的任务引擎是通过为sbt提供一系列设置来完成的,每个设置都声明一个任务实现。 sbt然后按顺序执行这些设置。可以通过多种设置多次声明任务,最后一项执行获胜。

所以在此刻线

val x = version.value

将被执行(如果允许的话!),整个程序仍在设置中,SBT不知道version的最终定义。

程序在什么意义上仍在设置中?

SBT的操作顺序基本上是(可能遗漏了一些东西:]:

  1. 您所有的Scala构建代码都已运行。
  2. 它包含一些设置和任务定义,SBT会在遇到它们时(与来自内核,插件等的一起)收集那些设置和任务定义。>>
  3. 按照拓扑将它们分类到任务图中,进行重复数据删除(“执行获胜的最后一个”,等等)
  4. 评估设置。
  5. 现在您可以实际运行任务(例如,从SBT控制台运行。)>
  6. [version.value仅在步骤4之后可用,但是val x = version.value在步骤1上运行。

    懒惰的评估会解决吗?

嗯,当您写val x = ...时,没有惰性评估。但是lazy val x = ...也在步骤1上运行。

© www.soinside.com 2019 - 2024. All rights reserved.