Reputation: 63405
Right now I have many params that can be none, and I want to assign the whole expressiona default value.
Right now I'm doing things like
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")
}
but it's a bit too verbose. I'd like to know what would be a more idiomatic and elegant way to handle it, ideally it would be something like (it's pseudo code, of course!):
val fullName = (name + ", " + surname).getOrElse("unknown")
or something similar...
(just avoiding the double .getOrElse would be great...)
Upvotes: 3
Views: 529
Reputation: 134270
You might want to learn a bit about applicative functors, as the same pattern can be used in all sorts of ways. Using scalaz, there is the applicative builder:
(name |@| surname)(_ + _)
What is going on is this:
(M[A] |@| M[B])(fabc) ~> M[C] //fabc is a function f: (A, B) => C
That is, the function f
is being lifted into the realm of applicative functor M
. This is particularly useful because it works with Option
, Validation
, Promise
, List
, Stream
and many more. That is, just as you might use the expression:
(name |@| surname)(_ + _)
where name
and surname
are both Option[String]
, you could switch them to be ValidationNEL[Exception, String]
or Promise[String]
and the code would still do the exact same thing (appropriate to the higher kind being used). This is very powerful.
Upvotes: 13
Reputation: 63405
I've found this way:
val fullname = (name, surname) match {
case (Some(x), Some(y)) => x + ", " + y
case _ => "unknonw"
}
but it's still a bit verbose
Upvotes: 2
Reputation: 18859
How about this
scala> val fullName = (for(n <-name;s <-surname) yield n + s).getOrElse("unknown")
fullName: String = unknown
Upvotes: 15