我正在尝试增强以下代码:
我使用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
,编译器只是不喜欢,我想知道应该更换什么。
我希望这个例子对我来说是Option
和Some
的学习课程。
好的,这就是我窒息的地方。我想检查directoryStream
是否为空并且是否已定义,如果是这种情况,我想调用getMeDirStream.get
来调用iterator()
方法。
Option
的API告诉我,如果选项为空,则调用get()
方法可能会产生java.util.NoSuchElementException
。
如果directoryStream为空,我想返回一些而不是None,因为IntelliJ告诉我"类型None.type
的表达式不符合预期类型DirectoryStream[Path]
& #34;
现在,我对这一切都很天真。
我想知道以下内容:
除else
以外的None
我应该返回什么内容?
我是否应该使用getMeDirStream.get
将java.util.NoSuchElementException
打包在try-catch中,即使我正在检查directoryStream
是否为空。?
getMeDirStream.get
中的try-catch的目的是什么,如果有这种需要的话?
如何清理上面的代码以包含对isDefined
的正确检查以及捕获适当的例外情况?
一旦我知道在else中返回什么(并且在必要时放入适当的try-catch块之后),我想在iterator()
上调用getMeDirStream
方法来执行一些下游操作
答案 0 :(得分:2)
Some
和None
是Option
的子类型,但为了更加正确,它们实际上是Option
或数据构造函数的两种不同情况。换句话说,即使Scala允许您直接调用Some
或None
,您仍应将其类型视为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 => /* ... */
}
或者您使用map
,flatMap
和foreach
等方法(或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
返回。 Try
与Option
类似。它不是Some
和None
,而是Success
和Failure
个子类型,失败案例包含Throwable
,而None
只是一个单身,没有其他信息。