- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
标题几乎概括了它。 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 属性的用法——这些非常明显。换句话说,map
和 flatMap
函数超出了这个问题的范围。它们绝对非常有用,只是来自其他地方。
最佳答案
我发现使用 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
以挽救提取内部选项类型。
正如您所指出的,map
和 flatMap
属于 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/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!