scala代码块中最后一个表达式的语义是什么?

时间:2017-03-25 02:48:40

标签: scala

如果我没有注释评论行,则以下代码无法使用。它说

类型不匹配;找到:需要的单位:选项[String]

import java.io._
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.text.PDFTextStripper

object PdfToText {
  def main(args: Array[String]) {
    val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
    getTextFromPdf(filename) 
  }
  def getTextFromPdf(filename: String): Option[String] = {
    val pdf = PDDocument.load(new File(filename))
    println(new PDFTextStripper().getText(pdf))
    // Some(new PDFTextStripper().getText(pdf))
  }
}

如果我保留行 -

,代码执行正常
  

一些(新的PDFTextStripper()。getText(pdf))

输出:

Welcome 
to 
The World of Scala 

有人可以解释一下这行

的行为

"一些(新的PDFTextStripper()。getText(pdf)"

2 个答案:

答案 0 :(得分:2)

方法的结果是最后一行代码的结果。 println返回Unit。如果这是最后一行,那么该方法返回的内容与指定的Option[String]返回类型冲突。

代码new PDFTextStripper().getText(pdf)返回String并将其包装在Some()中,使其成为Option[String],与指定的方法返回类型匹配。

<强>解释

这是一个编译的方法。

def six(): Int = {  // takes no arguments and returns an Int
  println("top")    // string sent to stdout
  6                 // this is the Int it returns
}

这是一种编译的方法。

def six(): Int = {  // takes no arguments and returns an Int
  6                 // this is the Int it should return
  println("end")    // Error: type mismatch
}

此方法假设返回Int(这是: Int的意思)但最后一行是println()语句和{{1} }返回println,而不是Unit,这会导致错误。当假设返回Int时,此方法会尝试返回Unit

这是Scala语言中的一个非常基本的概念。

答案 1 :(得分:1)

Option是一种Scala类型,表示值的存在与否。而不是像null这样的运行时构造和具有明显缺点的异常,Option(以及其他语言中的等效构造)允许编译时检查您是否正在处理这两种可能性。

Option的常见用法是通过id进行数据库查找。很可能没有具有该id的实体。 Scala中函数的返回类型为Option[Employee]。如果找到一个,它将返回Some(employee);否则只是None。子类Option。请注意,您可以将Option视为零或一个元素的容器。

在您的情况下,您已定义函数以返回Option[String],这就是为什么返回包含文件文本的Some(String)会使编译器满意。我希望能回答你的问题。

请注意,虽然您的功能并未真正以有效使用Option的方式设计,因为不存在存在/不存在的问题 - 只是始终存在。换句话说,返回Option在这里并不有用。但是,使用Option来表示文件在要读取的文件系统上可用或不可用的情况是完全合适的。

例如:

object PdfToText {
  def main(args: Array[String]) {
    val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
    val text = getTextFromPdf(filename)
    val result = text.map(t => s"File contents: ${t}").getOrElse("Empty file")
    println(result)
  }

  def getTextFromPdf(filename: String): Option[String] = {
    val file = new File(filename)
    if (file.exists() && !file.isDirectory) {
      val pdf = PDDocument.load(new File(filename))
      Some(new PDFTextStripper().getText(pdf))
    } else {
      None
    }
  }
}

这里的存在是由可读文件的存在定义的,它允许我在Some中返回其内容,而缺席是由文件不存在或文件作为目录定义的,其表现为一个None

然后,我在main中考虑了两种可能性。如果要读取的文字是因为函数给了我一个Some,我调用map(仅在Some s上触发)将文本转换为另一个字符串。如果我得到None,我们会跳到getOrElse并生成默认字符串。

无论哪种方式,我们打印出我们得到的任何内容,无论原始String发生了什么,都保证为File

作为一个无耻的插件,您可以在我们的教程Nine Reasons to Try Scala中详细了解Option。快进到8:36。