诚然,我对 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
,其中 a 的存在Person
是可选的,但如果我们有一个人,他的属性是有保证的。因此,Option
在Person
类型本身中没有使用类型。
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")
斯卡拉抱怨。
<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 是实现我所追求的最佳方式吗?还是有更好的更简洁和/或可读的方式来做到这一点?
提前致谢!