I have read the blog post recommended me here. Now I wonder what some those methods are useful for. Can you show e开发者_开发知识库xamples of using forall
(as opposed to foreach
) and toList
of Option
?
map
: Allows you to transform a value "inside" anOption
, as you probably already know forList
s. This operation makesOption
a functor (you can say "endofunctor" if you want to scare your colleagues)flatMap
:Option
is actually a monad, andflatMap
makes it one (together with something like a constuctor for a single value). This method can be used if you have a function which turns a value into anOption
, but the value you have is already "wrapped" in anOption
, soflatMap
saves you the unwrapping before applying the function. E.g. if you have anOption[Map[K,V]]
, you can writemapOption.flatMap(_.get(key))
. If you would use a simplemap
here, you would get anOption[Option[V]]
, but withflatMap
you get anOption[V]
. This method is cooler than you might think, as it allows to chain functions together in a very flexible way (which is one reason why Haskell loves monads).flatten
: If you have a value of typeOption[Option[T]]
,flatten
turns it into anOption[T]
. It is the same asflatMap(identity(_))
.orElse
: If you have several alternatives wrapped inOption
s, and you want the first one that holds actually a value, you can chain these alternatives withorElse
:steakOption.orElse(hamburgerOption).orElse(saladOption)
getOrElse
: Get the value out of theOption
, but specify a default value if it is empty, e.g.nameOption.getOrElse("unknown")
.foreach
: Do something with the value inside, if it exists.isDefined
,isEmpty
: Determine if thisOption
holds a value.forall
,exists
: Tests if a given predicate holds for the value.forall
is the same asoption.map(test(_)).getOrElse(true)
,exists
is the same, just withfalse
as default.toList
: Surprise, it converts theOption
to aList
.
Many of the methods on Option may be there more for the sake of uniformity (with collections) rather than for their usefulness, as they are all very small functions and so do not spare much effort, yet they serve a purpose, and their meanings are clear once you are familiar with the collection framework (as is often said, Option is like a list which cannot have more than one element).
forall checks a property of the value inside an option. If there is no value, the check pass. For example, if in a car rental, you are allowed one additionalDriver: Option[Person]
, you can do
additionalDriver.forall(_.hasDrivingLicense)
exactly the same thing that you would do if several additional drivers were allowed and you had a list.
toList may be a useful conversion. Suppose you have options: List[Option[T]], and you want to get a List[T], with the values of all of the options that are Some. you can do
for(option <- options; value in option.toList) yield value
(or better options.flatMap(_.toList)
)
I have one practical example of toList
method. You can find it in scaldi (my Scala dependency injection framework) in Module.scala at line 72:
https://github.com/OlegIlyenko/scaldi/blob/f3697ecaa5d6e96c5486db024efca2d3cdb04a65/src/main/scala/scaldi/Module.scala#L72
In this context getBindings
method can return either Nil
or List
with only one element. I can retrieve it as Option
with discoverBinding
. I find it convenient to be able to convert Option
to List
(that either empty or has one element) with toList
method.
精彩评论