Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return tail if list is not empty or return empty list

Tags:

scala

From the list of emails I have to get 2 values:

  • option of the head of the list
  • list of the rest of them

What is the idiomatic way to code this in scala? So far I have:

val primaryEmail = emails.headOption
val conf = Map[String, Any](
  "email" -> primaryEmail,
  "additionalEmails" -> 
     primaryEmail.map(_ => emails.tail).getOrElse(List())
)

EDIT: As to why there is Any: We use GSON for json serialization, and internally convert all collections to java collections and pass them to jsonSerializationContext.serialize, which have java.lang.Object as an argument, so Any suits us just fine.

like image 840
zbstof Avatar asked Jun 18 '13 15:06

zbstof


2 Answers

I would probably just drop the first element (if you're sure that the first element always is the primary email). Like so:

val conf = Map[String, Any](
  "email" -> emails.headOption,
  "additionalEmails" -> emails.drop(1)
)

This doesn't give an exception if the primary email is not in the list (the list is empty).

like image 82
Jens Egholm Avatar answered Nov 13 '22 21:11

Jens Egholm


Learn you a scalaz. All this is available in one call:

val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
val conf = Map("email" -> primary, "additionalEmails" -> rest)

Demonstration:

scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)

If non-empty

scala> val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
primary: Option[Int] = Some(1)
rest: List[Int] = List(2, 3)

if empty:

scala> val list = List.empty[Int]
list: List[Int] = List()

scala> val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
primary: Option[Int] = None
rest: List[Int] = List()

How does this work?

The <^> call says: if this list is empty, return the zero for the type as defined by the return type function to the right. If the list is non-empty, apply the function to it

The value nel is a NonEmptyList, which I can safely call head and tail on without fearing that they will throw an exception. My function returns a (Option[A], List[A])

Of course, the zero for this is just (None, Nil) for any A

like image 29
oxbow_lakes Avatar answered Nov 13 '22 22:11

oxbow_lakes