为什么不能在宏之外使用值方法? [英] Why value method cannot be used outside macros?

查看:37
本文介绍了为什么不能在宏之外使用值方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

错误信息

`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

中的解释sbt 大量使用宏 状态

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):

  1. 您的所有 Scala 构建代码都已运行.
  2. 它包含一些设置和任务定义,SBT 在遇到时收集这些(以及来自核心、插件等的)
  3. 它们按拓扑排序到任务图中,进行重复数据删除(最后一个执行获胜")等.
  4. 评估设置.
  5. 现在您可以实际运行任务(例如从 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