gpt4 book ai didi

scala - 作为单例集合的选项 - 现实生活中的用例

转载 作者:行者123 更新时间:2023-12-01 09:47:18 25 4
gpt4 key购买 nike

标题几乎概括了它。 Option 作为单例集合有时会令人困惑,但有时它允许一个有趣的应用程序。我有一个例子,我想了解更多这样的例子。

我唯一的例子是在 Option[List[T]] 上运行 for comprehension。我们可以做到以下几点:

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 属性的用法——这些非常明显。换句话说,mapflatMap 函数超出了这个问题的范围。它们绝对非常有用,只是来自其他地方。

最佳答案

我发现使用 Option[T] 作为集合的主要好处是您可以使用定义在集合上的操作,例如 map flatmap, filter, foreach 等。这使得对给定选项进行操作更容易,而不是使用模式匹配或检查 Option[T ].isDefined 查看值是否存在。

例如,让我们以来自Daniel Westheide blog post about Option[T] 的用户存储库为例:

假设您有一个 UserRepository 对象,它根据 ID 返回用户。用户可能存在也可能不存在,因此它返回一个 Option[Person]。现在假设我们想通过 id 搜索一个人,然后过滤他们的年龄。我们可以做到:

val age: Some[Int] = UserRepository.findById(1).map(_.age)

现在假设一个 Person 也有一个类型为 Option[String]gender 属性。如果你想把它提取出来,你可以使用 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 类型定义了嵌套的 Option[T] 字段,并且拥有类似集合的方法真的很方便,可以帮助您去除样板和噪音以提取实际值退出运营。

前几天我遇到的一个更真实的用例是使用 awscala SDK,我想从 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]])

所以这里发生的是您查询 S3 服务以获取存储桶,该存储桶可能存在也可能不存在。然后,您想从中提取一个实际包含数据的 S3Object,但 API 本身返回一个 Option[S3Object],因此使用 很方便flatMap 以获取 Option[S3Object] 而不是 Option[Option[S3Object]]。最后,我想反序列化实际上包含 JSON 的 S3Object,并使用 Argonaut 库返回一个 Option[MyObject],然后再次使用 flatMap 以挽救提取内部选项类型。

编辑:

正如您所指出的,mapflatMap 属于 Option[T] 的 monadic 属性。我写了一个 blog post描述两个选项的减少,最终解决方案是:

def reduce[T](a: Option[T], b: Option[T], f: (T, T) => T): Option[T] = {
(a ++ b).reduceLeftOption(f)
}

它利用了 ++Option[T] 上专门定义的任何集合上定义的运算符,都是一个集合。

关于scala - 作为单例集合的选项 - 现实生活中的用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36933813/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com