Scala Option - Getting rid of if (opt.isDefined) {} - scala

My code is becoming littered with the following code pattern:
val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
val actualThingIWant = opt.get
}
Is there some way to simplify this? (it seems needlessly complex and a code smell). Ideally it would be something like:
if (Some(actualThingIWant) = somethingReturningAnOpt) {
doSomethingWith(actualThingIWant)
}
Is anything like that possible?

Maybe something like this:
somethingReturningAnOpt match {
case Some(actualThingIWant) => doSomethingWith(actualThingIWant)
case None =>
}
or as pst suggests:
somethingReturningAnOpt.foreach { actualThingIWant =>
doSomethingWith(actualThingIWant)
}
// or...
for (actualThingIWant <- somethingReturningAnOpt) {
doSomethingWith(actualThingIWant)
}

The canonical guide to Option wrangling is by Tony Morris.

Or:
somethingReturningAnOpt.map(doSomethingWith(_))
As in in:
val str = Some("foo")
str.map(_.toUpperCase)
... and use flatMap when the result of doSomethingWith is an Option itself.
val index = Option(Map("foo" -> "bar"))
index.flatMap(_.get("whatever")) // Returns None :-)
index.map(_.get("whatever")) // Returns Some(None) :-(

The following code cannot do something useful, since after the if, actualThingIWant is not always defined and as such this code will not compile, as long as you try to use actualThingIWant later.
val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
val actualThingIWant = opt.get
}
So, you have to provide a default value. This can be achieved with getOrElse:
val thingIWant = opt.getOrElse(myDefaultValue)
Or if you don't want to have actualThingIWant after the body of the if, which means you want to trigger some side-effects only if the option is defined, you can write:
opt.foreach{ thingIWant =>
println(thingIWant)
}
or a bit shorter
opt.foreach(println)

Related

Unwrapping Optional Play Route Parameters In Comprehensions

