【发布时间】:2016-05-17 22:32:08
【问题描述】:
诚然,我对 Scala 非常陌生,而且我在使用许多 Scala 示例中看到的语法糖时遇到了麻烦。 它通常会导致一个非常简洁的陈述,但老实说到目前为止(对我而言)有点难以理解。
因此,我希望将 Option 类的典型用法(安全解引用)作为一个很好的起点来理解,例如,在我看到的特定示例中使用下划线。
我发现了一篇非常好的文章,展示了使用 Option 来避免 null 情况的示例。
https://medium.com/@sinisalouc/demystifying-the-monad-in-scala-cc716bb6f534#.fhrljf7nl
他这样描述一个用途:
trait User {
val child: Option[User]
}
顺便说一句,您也可以将这些函数编写为就地 lambda 函数而不是先验地定义它们。然后代码变成 这个:
val result = UserService.loadUser("mike")
.flatMap(user => user.child)
.flatMap(user => user.child)
看起来不错!也许不像 groovy 那样简洁,但还不错。
所以我想我会尝试将它应用到我试图解决的案例中。
我有一个类型Person,其中Person 的存在是可选的,但是如果我们有一个人,他的属性是有保证的。因此,在 Person 类型本身中没有使用 Option 类型。
Person 的 PID 类型为 Id。 Id 类型由两个String 类型组成; Id-Type 和 Id-Value。
我使用 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 一样好的东西吗?
在上面的链接示例中,他能够使用我之前提到的一些语法糖使他的陈述更加简洁。下划线:
或者更简洁:
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 是实现我所追求的最佳方式吗?还是有更好的更简洁和/或可读的方式来做到这一点?
提前致谢!
【问题讨论】: