如何用惯用的Scala编写代码?

时间:2014-02-12 13:02:06

标签: scala

假设我想编写一个函数def pair(s:String):Option[(String, String)]来将字符串转换为Scala中的键值对。该字符串应该看起来像"<key>:<value>"

您如何更正以下解决方案?

def pair(s:String) = {
  val a = s.split(":"); if (a.length == 2) Some((a(0).trim, a(1).trim)) else None
}

2 个答案:

答案 0 :(得分:8)

我个人觉得两种方法更好一点:

def pair(s: String) = s.split(":") match {
  case Array(k, v) => Some(k.trim -> v.trim)
  case _ => None
}

或使用Scala方便的正则表达式提取器:

val Pair = """\s*([^\s:]+)\s*:\s*([^\s:]+)\s*""".r

def pair(s: String) = s match {
  case Pair(k, v) => Some(k -> v)
  case _ => None
}

但是,你的也不是那么糟糕。

答案 1 :(得分:4)

我会删除分号并将其分为两行。否则它是一个完全精细的功能代码。

第二眼看模式匹配似乎更合适:

def pair(s:String) = 
  s.split(":") match {
    case Array(a, b) => Some(a, b)
    case _ => None
  } 

在这种情况下,模式匹配更适合的原因是您使用if-else来模拟数据结构解构 - 确切的事情,模式匹配的用途。这会让您获得更低的抽象级别,更多的逻辑和更多的植入bug的机会。因此,您的实现依赖于a(0)中的部分功能,这始终是一种沮丧的做法。

部分函数是一个未为其输入的整个域定义的函数。在您的情况下,这意味着在空数组上调用a(0)将导致异常,但不会导致有意义的功能结果。在这个特定示例中,if条件可以保护您免受该场景的影响,但是如果将此条件置于函数体之外,则在更复杂的情况下,使用部分函数会成为潜在的错误。这就是为什么不鼓励它作为一般做法。

但我也必须提一下,你不应该对if-else构造一般不赞成。它是一个非常有效的功能表达,有其用途。只是在这个特定的例子中,这是一种次优的方法。