Почему метод value нельзя использовать вне макросов? - PullRequest
1 голос
/ 26 апреля 2020

Сообщение об ошибке

`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 интенсивно используются макросы состояний

Сам метод value на самом деле является макросом, который, если вы вызываете его вне контекста другого макроса, приведет к ошибке времени компиляции, точному сообщению об ошибке быть ... И вы можете понять, почему, поскольку настройки sbt полностью декларативны, вы не можете получить доступ к значению задачи из ключа, это не имеет смысла.

однако меня смущает то, что подразумевается под декларативной природой sbt, являющейся причиной. Например, интуитивно я думаю, что следующий ванильный Scala фрагмент семантически похож на sbt

def version: String = ???
lazy val x = s"Hello $version"  // ok

trait Foo {
  def version: String
  val x = version               // ok
}

Поскольку это допустимо, ясно, что фрагмент Scala не является семантически эквивалентным sbt. Мне было интересно, если кто-то может уточнить, почему value нельзя использовать вне макросов? Является ли причина чисто syntacti c связанной с макросинтаксисом или я упускаю что-то фундаментальное в природе sbt?

1 Ответ

3 голосов
/ 26 апреля 2020

В другом предложении говорится:

Определение механизма задач sbt выполняется путем предоставления серии параметров sbt, каждый из которых объявляет реализацию задачи. Затем sbt выполняет эти настройки по порядку. Задачи могут быть объявлены несколько раз с помощью нескольких настроек, последняя из которых будет выполнена, выигрывает.

Таким образом, в тот момент, когда будет выполнена строка

val x = version.value

(если бы она была разрешена) !), вся эта программа все еще настраивается, и SBT не знает окончательного определения version.

В каком смысле программа «все еще настраивается»?

Порядок действий SBT, в основном (возможно, что-то отсутствует):

  1. Весь ваш код сборки Scala выполняется.
  2. Он содержит некоторые настройки и задачи Определения, SBT собирает их, когда встречает (наряду с таковыми из ядра, плагинов и т. д. c.)
  3. Они топологически сортируются в графе задач, дедуплицируются («последний выполнил выигрыш»), et c.
  4. Настройки оцениваются.
  5. Теперь вы можете запускать задачи (например, из консоли SBT).

version.value только доступно после шага 4, но val x = version.value выполняется на шаге 1.

Не будет ленивым оценка позаботится об этом?

Ну, когда пишешь val x = ... нет ленивых оценок. Но lazy val x = ... работает и на шаге 1.

...