标题几乎总结了它。 Option
作为单例集合有时会令人困惑,但有时它会允许有趣的应用程序。我有一个例子,我想了解更多这样的例子。
我唯一的例子是在for
上运行Option[List[T]]
理解。我们可以做到以下几点:
val v = Some(List(1, 2, 3))
for {
list <- v.toList
elem <- list
} yield elem + 1
没有Option.toList
,就不可能保持同样的for
理解力,而且我会被迫写出这样的东西:
for {
list <- v
} yield for {
elem <- list
} yield elem + 1
第一个例子更清晰,Option
是一个集合的优点。当然,结果类型在这两个例子中会有所不同,但我们假设它无关紧要。
还有其他例子吗?我特别喜欢专注于类似集合的用法,而不是Option
的monadic属性的使用 - 这些非常明显。换句话说,map
和flatMap
函数超出了此问题的范围。他们肯定非常有用,只是来自其他地方。
答案 0 :(得分:2)
我发现使用Option[T]
作为集合的主要好处是您可以使用在集合上定义的操作,例如map
,flatmap
,{{ 1}},filter
等。这样可以更轻松地对给定选项执行操作,而不是使用模式匹配或检查foreach
以查看值是否存在。
例如,让我们从Daniel Westheide blog post about Option[T]
获取用户存储库示例:
假设您有一个Option[T].isDefined
对象,该对象根据用户ID返回用户。用户可能存在也可能不存在,因此它返回UserRepository
。现在让我们说我们想通过id搜索一个人,然后过滤他们的年龄。我们可以这样做:
Option[Person]
现在让我们说val age: Some[Int] = UserRepository.findById(1).map(_.age)
还有Person
类型gender
的属性。如果您想将其解压缩,可以使用Option[String]
:
map
但使用嵌套选项并不方便。为此,您有val gender: Option[Option[String]] = UserRepository.findById(1).map(_.gender)
:
flatMap
如果我们想要打印性别(如果存在),我们可以使用val gender: Option[String] = UserRepository.findById(1).flatMap(_.gender)
:
foreach
您将发现自己使用已定义嵌套gender.foreach(println)
字段的scala类型,并且使用类似方法的集合非常方便,可帮助您删除样板和噪声以提取实际值退出了手术。
我前几天遇到的一个更真实的用例是使用awscala SDK,我想从S3存储中检索一个对象:
Option[T]
所以这里发生的是你在S3服务中查询一个桶,它可能存在也可能不存在。然后,您想要从中提取实际包含数据的val bucket: Option[Bucket] = s3.bucket(amazonConfig.bucketName)
val result: Option[S3Object] = bucket.flatMap(_.get(amazonConfig.offsetKey))
result.flatMap(s3Object =>
Source.fromInputStream(s3Object.content).mkString.decodeOption[Array[KafkaOffset]])
,但API本身会返回S3Object
,因此使用Option[S3Object]
展开会很方便得到flatMap
而不是Option[S3Object]
。最后,我想反序列化实际包含JSON的Option[Option[S3Object]]
,并使用Argonaut库返回S3Object
,然后再使用Option[MyObject]
来解除内部选项的提取类型。
正如您所指出的,flatMap
和map
属于flatMap
的monadic属性。我写了一篇blog post来描述减少最终解决方案的两个选项:
Option[T]
利用在def reduce[T](a: Option[T], b: Option[T], f: (T, T) => T): Option[T] = {
(a ++ b).reduceLeftOption(f)
}
上明确定义的任何集合上定义的++
运算符,作为集合。
答案 1 :(得分:0)
我建议您查看“新生儿斯卡拉指南”的the corresponding chapter。 根据我的经验,Option-as-collection的大多数有用用例是过滤选项并使flatMap隐式过滤无值。