可以更简洁地使用 Scala 的 Option flatMap 方法吗?
Possible to make use of Scala's Option flatMap method more concise?
无可否认,我对 Scala 还是很陌生,而且我在使用许多 Scala 示例中看到的语法糖时遇到了麻烦。
它通常会产生一个非常简洁的陈述,但老实说到目前为止(对我来说)有点不可读。
因此,我希望采用选项 class 的典型用法,安全取消引用,作为开始理解的好地方,例如,在我的特定示例中使用下划线见过。
我找到了一篇非常好的文章,其中展示了使用 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 是要走的路。
不过,这确实不是一个很简洁的说法。
如果我用 groovy 的风格来写,我想我可以做这样的事情:
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) => x.idVal)
val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")
有人可以帮助我吗?
我怎么会误解这个?
有没有一种速记法可以写出我上面冗长的陈述?
flatMap 是实现我所追求目标的最佳方式吗?或者有更好更简洁 and/or 可读的方法吗?
提前致谢!
为什么坚持使用flatMap?我只是用 map
作为你的例子:
val result = operson.map(_.pid).map(_.idVal).getOrElse("NoValue")
甚至更短:
val result = operson.map(_.pid.idVal).getOrElse("NoValue")
您应该只将 flatMap
与 return Option
的函数一起使用。您的 pid
和 idVal
不是 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
的原因。
如果您正在寻找最简洁的解决方案,请考虑以下内容:
val result = operson.fold("NoValue")(_.pid.idVal)
虽然可能会觉得不清楚或令人困惑
无可否认,我对 Scala 还是很陌生,而且我在使用许多 Scala 示例中看到的语法糖时遇到了麻烦。 它通常会产生一个非常简洁的陈述,但老实说到目前为止(对我来说)有点不可读。
因此,我希望采用选项 class 的典型用法,安全取消引用,作为开始理解的好地方,例如,在我的特定示例中使用下划线见过。
我找到了一篇非常好的文章,其中展示了使用 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 是要走的路。
不过,这确实不是一个很简洁的说法。 如果我用 groovy 的风格来写,我想我可以做这样的事情:
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) => x.idVal)
val result = operson.flatMap(Some(_.pid)).flatMap(Some(_.idVal)).getOrElse("NoValue")
有人可以帮助我吗?
我怎么会误解这个? 有没有一种速记法可以写出我上面冗长的陈述? flatMap 是实现我所追求目标的最佳方式吗?或者有更好更简洁 and/or 可读的方法吗?
提前致谢!
为什么坚持使用flatMap?我只是用 map
作为你的例子:
val result = operson.map(_.pid).map(_.idVal).getOrElse("NoValue")
甚至更短:
val result = operson.map(_.pid.idVal).getOrElse("NoValue")
您应该只将 flatMap
与 return Option
的函数一起使用。您的 pid
和 idVal
不是 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
的原因。
如果您正在寻找最简洁的解决方案,请考虑以下内容:
val result = operson.fold("NoValue")(_.pid.idVal)
虽然可能会觉得不清楚或令人困惑