【问题标题】:Property of an object extending App has null value when accessed in REPL在 REPL 中访问时扩展 App 的对象的属性具有空值
【发布时间】:2021-04-02 12:23:02
【问题描述】:

我的问题是如何在 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> 下载文件.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"

【问题讨论】:

  • 这是Hello 扩展App 的结果,它间接扩展了DalayedInit,从而改变了初始化语义。尝试将fileURLList 声明为lazy,或在调用fileURLList 之前调用DownloadedFiles.main(Array.emtpy)。查看相关stackoverflow.com/questions/66896016/…
  • @MarioGalic 谢谢!就是这样。您可以将此作为答案发布吗?

标签: scala sbt


【解决方案1】:

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

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

App之前的功能,靠的是“魔力” DelayedInit 特征,不再可用。应用程序仍然存在于有限 形式现在,但它不支持命令行参数,将 将来弃用。如果程序需要在之间交叉构建 Scala 2 和 Scala 3,建议使用显式的 main 方法 使用 Array[String] 参数代替。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢指出错误。发生这种情况是因为我正在修改 SO 的代码。我现在修好了,但问题是一样的。因此,正如问题下的评论所指出的那样,问题是实际原因,我可以确认,因为我检查了 Scala Reddit 组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多