Scala最佳实践:简化Option[]用法

9
作为Java转Scala的人,我经常会重写空值处理相关的代码,比如:
val itemOpt: Option[Item] = items.get(coords) // "items" is something like a Map
if (itemOpt.isDefined) {
  val item = itemOpt.get
  // do something with item, querying item fields a lot of times, for example
  if (item.qty > 10) {
    storeInVault(item.name, item.qty, coords)
  } else {
    storeInRoom(item)
  }
}

我猜它看起来很丑,而且它真的看起来像是从Java重新编写的代码:
Item item = items.get(coords);
if (item != null) {
  // do something with item, querying item fields a lot of times, for example
}

在Java中,这看起来也很丑,但至少可以少一行代码。在Scala中,如何处理这样简单的情况最佳实践是什么?我已经知道了使用 flatMapflatten 处理Option[Stuff]集合,以及使用 getOrElse 处理默认值。我梦想有一个像这样的函数:

items.get(coords).doIfDefined(item =>
  // do stuff with item
)

但是在Option API中我没有看到类似的内容。


4
这可能会有帮助:http://dibblego.wordpress.com/2008/01/16/scalaoption-cheat-sheet/。 - dhg
4个回答

12

非常流行的使用模式:

val item: Option[Int] = None
val result = item map (_ + 1) getOrElse 0

如果值已定义,只需使用map来转换值。

如果您只想使用存储在Option中的值,则只需使用foreach

item foreach { it =>
    println(it)
}

正如你所看到的,Option 还支持许多集合方法,因此您实际上不需要学习新的 API。您可以将其视为只包含 1 或 0 个元素的集合。


7
这应该能实现您想要做的事情:
items.get(coords).foreach{ item => 
  //do stuff
}

6
或者,您可以使用 for 推导式 for(item <- maybeItem) {...},其中 maybeItem 是您的选项。 - om-nom-nom
为了更加节省,注意:items.get(coords) map { item => //... - Connor Doyle

5

看看这篇 Tony Morris 的文章,它对我理解 Option 很有帮助。你的代码可以改写成这样:

for (item <- items.get(coords)) { // "items" is something like a Map
  // do something with item, querying item fields a lot of times, for example
  if (item.qty > 10) {
    storeInVault(item.name, item.qty, coords)
  } else {
    storeInRoom(item)
  }
}

3
此外,Option 可以与 if 条件语句一起在模式匹配中使用。个人认为在这种情况下使用它更易于阅读。
因为 Option 上的 map 只有在 Option 不是 None 时才会生效,所以您可以先执行它,然后使用模式匹配来查看 itemOpt 是否为 Some 或 None。
def shouldInVault(item: Item) = item.qty > 10

val itemOpt: Option[Item] = items.get(coords).map(...)

itemOpt match {
    case Some(item) if shouldInVault(item) => storeInVault(item.name, item.qty, coords)
    case Some(item) => storeInRoom(item)
    case None =>
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接