Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala syntax to access property of an option inline and chain "OrElse"?

Tags:

scala

Sometimes I want to return the value that is a property of an object wrapped in option, but I can't do that easily with getValue.orElse(otherValue).

For instance, I am mapping properties inline and I want to use a pattern like object.get.property.orElse(""). But the preceding doesn't compile. How can I access that property and still maintain an option-like syntax?

like image 985
crockpotveggies Avatar asked Jun 26 '12 17:06

crockpotveggies


2 Answers

You can use map() to achieve this. It becomes obvious once you start to think about Option[T] like a container of type T that can hold 0 or 1 element:

case class Person(name: String, age: Int)

val optionalPerson = Some(Person("John", 29))
val name = optionalPerson map {_.name} getOrElse "?"

Furthermore if you have a nested structure of Options:

case class Person(name: String, age: Int, parent: Option[Person])

you can extract nested Option with flatMap:

val optionalPerson = Some(Person("John", 29, Some(Person("Mary", 55, None))))
val parentName = optionalPerson flatMap {_.parent} map {_.name} getOrElse "Unknown parent name"  //Mary

Or you can use filter() to turn Some() into None when value wrapped in Some does not satisfy some criteria:

val nameIfAdult = optionalPerson filter {_.age >= 18} map {_.name}
like image 143
Tomasz Nurkiewicz Avatar answered Nov 09 '22 23:11

Tomasz Nurkiewicz


Use map() to maintain the option-like pattern.

For instance you need to get the name property of a field object. But if field is actually None, you can return a blank string. Like this:

field.map(_.name).getOrElse("")

And using it in the bigger picture:

implicit def castDraftModel(drafts:List[Tuple2[models.ReportInstance,Option[models.Report]]]) = drafts.map{
    (field) => 
      List(Field(
        field._1.id, 
        field._1.teamId, 
        field._2.map(_.name).getOrElse(""), 
        field._1.lastModifiedRelative, 
        field._2.map(_.id).getOrElse(0L), 
        field._2.map(_.reportType).getOrElse(""), 
        field._1.referenceId, 
        field._1.referenceName( draft._2.map(_.reportType).getOrElse("") ) ))
  }.flatten.sortBy(_.id)
like image 22
crockpotveggies Avatar answered Nov 10 '22 01:11

crockpotveggies