scopt "not found: value", определяющий val с тем же именем

Для следующего использования scopt:

import java.io.File

object Application extends App {

  case class Config(in: File = new File("."), out: File = new File("."), scripts: Seq[File] = Seq())

  val parser = new scopt.OptionParser[Config]("scopt") {
    head("Script Runner", "0.1")
    opt[File]('i', "in") required () valueName ("<path>") action { (x, c) =>
      c.copy(in = x)
    } text ("required in path property")
    opt[File]('o', "out") required () valueName ("<path>") action { (x, c) =>
      c.copy(out = x)
    } text ("required out path file property")
    arg[File]("<file>...") unbounded () required() action { (x, c) =>
      c.copy(scripts = c.scripts :+ x)
    } text ("unbounded script paths")
  }

  val config = parser.parse(args, Config())

  val scripts = config.map { argConfig => argConfig.scripts }

  config match {
    case Some(config) => println(config)
    case _ => println("config undefined")
  }
}

Я получаю ошибку компиляции:

[error] /Users/jamesclark/code/scratch/src/main/scala/Application.scala:13: not found: value x
[error]       c.copy(out = x)

Если я переименую либо Config параметр scripts или Валь scripts тогда это компилируется.

Может ли кто-нибудь просветить меня о том, что здесь происходит? Это проблема компилятора, или мне не хватает какой-то магии?

scala 2.11.8 / sbt 0.13.7 / scopt 3.5.0

1 ответ

Решение

Делать вальс parser, config а также scripts в lazy valс вместо vals дает более полезное сообщение об ошибке: /src/main/scala/Application.scala:23: variable definition needs type because 'scripts' is used as a named argument in its body.

Предоставление сценариям своих аннотаций типов val scripts: Option[Seq[File]] = ... решает проблему.

Альтернативные способы обойти это переименовать либо val scripts или case class Config(... scripts: Seq[File] ...) появления scripts,

Корень проблемы, похоже, исходит из библиотеки scopt, так как определение parser в отдельную область устраняет необходимость в обходных путях переименования или аннотации типов.

object Application extends App {

  def newParser(): OptionParser[Config] = {
    new scopt.OptionParser[Config]("scopt") {
      head("Script Runner", "0.1")

      opt[File]('i', "in") required () valueName ("<path>") action { (x, c) =>
        c.copy(in = x)
      } text ("required in path property")

      opt[File]('o', "out") required () valueName ("<path>") action { (x, c) =>
        c.copy(out = x)
      } text ("required out path file property")

      arg[File]("<file>...") unbounded () required() action { (x, c) =>
        c.copy(scripts = c.scripts :+ x)
      } text ("unbounded script paths")
    }
  }

  case class Config(in: File = new File("."), out: File = new File("."), scripts: Seq[File] = Seq())

  val parser = newParser()

  val config = parser.parse(args, Config())

  val scripts = config.map { argConfig => argConfig.scripts }

  config match {
    case Some(config) =>
      println(config)
    case _ =>
      println("config undefined")
  }
}
Другие вопросы по тегам