属性 在 REPL 中访问时扩展 App 的对象具有空值

Property of an object extending App has null value when accessed in REPL

我的问题是如何在 sbt 控制台(Scala REPL)中访问 DownloadFiles.fileURLList 属性?

我创建了一个 SBT Scala 项目并将此代码放在 src/main/scala/DownloadFiles.scala

    import sys.process._
    import biz.neumann.url.NiceURLCodecs._
    import java.net._
    import java.io._

    object DownloadFiles extends App {
        val fileURLList = Array(
            "https://www.example.com/file1.txt",
            "https://www.example.com/file2.txt",
            "https://www.example.com/file3.txt"
        )

        fileURLList.foreach(url => {
            val fileName = "downloaded-files/" + new File(new URI(url).getPath).getName;
            println(url.decode.encode + ": " + fileName)
            new URL(url.decode.encode) #> new File(fileName) !!
        })
    }

我使用 sbt console 打开 Scala REPL,当我访问 DownloadFiles 对象的 fileURLList 属性 时,我得到空值(未计算),如下所示。

scala> DownloadFiles.fileURLList

res0: Array[String] = null

我需要的是该对象的 属性 的评估值。

如果对您有帮助,build.sbt 是:

scalaVersion := "2.12.10"
name := "image-downloader"
organization := "in.bhargav.inc"
version := "1.0"

libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
libraryDependencies += "biz.neumann" % "nice-url-encode-decode_2.12" % "1.5"

代码的第一部分使用了一个名为 fileURLList 的变量。代码的第二部分和 SBT 命令使用 imageURLList。 imageURLList 从未声明为变量,因此它为空。查找并将您的代码从 fileURLList 替换为 imageURLList,我敢打赌它会达到您的预期。

我有点惊讶你没有收到其他错误。

这是 Hello 扩展 App 的结果,后者间接扩展了 ,从而改变了初始化语义:

@nowarn("""cat=deprecation&origin=scala\.DelayedInit""")
trait App extends DelayedInit

快速修复是让fileURLList变懒

➜ scala
Welcome to Scala 2.13.5 (OpenJDK 64-Bit Server VM, Java 1.8.0_282).
Type in expressions for evaluation. Or try :help.

scala> object DownloadFiles extends App {
     |   val fileURLList = Array("https://www.example.com/file1.txt")
     | }
object DownloadFiles

scala> DownloadFiles.fileURLList
val res1: Array[String] = null

scala> object DownloadFiles extends App {
     |   lazy val fileURLList = Array("https://www.example.com/file1.txt")
     | }
object DownloadFiles

scala> DownloadFiles.fileURLList
val res2: Array[String] = Array(https://www.example.com/file1.txt)

此行为在 Scala 3 中发生了变化,它删除了 DelayedInit 语义

➜ scala3-repl 
scala> object DownloadFiles extends App {
     |   val fileURLList = Array("https://www.example.com/file1.txt")
     | }
// defined object DownloadFiles

scala> DownloadFiles.fileURLList                                                                                                            
val res0: Array[String] = Array(https://www.example.com/file1.txt)

The previous functionality of App, which relied on the "magic" DelayedInit trait, is no longer available. App still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build between Scala 2 and Scala 3, it is recommended to use an explicit main method with an Array[String] argument instead.