Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic Scala for Nested Options

Tags:

scala

Lets say I have an Element object (from JDom actually). It might have a child element called "Group", or it might not. If it does, then it might have an attribute called "ID", or again it might not. I want the ID value if it exists.

If Java I would write.

private String getId(Element e) {
  for (Element child : e.getChildren()) 
    if (child.getName().equals("Group")) 
      for (Attribute a : child.getAttributes()) 
        if (a.getName().equals("ID"))
          return a.getValue();
  return null;
}

In scala I have either

  val id = children.find(_.getName == "Group") match {
        case None => None
        case Some(child) => {
            child.getAttributes.asScala.find(_.getName == "ID") match {
                case None => None
                case Some(a) => Some(a.getValue)
            }
        }
    }

Or

val id = children.find(_.getName == "Group").
             map(_.getAttributes.asScala.find(_.getName == "ID").
             map(_.getValue).getOrElse("")).getOrElse("")

Which of theirs, or a third, is more idiomatic

like image 683
sksamuel Avatar asked Nov 28 '12 14:11

sksamuel


1 Answers

How about this?

val idOption = children
   .find(_.getName == "Group")
   .flatMap(_.getAttributes.asScala.find(_.getName == "ID"))

Or, with a for comprehension:

val idOption =
  for {
    child <- children.find(_.getName == "Group")
    id <- child.getAttributes.asScala.find(_.getName == "ID")
  } yield id
like image 113
Jean-Philippe Pellet Avatar answered Nov 16 '22 00:11

Jean-Philippe Pellet