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

2024-06-23

标题几乎概括了这一点。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的单子属性 - 这些非常明显。换句话说,map and flatMap函数超出了这个问题的范围。它们绝对非常有用,只是来自其他地方。


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

例如,让我们以用户存储库为例丹尼尔·韦斯特海德 (Daniel Westheide) 博客文章介绍Option[T] http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html:

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

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 类型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]]。最后,我想反序列化S3Object它实际上包含一个 JSON,并使用 Argonaut 库,它返回一个Option[MyObject],然后再次使用flatMap来拯救提取内部选项类型。

Edit:

正如你所指出的,map and flatMap属于一元属性Option[T]。我写了一个博客文章 http://asyncified.io/2016/04/16/reducing-two-options-in-scala/描述了两个选项的减少,最终解决方案是:

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

这利用了++ http://www.scala-lang.org/api/current/index.html#scala.Option@++%5BB%5D(that:scala.collection.GenTraversableOnce%5BB%5D):Option%5BB%5D定义在任何集合上的运算符,该集合也专门定义​​在Option[T],作为一个集合。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

作为单例集合的选项 - 现实生活中的用例 的相关文章

随机推荐

  • NSCollectionView 拖放:大多数委托事件未被调用

    我有一个 NSCollectionView 绑定到一个 NSArrayController 我想让拖放工作 所以我创建一个委托并实现方法 BOOL collectionView NSCollectionView collectionView
  • 允许 DialogFragment 的外部触摸

    我有一个Fragment在我的应用程序中显示DialogFragment 我在片段中有一个关闭对话框的按钮 但是 当我显示dialogFragment时 对话框外部的触摸不起作用 并且我无法单击对话框片段外部的按钮 如何允许 DialogF
  • 如何使用符合“Hashable”协议的 ForEach

    您好 我有一个关于确认协议 Hashable 的问题 实在是太烂了 这是我的模型 struct Page Decodable Identifiable var id String var name String var thumbnail
  • Ember-data和MongoDB,如何处理_id

    我正在将 ember data 与 Rails 和 MongoDB 一起使用 并且在 MongoDB 中的 id 字段中存储 ID 的方式遇到问题 Ember data 将使用 id 作为 ID 的默认字段 所以我尝试像这样覆盖它 App
  • 为什么 J2ME 不能创建递归目录?

    我想创建recursive目录 例如 Connector open file Phone folder 1 folder 2 Connector READ WRITE 问题是两个folders 这里的folder 1和folder 2没有明
  • 在库中实现 Javascript 链接的最佳方法

    我正在创建一个 JavaScript 库 我一直在尝试实现链接 0 我首先想到的是 function V p return add function addend return V p addend sub function subtra
  • 将 Protobuf 消息持久保存到数据库

    保存使用 protobuf3 定义的数据的正确方法是什么 我使用 golang 和 Java 两者都支持 ORM 在 java 中使用 Hibernate 在 golang 中使用 gorm 这两个地方我都需要将生成的代码转换为相应的实体模
  • 合并 JSON 对象而不使用新键

    如何合并两个 JSON 对象但不包含第一个对象中不存在的属性 Input var obj1 x y a b var obj2 x 1 y a 1 b 2 c 3 z Output obj1 x 1 y a 1 b 2 附 对象有一个方法叫做
  • python2.6 中应该使用 OrderedDict 的哪个实现?

    正如你们中的一些人可能知道的那样 在 python2 7 3 2 中我们将得到 OrderedDictPEP372 http www python org dev peps pep 0372 然而 PEP 存在的原因之一是因为每个人都做了自
  • Pascal - 在定义之前使用过程

    我有一段代码 非常简化 如下所示 program helloworld a integer procedure alpha begin writeln This is procedure alpha beta end procedure b
  • Laravel 作业/通知失败

    我正在尝试在我的网站上设置一个联系表单 当有人单击 发送 时 就会运行一个作业 并在该作业中向所有管理员用户发送通知 不过 我在失败的作业表中不断收到此错误 Illuminate Database Eloquent ModelNotFoun
  • Qt,颜色选择器对话框?

    Qt 是否有如下所示的颜色选择器对话框 它还需要有一个 OnColorChanged 信号 当选定的颜色发生变化时会调用该信号 我想在他们改变颜色时提供实时预览 这就是原因 使用谷歌我只能找到这个 它是一个圆边上的三角形 我个人认为它看起来
  • Laravel csrf 令牌与 ajax POST 请求不匹配

    我正在尝试通过ajax从数据库中删除数据 HTML foreach a as lis some code a href class delteadd Delete a click action perform on this link en
  • 如何避免 numpy.random.choice 中的舍入错误?

    假设 x 1 x 2 x n 是 n 个对象 并且想要选择其中一个 以便选择 x i 的概率与某个数字 u i 成正比 Numpy 为此提供了一个函数 x u np array x 1 x 2 x n np array u 1 u n np
  • 在同一站点上使用基本身份验证和表单身份验证

    谁能告诉我 是否可以在我的网站上同时使用基本身份验证和表单身份验证 而两者不会相互干扰 我有一个新网站 出于批准目的 我只希望某些人看到该网站 该网站有一个使用表单身份验证的会员区域 现在当任何人在通过基本身份验证后进入该网站时 他们都会被
  • 如何使用 Java 将系统剪贴板内容粘贴到任意窗口

    我想编写一个带有按钮的Java程序 当按下该按钮时 它会将系统剪贴板的内容粘贴 拖放到当前在任意 可能是非 Java 应用程序 例如 MS Word 中具有焦点的文本字段 本质上 按钮操作必须以某种方式模拟 CTRL V 粘贴 操作的发送
  • Windows 上的 CMake 链接共享库

    共有三个文件 m c m h和 main c File m h m h int m File m c m c include
  • 我可以阻止 Uri 在 WebRequest.Create 中取消对 url 的编码吗?

    代码本身并不复杂 只是无法正常工作 Uri uri new Uri https www google com webmasters tools feeds sites http 3A 2F 2Fwww mydomain co uk 2F W
  • PetaPoco 和存储过程的输出参数?

    我正在尝试使用 PetaPoco 设置输出参数 我发现有人在网上使用这个示例 var ctx new CustomDBDatabase var total new SqlParameter Total System Data SqlDbTy
  • 作为单例集合的选项 - 现实生活中的用例

    标题几乎概括了这一点 Option作为单例集合有时会令人困惑 但有时它允许一个有趣的应用程序 我脑子里有一个例子 并且想了解更多这样的例子 我唯一的例子是运行for对的理解Option List T 我们可以执行以下操作 val v Som