I have the following pattern:
Some play route with some optional parameters defined
GET /my/route controllers.something.Class.method(maybeA: Optional[Int], maybeB: Optional[Int])
In the method, I'd like to be able to use those parameters. I feel like I don't understand the proper pattern to use. What I'd like to do is something like:
blah match {
case Some(someCase) => // do something
case _ => for {
a <- maybeA
b <- maybeB
} yield {
somethingThatReturnsAFuture(a, b)
}
}
The problem is that the for comprehension returns an Option[Future[Int]], but I need it to return Future[Int]. I'd like to be able to just throw a get on the end of the comprehension, but that smells funny (and I don't actually think it's possible to just throw get at the end of the comprehension).
Any suggestions?
If something is Option then the result of the direct processing of this will be Option as well. The only way to get rid of Option is to define the None case.
val resultOpt: Option[Future[Int]] = blah match { ...
val result: Future[Int] = resultOpt match {
case Some(f) => f
case None => Future.successful(0)
}
Or just use getOrElse. The same code, different style:
val resultOpt: Option[Future[Int]] = blah match { ...
val result: Future[Int] = resultOpt.getOrElse(Future.successful(0))
A little bit more about this:
http://alvinalexander.com/scala/how-to-use-multiple-options-for-loop-comprehension

Return second string if first is empty?

Here is an idiom I find myself writing.
def chooseName(nameFinder: NameFinder) = {
if(nameFinder.getReliableName.isEmpty) nameFinder.getReliableName
else nameFinder.secondBestChoice
}
In order to avoid calling getReliableName() twice on nameFinder, I add code that makes my method look less elegant.
def chooseName(nameFinder: NameFinder) = {
val reliableName = nameFinder.getReliableName()
val secondBestChoice = nameFinder.getSecondBestChoice()
if(reliableName.isEmpty) reliableName
else secondBestChoice
}
This feels dirty because I am creating an unnecessary amount of state using the vals for no reason other than to prevent a duplicate method call. Scala has taught me that whenever I feel dirty there is almost always a better way.
Is there a more elegant way to write this?
Here's two Strings, return whichever isn't empty while favoring the first
There's no need to always call getSecondBestChoice, of course. Personally, I find nothing inelegant about the code after changing that - it's clear what it does, has no mutable state. The other answers just seem overcomplicated just to avoid using a val
def chooseName(nameFinder: NameFinder) = {
val reliableName = nameFinder.getReliableName()
if(reliableName.isEmpty) reliableName
else nameFinder.getSecondBestChoice()
}
If you really want to avoid the val, here's another variant (generalises well if there are more than two alternatives)
List(nameFinder.getReliableName(), nameFinder.getSecondBestChoice()).find(_.nonEmpty).get
(or getOrElse(lastResort) if everything in the list may be empty too)
Here's a way using Option. It's not that much prettier, but everything is called only once. This assumes you want a String as a result, and don't care if the second string is empty.
Some(nameFinder.getReliableName)
.filter(_.nonEmpty)
.getOrElse(nameFinder.secondBestChoice)
Option(namefinder.getReliableName) // transforms a potential null into None
.filter(_.trim.nonEmpty) // "" is None, but also " "
.getOrElse(nameFinder.secondBestChoice)
Or better, if you can modify getReliableName to return an Option[String]:
def chooseName(nameFinder: NameFinder): String =
namefinder.getReliableName getOrElse nameFinder.secondBestChoice
Finally, if secondBestChoice can fail as well (assuming it returns an Option[String]):
def chooseName(nameFinder: NameFinder): Option[String] =
namefinder.getReliableName orElse nameFinder.secondBestChoice
If you need it more than once:
scala> implicit class `nonempty or else`(val s: String) extends AnyVal {
| def nonEmptyOrElse(other: => String) = if (s.isEmpty) other else s }
defined class nonempty
scala> "abc" nonEmptyOrElse "def"
res2: String = abc
scala> "" nonEmptyOrElse "def"
res3: String = def
Using the following pattern matching may deliver a neater scalish code,
def chooseName(nameFinder: NameFinder) = {
nameFinder.getReliableName match {
case r if r.isEmpty => r
case _ => nameFinder.secondBestChoice
}
}

Using Option with cleaner code

Apologies if this is a newbie question...
In Scala I understand that it is preferred to use an Option rather than returning null when you have a function which returns an instance but could potentially return nothing. I understand that this makes it better with regards to safety, because you are not passing null references around, and risking NullPointerException somewhere down the line.
However, is there a cleaner way to handle options than using pattern matching?
The syntax I end up using is the following:
val optObj : Option[MyObject] = myFunctionThatReturnsOption
optObj match {
case Some(obj) => {
//my code using obj
}
case None => _
}
In reality all this doing is the equivalent of the Java version:
MyObject obj = myMethodThatCanReturnNull()
if (obj != null) {
//my code using obj
}
Is there some other way to avoid all this boilerplate in Scala when using Option instead of null references? All I want to do is execute a piece of code as long as the Option contains some object (i.e. is not None).
Use foreach, getOrElse and/or map if you want to work in a more consistent way. Here's some use cases and what I'd do:
//I want to get a non-null value and I have a sane default
val result = myOption getOrElse 3
//I want to perform some side effecting action but only if not None
myOption foreach{ value =>
println(value toString ())
}
//equivalently
for(value <- myOption){
//notice I haven't used the "yeild" keyword here
}
//I want to do a computation and I don't mind if it comes back as an Option
val result = for(value <- myOption) yield func(value)
val equivalent = myOption map func
The third example will use map in both cases.
It gets really interesting when you can mix and match things in a "for comprehension" (Google term.) Let's say that func also returns an Option but I only want things working in specific cases:
val result = for{
value <- myOption if value > 0
output <- func(value)
} yield output
Now I get back an Option but only if myOption contained an integer that was greater than zero. Pretty nifty stuff, no?
You can use foreach if you just want to perform some side-effecting operation with the value:
optObj.foreach(obj => {
//my code using obj
})
if you have some other use case you should use some other method on Option like map, filter or getOrElse.
Of course, the way I usually use options if I only care about present value is foreach:
optObj.foreach { obj =>
//...
}
Having said this, there are a lot of other options (which #wheaties enlisted) and some people keep battling about the true one.
You can use the flatMap-method pretty well with Option. Like hier:
case class Player(name: String)
def lookupPlayer(id: Int): Option[Player] = {
if (id == 1) Some(new Player("Sean"))
else if(id == 2) Some(new Player("Greg"))
else None
}
def lookupScore(player: Player): Option[Int] = {
if (player.name == "Sean") Some(1000000) else None
}
println(lookupPlayer(1).map(lookupScore)) // Some(Some(1000000))
println(lookupPlayer(2).map(lookupScore)) // Some(None)
println(lookupPlayer(3).map(lookupScore)) // None
println(lookupPlayer(1).flatMap(lookupScore)) // Some(1000000)
println(lookupPlayer(2).flatMap(lookupScore)) // None
println(lookupPlayer(3).flatMap(lookupScore)) // None
Here's a great reference for Scala best practices regarding options:
http://blog.tmorris.net/posts/scalaoption-cheat-sheet/index.html

How to create a play.api.libs.iteratee.Enumerator which inserts some data between the items of a given Enumerator?

I use Play framework with ReactiveMongo. Most of ReactiveMongo APIs are based on the Play Enumerator. As long as I fetch some data from MongoDB and return it "as-is" asynchronously, everything is fine. Also the transformation of the data, like converting BSON to String, using Enumerator.map is obvious.
But today I faced a problem which at the bottom line narrowed to the following code. I wasted half of the day trying to create an Enumerator which would consume items from the given Enumerator and insert some items between them. It is important not to load all the items at once, as there could be many of them (the code example has only two items "1" and "2"). But semantically it is similar to mkString of the collections. I am sure it can be done very easily, but the best I could come with - was this code. Very similar code creating an Enumerator using Concurrent.broadcast serves me well for WebSockets. But here even that does not work. The HTTP response never comes back. When I look at Enumeratee, it looks that it is supposed to provide such functionality, but I could not find the way to do the trick.
P.S. Tried to call chan.eofAndEnd in Iteratee.mapDone, and chunked(enums >>> Enumerator.eof instead of chunked(enums) - did not help. Sometimes the response comes back, but does not contain the correct data. What do I miss?
def trans(in:Enumerator[String]):Enumerator[String] = {
val (res, chan) = Concurrent.broadcast[String]
val iter = Iteratee.fold(true) { (isFirst, curr:String) =>
if (!isFirst)
chan.push("<-------->")
chan.push(curr)
false
}
in.apply(iter)
res
}
def enums:Enumerator[String] = {
val en12 = Enumerator[String]("1", "2")
trans(en12)
//en12 //if I comment the previous line and uncomment this, it prints "12" as expected
}
def enum = Action {
Ok.chunked(enums)
}
Here is my solution which I believe to be correct for this type of problem. Comments are welcome:
def fill[From](
prefix: From => Enumerator[From],
infix: (From, From) => Enumerator[From],
suffix: From => Enumerator[From]
)(implicit ec:ExecutionContext) = new Enumeratee[From, From] {
override def applyOn[A](inner: Iteratee[From, A]): Iteratee[From, Iteratee[From, A]] = {
//type of the state we will use for fold
case class State(prev:Option[From], it:Iteratee[From, A])
Iteratee.foldM(State(None, inner)) { (prevState, newItem:From) =>
val toInsert = prevState.prev match {
case None => prefix(newItem)
case Some(prevItem) => infix (prevItem, newItem)
}
for(newIt <- toInsert >>> Enumerator(newItem) |>> prevState.it)
yield State(Some(newItem), newIt)
} mapM {
case State(None, it) => //this is possible when our input was empty
Future.successful(it)
case State(Some(lastItem), it) =>
suffix(lastItem) |>> it
}
}
}
// if there are missing integers between from and to, fill that gap with 0
def fillGap(from:Int, to:Int)(implicit ec:ExecutionContext) = Enumerator enumerate List.fill(to-from-1)(0)
def fillFrom(x:Int)(input:Int)(implicit ec:ExecutionContext) = fillGap(x, input)
def fillTo(x:Int)(input:Int)(implicit ec:ExecutionContext) = fillGap(input, x)
val ints = Enumerator(10, 12, 15)
val toStr = Enumeratee.map[Int] (_.toString)
val infill = fill(
fillFrom(5),
fillGap,
fillTo(20)
)
val res = ints &> infill &> toStr // res will have 0,0,0,0,10,0,12,0,0,15,0,0,0,0
You wrote that you are working with WebSockets, so why don't you use dedicated solution for that? What you wrote is better for Server-Sent-Events rather than WS. As I understood you, you want to filter your results before sending them back to client? If its correct then you Enumeratee instead of Enumerator. Enumeratee is transformation from-to. This is very good piece of code how to use Enumeratee. May be is not directly about what you need but I found there inspiration for my project. Maybe when you analyze given code you would find best solution.

Repeating function call until we'll get non-empty Option result in Scala

A very newbie question in Scala - how do I do "repeat function until something is returned meets my criteria" in Scala?
Given that I have a function that I'd like to call until it returns the result, for example, defined like that:
def tryToGetResult: Option[MysteriousResult]
I've come up with this solution, but I really feel that it is ugly:
var res: Option[MysteriousResult] = None
do {
res = tryToGetResult
} while (res.isEmpty)
doSomethingWith(res.get)
or, equivalently ugly:
var res: Option[MysteriousResult] = None
while (res.isEmpty) {
res = tryToGetResult
}
doSomethingWith(res.get)
I really feel like there is a solution without var and without so much hassle around manual checking whether Option is empty or not.
For comparison, Java alternative that I see seems to be much cleaner here:
MysteriousResult tryToGetResult(); // returns null if no result yet
MysteriousResult res;
while ((res = tryToGetResult()) == null);
doSomethingWith(res);
To add insult to injury, if we don't need to doSomethingWith(res) and we just need to return it from this function, Scala vs Java looks like that:
Scala
def getResult: MysteriousResult = {
var res: Option[MysteriousResult] = None
do {
res = tryToGetResult
} while (res.isEmpty)
res.get
}
Java
MysteriousResult getResult() {
while (true) {
MysteriousResult res = tryToGetResult();
if (res != null) return res;
}
}
You can use Stream's continually method to do precisely this:
val res = Stream.continually(tryToGetResult).flatMap(_.toStream).head
Or (possibly more clearly):
val res = Stream.continually(tryToGetResult).dropWhile(!_.isDefined).head
One advantage of this approach over explicit recursion (besides the concision) is that it's much easier to tinker with. Say for example that we decided that we only wanted to try to get the result a thousand times. If a value turns up before then, we want it wrapped in a Some, and if not we want a None. We just add a few characters to our code above:
Stream.continually(tryToGetResult).take(1000).flatMap(_.toStream).headOption
And we have what we want. (Note that the Stream is lazy, so even though the take(1000) is there, if a value turns up after three calls to tryToGetResult, it will only be called three times.)
Performing side effects like this make me die a little inside, but how about this?
scala> import scala.annotation.tailrec
import scala.annotation.tailrec
scala> #tailrec
| def lookupUntilDefined[A](f: => Option[A]): A = f match {
| case Some(a) => a
| case None => lookupUntilDefined(f)
| }
lookupUntilDefined: [A](f: => Option[A])A
Then call it like this
scala> def tryToGetResult(): Option[Int] = Some(10)
tryToGetResult: ()Option[Int]
scala> lookupUntilDefined(tryToGetResult())
res0: Int = 10
You may want to give lookupUntilDefined an additional parameter so it can stop eventually in case f is never defined.