Scala:如何 return 一些或选项
Scala: How to return a Some or 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
}
上面的代码无法编译,因为我不知道 return 在 else 中要做什么,现在,为了我的生活,我只能想出 None
,编译器根本不喜欢它,我想了解应该用什么来替代它。
我希望这个例子对我来说是 Option
和 Some
的学习课程。
好吧,这是我窒息的地方。我想检查 directoryStream
是否不为空并且已定义,然后如果是这种情况,我想调用 getMeDirStream.get
来调用它的 iterator()
方法。
Option
的 API 告诉我,如果选项为空,调用 get()
方法可能会导致 java.util.NoSuchElementException
。
如果 directoryStream 是空的,我想 return 而不是 None,因为 IntelliJ 告诉我 "Expression of type None.type
doesn't conform to expected type DirectoryStream[Path]
".
现在,我对此很天真。
我想了解以下内容:
除了None
之外,else
我应该return什么?
即使我正在检查 directoryStream
是否为空,我是否应该将 getMeDirStream.get
包装在带有 java.util.NoSuchElementException
的 try-catch 中?
getMeDirStream.get
中的try-catch的目的是什么,如果确实有这样的需要?
我怎样才能清理上面的代码以合并正确的检查 isDefined
和捕获适当的异常?
一旦我知道要在 else 中 return 做什么(并在必要时放入适当的 try-catch 块之后),我想在 [=33= 上调用 iterator()
方法]做一些下游操作。
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])
您的具体问题很难解决,因为不清楚您要实现的目标。特别是,当你问 try
块的目的是什么时......好吧,你写了它,所以只有你能回答。
一般来说,您从不 在 Option
上调用 get
。您要么使用模式匹配:
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
中使用隐式来 return 作为 Scala Iterator
的结果。
Try
类似于 Option
。它有 Success
和 Failure
子类型,而不是 Some
和 None
,失败案例包括 Throwable
,而 None
只是一个没有附加信息的单例。
我正在尝试增强以下代码:
我正在使用 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
}
上面的代码无法编译,因为我不知道 return 在 else 中要做什么,现在,为了我的生活,我只能想出 None
,编译器根本不喜欢它,我想了解应该用什么来替代它。
我希望这个例子对我来说是 Option
和 Some
的学习课程。
好吧,这是我窒息的地方。我想检查 directoryStream
是否不为空并且已定义,然后如果是这种情况,我想调用 getMeDirStream.get
来调用它的 iterator()
方法。
Option
的 API 告诉我,如果选项为空,调用 get()
方法可能会导致 java.util.NoSuchElementException
。
如果 directoryStream 是空的,我想 return 而不是 None,因为 IntelliJ 告诉我 "Expression of type None.type
doesn't conform to expected type DirectoryStream[Path]
".
现在,我对此很天真。
我想了解以下内容:
除了
None
之外,else
我应该return什么?即使我正在检查
directoryStream
是否为空,我是否应该将getMeDirStream.get
包装在带有java.util.NoSuchElementException
的 try-catch 中?getMeDirStream.get
中的try-catch的目的是什么,如果确实有这样的需要?我怎样才能清理上面的代码以合并正确的检查
isDefined
和捕获适当的异常?
一旦我知道要在 else 中 return 做什么(并在必要时放入适当的 try-catch 块之后),我想在 [=33= 上调用 iterator()
方法]做一些下游操作。
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])
您的具体问题很难解决,因为不清楚您要实现的目标。特别是,当你问 try
块的目的是什么时......好吧,你写了它,所以只有你能回答。
一般来说,您从不 在 Option
上调用 get
。您要么使用模式匹配:
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
中使用隐式来 return 作为 ScalaIterator
的结果。
Try
类似于 Option
。它有 Success
和 Failure
子类型,而不是 Some
和 None
,失败案例包括 Throwable
,而 None
只是一个没有附加信息的单例。