3

现在我有很多可以为空的参数,我想为整个表达式分配一个默认值。

现在我正在做类似的事情

var name: Option[String] = None
var surname: Option[String] = Some("Smith")

val fullName:String = {
  name.map { name => 
    surname.map { surname => 
      surname + ", " + name
    }.getOrElse("unknown")
  }.getOrElse("unknown")
}

但这有点太冗长了。我想知道什么是更惯用和优雅的方式来处理它,理想情况下它会是这样的(当然是伪代码!):

val fullName = (name + ", " + surname).getOrElse("unknown")

或类似的东西...

(只是避免双重 .getOrElse 会很棒......)

4

3 回答 3

15

这个怎么样

scala> val fullName = (for(n <-name;s <-surname) yield n + s).getOrElse("unknown")  
fullName: String = unknown
于 2012-06-03T23:53:19.810 回答
13

您可能想了解一些有关应用函子的知识,因为可以以各种方式使用相同的模式。使用 scalaz,有应用程序构建器:

(name |@| surname)(_ + _)

这是怎么回事:

(M[A] |@| M[B])(fabc) ~> M[C] //fabc is a function f: (A, B) => C

也就是说,函数f被提升到了 applicative functor 的领域M。这特别有用,因为它适用于Option, Validation, Promise,List等等Stream。也就是说,就像您可能使用的表达式一样:

(name |@| surname)(_ + _)

wherenamesurnameare both Option[String],您可以将它们切换为ValidationNEL[Exception, String]orPromise[String]并且代码仍然会做完全相同的事情(适用于正在使用的更高类型)。这是非常强大的。

于 2012-06-04T00:12:30.017 回答
2

我找到了这种方式:

val fullname = (name, surname) match {
  case (Some(x), Some(y)) => x + ", " + y
  case _ => "unknonw"
}

但它仍然有点冗长

于 2012-06-03T23:54:54.847 回答