如何用惯用的Scala编码?

如何用惯用的Scala编码?,scala,Scala,假设我想编写一个函数defpair(s:String):Option[(String,String)]来将字符串转换为Scala中的键值对。字符串应类似于:“ 您将如何更正下面的解决方案 def pair(s:String) = { val a = s.split(":"); if (a.length == 2) Some((a(0).trim, a(1).trim)) else None } def对(s:字符串)={ val a=s.split(“:”);如果(a.length==2)一

假设我想编写一个函数
defpair(s:String):Option[(String,String)]
来将字符串转换为Scala中的键值对。字符串应类似于
:“

您将如何更正下面的解决方案

def pair(s:String) = { val a = s.split(":"); if (a.length == 2) Some((a(0).trim, a(1).trim)) else None } def对(s:字符串)={ val a=s.split(“:”);如果(a.length==2)一些((a(0.trim,a(1.trim))其他无 }
我要去掉分号,把它改成两行。否则,这是一个非常好的函数代码

再看一眼,模式匹配似乎更合适:

def pair(s:String) = 
  s.split(":") match {
    case Array(a, b) => Some((a, b))
    case _ => None
  } 
在这种情况下,模式匹配更适合的原因是您使用
if-else
来模拟数据结构解构,这正是模式匹配的目的。这将使您的抽象级别降低,逻辑更加复杂,并有更多机会植入bug。同样,您的实现依赖于
a(0)
中的部分函数,这是一种不鼓励的做法

部分函数是一种未为其输入的整个域定义的函数。在您的情况下,这意味着对空数组调用
a(0)
将导致异常,但不会产生有意义的函数结果。在这个特定的例子中,
if
条件保护您免受该情况的影响,但在更复杂的情况下,如果该条件位于函数体之外,则使用部分函数将成为潜在的bug。这就是为什么它作为一种普遍做法不被鼓励的原因


但我还必须指出,您不应该对
if-else
结构表示普遍的不满。它是一个完全有效的函数表达式,有它的用途。只是在这个特定的例子中,这是一个次优的方法。

我个人认为有两种方法更好:

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种方法:)你能描述一下为什么它们看起来更漂亮吗?使用条件表达式没有什么错,但它们通常更具命令性或过程性(“检查这个!”,“做那个!”),模式匹配通常感觉更具声明性,我倾向于使用声明性代码。你说得对<代码>如果看起来像贾拉而不是真正的斯卡拉。@迈克尔不必在意事情的外观。模式匹配更适合这种特殊情况,还有更重要的原因。我已经在更新我的答案时解释过了。@NikitaVolkov谢谢。很好的解释。为了消除歧义,
Some(a,b)
应该用
Some((a,b))
显式标识Tuple2。