Scala:如何返回Some或Option

时间:2015-03-11 03:37:17

标签: scala option

我正在尝试增强以下代码: 我使用java.nio.file包将目录或文件表示为Path。 所以这里:

import java.nio.file.{Paths,DirectoryStream,Files,
                      Path,DirectoryIteratorException}

val path: Path = Paths.get(directoryPath) 
var directoryStream: Option[DirectoryStream[Path]] = None

// so far so good

try {
    directoryStream = Some(Files.newDirectoryStream(pathO))

    // this is where i get into trouble
    def getMeDirStream: DirectoryStream[Path] =
        if (!directoryStream.isEmpty && directoryStream.isDefined)
            getMeDirStream.get
        else
            None

    // invoke the iterator() method of dstream here
}

上面的代码将无法编译,因为我不知道在else中返回什么,现在,对于我的生活,我只能提出None,编译器只是不喜欢,我想知道应该更换什么。 我希望这个例子对我来说是OptionSome的学习课程。


好的,这就是我窒息的地方。我想检查directoryStream是否为空并且是否已定义,如果是这种情况,我想调用getMeDirStream.get来调用iterator()方法。 Option的API告诉我,如果选项为空,则调用get()方法可能会产生java.util.NoSuchElementException

如果directoryStream为空,我想返回一些而不是None,因为IntelliJ告诉我"类型None.type的表达式不符合预期类型DirectoryStream[Path]& #34;

现在,我对这一切都很天真。

我想知道以下内容:

  1. else以外的None我应该返回什么内容?

  2. 我是否应该使用getMeDirStream.getjava.util.NoSuchElementException打包在try-catch中,即使我正在检查directoryStream是否为空。?

  3. getMeDirStream.get中的try-catch的目的是什么,如果有这种需要的话?

  4. 如何清理上面的代码以包含对isDefined的正确检查以及捕获适当的例外情况?

  5. 一旦我知道在else中返回什么(并且在必要时放入适当的try-catch块之后),我想在iterator()上调用getMeDirStream方法来执行一些下游操作

2 个答案:

答案 0 :(得分:2)

SomeNoneOption的子类型,但为了更加正确,它们实际上是Option或数据构造函数的两种不同情况。换句话说,即使Scala允许您直接调用SomeNone,您仍应将其类型视为Option。更重要的是,你不应该在任何情况下调用Option#get因为它不安全。

Option的意图是表明某个值不存在的可能性。如果您关心错误,那么您应该考虑使用Either代替(或Scalaz' Either调用\/)。

您可以将计算保持在Option上下文中,然后仅在稍后提取值,或提供默认值。

def fromTryCatch[A](a: => A): Either[Throwable, A] = try { Right(a) } catch { case e: Throwable => Left(e) }

val getMeDirStream: Option[java.util.Iterator[Path]] =
  for {
    path <- fromTryCatch(Paths.get(directoryPath)).toOption
    directoryStream <- fromTryCatch(Files.newDirectoryStream(pathO)).toOption
  } yield directoryStream.iterator()

稍后或之后,您可以获取迭代器,或提供默认值:

val iterator = getMeDirStream.getOrElse(java.util.Collections.emptyIterator[Path])

答案 1 :(得分:1)

您的具体问题难以解决,因为目前还不清楚您要实现的目标。特别是,当你问try块的目的是什么时......好吧,你写了它,所以只有你能回答它。

一般情况下,您从不get上致电Option。您可以使用模式匹配:

option match {
    case Some(value) => /* ... */
    case None =>        /* ... */
}

或者您使用mapflatMapforeach等方法(或gpampara代码使用的等效理解语法)。


我对gpampara答案的修订:

import scala.collection.convert.wrapAll._
import scala.util.Try
import java.nio.file.{Paths, Files, Path}

val getMeDirStream: Option[Iterator[Path]] =
  for {
    path <- Try(Paths.get("")).toOption
    directoryStream <- Try(Files.newDirectoryStream(path)).toOption
  } yield directoryStream.iterator

的变化:

  • 使用Try(...).toOption代替Either
  • 使用scala.collection.convert中的含义将结果作为Scala Iterator返回。

TryOption类似。它不是SomeNone,而是SuccessFailure个子类型,失败案例包含Throwable,而None只是一个单身,没有其他信息。

相关问题