Reputation: 13686
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
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
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
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
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