为什么不能在宏之外使用值方法? [英] Why value method cannot be used outside macros?
问题描述
错误信息
`value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
val x = version.value
^
明确指出如何解决问题,例如使用:=
clearly indicates how to fix the problem, for example, using :=
val x = settingKey[String]("")
x := version.value
value
方法本身实际上是一个宏,如果你调用它在另一个宏的上下文之外,将导致编译时间错误,确切的错误消息是...你会明白为什么,因为 sbt 设置完全是声明性的,你无法从key中访问任务的值,没有意义这样做.
The
value
method itself is in fact a macro, one that if you invoke it outside of the context of another macro, will result in a compile time error, the exact error message being... And you can see why, since sbt settings are entirely declarative, you can’t access the value of a task from the key, it doesn’t make sense to do that.
然而,我很困惑 sbt 的声明性本质是什么意思.例如,直觉上我会认为以下 vanilla Scala 片段在语义上类似于 sbt 的
however I am confused what is meant by declarative nature of sbt being the reason. For example, intuitively I would think the following vanilla Scala snippet is semantically similar to sbt's
def version: String = ???
lazy val x = s"Hello $version" // ok
trait Foo {
def version: String
val x = version // ok
}
由于这是合法的,显然 Scala 片段在语义上不等同于 sbt 片段.我想知道是否有人可以详细说明为什么 value
不能在宏之外使用?原因纯粹是与宏语法相关的语法,还是我遗漏了一些关于 sbt 本质的基本知识?
As this is legal, clearly the Scala snippet is not semantically equivalent to the sbt one. I was wondering if someone could elaborate on why value
cannot be used outside macros? Is the reason purely syntactic related to macro syntax or am I missing something fundamental about sbt's nature?
推荐答案
另外一句话
定义 sbt 的任务引擎是通过给 sbt 一系列设置来完成的,每个设置声明一个任务实现.sbt 然后按顺序执行这些设置.任务可以通过多个设置多次声明,最后一个执行的获胜.
Defining sbt’s task engine is done by giving sbt a series of settings, each setting declaring a task implementation. sbt then executes those settings in order. Tasks can be declared multiple times by multiple settings, the last one to execute wins.
所以此刻行
val x = version.value
会被执行(如果允许的话!),整个程序仍在设置中,SBT不知道version
的最终定义.
would be executed (if it were allowed!), that whole program is still being set up and SBT doesn't know the final definition of version
.
在什么意义上该程序仍在设置中"?
In what sense is the program "still being set up"?
SBT 的操作顺序基本上是(可能遗漏了一些东西):
SBT's order of actions is, basically (maybe missing something):
- 您的所有 Scala 构建代码都已运行.
- 它包含一些设置和任务定义,SBT 在遇到时收集这些(以及来自核心、插件等的)
- 它们按拓扑排序到任务图中,进行重复数据删除(最后一个执行获胜")等.
- 评估设置.
- 现在您可以实际运行任务(例如从 SBT 控制台).
version.value
仅在第 4 步之后可用,但 val x = version.value
在第 1 步中运行.
version.value
is only available after step 4, but val x = version.value
runs on step 1.
懒惰评估会解决这个问题吗?
Would not lazy evaluation take care of that?
好吧,当您编写 val x = ...
时,没有惰性求值.但是 lazy val x = ...
也运行在第 1 步.
Well, when you write val x = ...
there is no lazy evaluation. But lazy val x = ...
runs on step 1 too.
这篇关于为什么不能在宏之外使用值方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!