matanox
matanox

Reputation: 13686

scala idiomatic way of transforming a list to an option

What might be the most idiomatic way for turning any scala collection into an Option of the same collection, whereas when the collection is empty, the option would be None and otherwise just a Some of the original?

Oh, and without making scala create a memory copy of the entire collection for that humble conversion.

Option.apply is suited for translating null to Option of type None, a nice legacy-wrangling utility, but useless for idiomatic scala seeking the following semantics:

val some = Option(List(3,4,5))
val none = Option(List()) // seeking None, rather than Some(List()) here

Upvotes: 2

Views: 2266

Answers (4)

Shadowlands
Shadowlands

Reputation: 15074

I'd probably just go with a filter call after creating the Option:

scala> Option(List()).filter(_.isNonEmpty)
res1: Option[List[Nothing]] = None

scala> Option(List(1,2,3)).filter(_.isNonEmpty)
res2: Option[List[Int]] = Some(List(1, 2, 3))

Upvotes: 5

lloydmeta
lloydmeta

Reputation: 1339

Similar to Lukasz's answer, but more complete and works for any collection (I think all collections extend from Traversable as this image suggests https://i.sstatic.net/Dsptl.png) as requested.

object EnrichedCollections {

  implicit class CollectionOps[A <: Traversable[_]](val collection: A) extends AnyVal {

    /**
     * Returns None if the collection is empty, otherwise returns Some of the collection
     */
    def toOption: Option[A] = if (collection.isEmpty) None else Some(collection)
  }

}

import EnrichedCollections._

assert(Nil.toOption == None)
assert(Seq(1,2).toOption == Some(Seq(1,2)))
assert(Map.empty.toOption == None)
assert(Map(1 -> "hi", 2 -> "bye").toOption == Some(Map(1 -> "hi", 2 -> "bye")))

Upvotes: 3

jazmit
jazmit

Reputation: 5410

Just for fun:

val list = List(1, 2, 3, 4)
val option = list.headOption.map{_ => list}

However, I would question why you would want to do this... using isEmpty is a nice way of checking uniformly for empty lists or None values - you might find this avoids you having to convert to Option in the first place.

Upvotes: 0

Łukasz
Łukasz

Reputation: 8663

I feel like it is not a common thing to do and can't think of any common idiomatic way, what I can suggest is adding toOption method like this:

implicit class OptList[A](val list: List[A]) extends AnyVal {
  def toOption: Option[List[A]] = if (list.isEmpty) None else Some(list)
}

and use it as follows:

scala> List().toOption
res0: Option[List[Nothing]] = None

scala> List(615, 5).toOption
res1: Option[List[Int]] = Some(List(615, 5))

toOption is a method in scala that appears in some other contexts, for example Try has toOption method.

Upvotes: 4

Related Questions