scala - 可以更简洁地使用 Scala 的 Option flatMap 方法吗?

标签 scala option-type flatmap

诚然,我是 Scala 的新手,而且我在许多 Scala 示例中看到的语法糖上遇到了麻烦。 它通常会产生非常简洁的陈述,但老实说到目前为止(对我而言)有点不可读。

因此,我希望以 Option 类的典型用法(安全解除引用)作为理解的良好开端,例如,在我见过的特定示例中使用下划线。

我找到了一篇非常好的文章,其中展示了使用 Option 来避免 null 情况的示例。

https://medium.com/@sinisalouc/demystifying-the-monad-in-scala-cc716bb6f534#.fhrljf7nl

他这样描述一个用途:

trait User {
  val child: Option[User]
}

By the way, you can also write those functions as in-place lambda functions instead of defining them a priori. Then the code becomes this:

val result = UserService.loadUser("mike")
  .flatMap(user => user.child)
  .flatMap(user => user.child)

看起来不错!也许不像 groovy 中那样简洁,但也不错。

所以我想我会尝试将它应用到我正在尝试解决的案例中。

我有一个 Person 类型,其中 Person 的存在是可选的,但如果我们有一个人,他的属性是有保证的。因此,Person 类型本身没有使用 Option 类型。

Person 有一个类型为 Id 的 PID。 Id 类型由两个String 类型组成; Id 类型和 Id 值。

我使用 Scala 控制台测试了以下内容:

class Id(val idCode : String, val idVal : String)

class Person(val pid : Id, val name : String)

val anId: Id = new Id("Passport_number", "12345")

val person: Person = new Person(anId, "Sean")

val operson : Option[Person] = Some(person)

好的。这设置了我的人,它是可选的实例。

我从上面链接的文章中了解到,我可以使用 flatMap 获取 Persons Id-Val;像这样:

val result = operson.flatMap(person => Some(person.pid)).flatMap(pid => Some(pid.idVal)).getOrElse("NoValue")

太棒了!这样可行。如果我实际上没有人,我的结果是“NoValue”。

我使用 flatMap(而不是 Map)是因为,除非我误解(并且我对 Map 的测试不正确)如果我使用 Map,我必须提供替代或默认的 Person 实例。这是我不想做的。

好的,所以,flatMap 是要走的路。

然而,这确实不是一个非常简洁的说法。 如果我用更时髦的风格来写,我想我可以做这样的事情:

val result = person?.pid.idVal

哇,这有点漂亮!

Scala 肯定有办法提供至少与 Groovy 一样好的东西吗?

在上面的链接示例中,他能够使用我之前提到的一些语法糖使他的陈述更加简洁。下划线:

or even more concise:

val result = UserService.loadUser("mike")
  .flatMap(_.child)
  .flatMap(_.child)

因此,在这种情况下,下划线字符似乎允许您跳过指定类型(因为类型是推断的)并将其替换为下划线。

但是,当我用我的例子尝试同样的事情时:

val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")

Scala 提示。

<console>:15: error: missing parameter type for expanded function ((x$2) => x$2.idVal)
       val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")

有人可以帮我吗?

我怎么会误解这个? 有没有一种速记法可以写出我上面冗长的陈述? flatMap 是实现我所追求目标的最佳方式吗?还是有更好的更简洁和/或可读的方式来做到这一点?

提前致谢!

最佳答案

为什么坚持使用flatMap?我只是用 map 作为你的例子:

val result = operson.map(_.pid).map(_.idVal).getOrElse("NoValue")

或更短:

val result = operson.map(_.pid.idVal).getOrElse("NoValue")

您应该只将 flatMap 与返回 Option 的函数一起使用。您的 pididVal 不是 Option,因此只需映射它们即可。

你说

I have a type Person where the existence of a Person is optional, but if we have a person, his attributes are guaranteed. For that reason, there are no use of the Option type within the Person type itself.

这是您的示例与 User 示例之间的本质区别。在 User 示例中,User 实例的存在及其 child 字段都是选项。这就是为什么要获得 child,您需要 flatMap。但是,由于在您的示例中,不能保证仅存在 Person,因此在检索到 Option[Person] 后,您可以安全地映射到它的任何一个字段。

flatMap 视为 map,后跟 flatten(因此得名)。如果我映射到 child 身上:

val ouser = Some(new User())
val child: Option[Option[User]] = ouser.map(_.child)

我最终会得到一个 Option[Option[User]]。我需要将其展平到单个 Option 级别,这就是我首先使用 flatMap 的原因。

关于scala - 可以更简洁地使用 Scala 的 Option flatMap 方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35266651/

相关文章:

scala - 电梯/Scala 上的 MVC

scala - 我对 Scala Sets 的理解有什么问题?

java - 带有可选<String>的构造函数

ios - 输入字符串或字符时应用程序崩溃

ios - flatMap 是 Swift 中字典的字典

Scala Play 2.1 : Accessing request and response bodies in a filter

swift - 在 Swift 的 case 语句中赋值的 2 种方式

arrays - flatMap 中的 "Cannot convert return expression"里面有一个无意义的表达式

arrays - 理解 compactMap 和 flatMap 的问题

scala - scala中的命名函数是什么?