Using Option with cleaner code - scala

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

Related

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
}
}

Handle Scala Option idiomatically

What is the more idiomatic way to handle an Option, map / getOrElse, or match?
val x = option map {
value => Math.cos(value) + Math.sin(value)
} getOrElse {
.5
}
or
val x = option match {
case Some(value) => Math.cos(value) + Math.sin(value)
case None => .5
}
You could always just look at the Scaladoc for Option:
The most idiomatic way to use an scala.Option instance is to treat it as a collection or monad and use map,flatMap, filter, or foreach:
val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")
And a bit later:
A less-idiomatic way to use scala.Option values is via pattern matching:
val nameMaybe = request getParameter "name"
nameMaybe match {
case Some(name) =>
println(name.trim.toUppercase)
case None =>
println("No name value")
}
Use fold for this kind of map-or-else-default thing:
val x = option.fold(0.5){ value => Math.cos(value) + Math.sin(value) }
Obviously both are valid and I don't think one is more idiomatic than the other. That being said, using map uses the fact the Option is a Monad. This can be particularly advantageous when combining two Options. Say you have two Option[Int] that you would like to add. In this case instead of doing multiple matches it is much cleaner to use map/flatMap and it's equivalent "for comprehensions". So for your example both are valid... but for other examples using map/flatMap is often much more succinct.
Some(6).flatMap(intValue => Some(5).map(intValue + _))
or
for {
i <- Some(6)
j <- Some(5)
} yield i + j
All of them have different semantics, so in your case none of them.
map applies some function to the value inside Option, if it exists (Some, not None). Basically this is how you safely work with Options, appling function on some null value is dangeroues, cause it can throw NPE, but in case with Option it just returns None.
getOrElse simply returns either it's value or default one (which you provide as an argument). It won't do anything with the value inside the Option, you can just extract it, if you have Some, or return a default one, in case of None.
and match approach i'd say is a combination of two, cause you can apply some computation on the values and extract it from the Option

How to handle Option of List in Scala?

Suppose I have a function getCustomers and getOrdersByCustomer.
def getCustomer():List[Customer] = ...
def getOrdersByCustomer(cust: Customer): List[Order] = ...
Now I can easily define a function getOrdersOfAllCustomers
def getOrdersOfAllCustomers(): List[Order] =
for(cust <- getCustomer(); order <- getOrderByCustomer(cust)) yield order
So far, so good but what if getCustomer and getOrdersByCustomer return Options of the lists ?
def getCustomer():Option[List[Customer]] = ...
def getOrdersByCustomer(cust: Customer): Option[List[Order]] = ...
Now I would like to implement two different flavors of getOrdersOfAllCustomers():
Return None if one of the functions returns None;
Return None if getCustomer returns None and do not care if getOrdersByCustomer returns None.
How would you suggest implement it?
I think you should consider three possibilities--a populated list, an empty list, or an error--and avoid a lot of inelegant testing to figure out which one happened.
So use Try with List:
def getOrdersOfAllCustomers(): Try[List[Order]] = {
Try(funtionReturningListOfOrders())
}
If all goes well, you will come out with a Success[List[Order]]; if not, Failure[List[Order]].
The beauty of this approach is no matter which happens--a populated list, an empty list, or an error--you can do all the stuff you want with lists. This is because Try is a monad just like Option is. Go ahead and filter, forEach, map, etc. to your heart's content without caring which of those three occurred.
The one thing is that awkward moment when you do have to figure out if success or failure happened. Then use a match expression:
getOrdersOfAllCustomers() match {
case Success(orders) => println(s"Awww...yeah!")
case Failure(ex) => println(s"Stupid Scala")
}
Even if you don't go with the Try, I implore you not to treat empty lists different from populated lists.
Try this,
def getOrdersOfAllCustomers(): Option[List[Order]] =
for{
cust <- getCustomer().toList.flatten;
order <- getOrderByCustomer(cust).toList.flatten
} yield order
This should do it:
def getOrdersOfAllCustomers(): Option[List[Order]] = {
getCustomer() flatMap { customers =>
//optOrders is a List[Option[List[Order]]]
val optOrders = customers map { getOrderByCustomer }
// Any result must be wrapped in an Option because we're flatMapping
// the return from the initial getCustomer call
if(optOrders contains None) None
else {
// map the nested Option[List[Order]]] into List[List[Order]]
// and flatten into a List[Order]
// This then gives a List[List[Order]] which can be flattened again
Some(optOrders.map(_.toList.flatten).flatten)
}
}
}
The hard part is handling the case where one of the nested invocations of getOrderByCustomer returns None and bubbling that result back to the outer scope (which is why using empty lists is so much easier)

Expecting null in Scala. Should Option be used?

I have a play template in which the most typical scenario for a parameter is "null".
I have understood that idiomatic Scala favors Option instead.
My first intuition coming from java would be using null.
Case with null:
In Controller
views.html.addPost(errors.errorsAsJson)
In View
#(errors: play.api.libs.json.JsValue = null)
...
#if(errors != null){#errors}
Case with Option:
In Controller
views.html.addPost(Option(errors.errorsAsJson))
In View
#(errors: Option[play.api.libs.json.JsValue] = None)
...
#{errors match {
case None => {}
case _ => {errors.get}
}
}
Update: I got it now.
Instead of:
#{errors match {
case None => {}
case _ => {errors.get}
}
}
I could just do
#errors
Update 2:
Apparently I didn't have to do the null check with null either? Maybe somePlay framework magic? Calling a null variable worked without exception.
The reason Option is less verbose is that you don't need to do those null checks. In other words, your match/case verbosity is unnecessary.
Let's assume we have these two variables:
val x: Option[Int] = Some(5)
val y: Option[Int] = None
If we want to call a function things that are Some rather than None, we don't need to null-check:
x foreach println // prints 5
y foreach println // nothing printed
Or if we want to apply a function and get a new result, it's similar, and keeps track of whether the input was present or not.
val f = (i: Int) => i + 1
x map f // Some(6)
y map f // None
There are plenty more examples of how Option cleans things up, but this should give you an idea.

How to use scalax.io.CommandLineParser?

I want to create a class that takes string array as a constructor argument and has command line option values as members vals. Something like below, but I don't understand how the Bistate works.
import scalax.data._
import scalax.io.CommandLineParser
class TestCLI(arguments: Array[String]) extends CommandLineParser {
private val opt1Option = new Flag("p", "print") with AllowAll
private val opt2Option = new Flag("o", "out") with AllowAll
private val strOption = new StringOption("v", "value") with AllowAll
private val result = parse(arguments)
// true or false
val opt1 = result(opt1Option)
val opt2 = result(opt2Option)
val str = result(strOption)
}
Here are shorter alternatives to that pattern matching to get a boolean:
val opt1 = result(opt1Option).isInstanceOf[Positive[_]]
val opt2 = result(opt2Option).posValue.isDefined
The second one is probably better. The field posValue is an Option (there's negValue as well). The method isDefined from Option tells you whether it is a Some(x) or None.
I'm not personally familiar with Scalax or Bistate in particular, but just looking at the scaladocs, it looks like a left-right disjunction. Scala's main library has a monad very much like this (Either), so I'm surprised that they didn't just use the standard one.
In essence, Bistate and Either are a bit like Option, except their "None-equivalent" can contain a value. For example, if I were writing code using Either, I might do something like this:
def div(a: Int, b: Int) = if (b != 0) Left(a / b) else Right("Divide by zero")
div(4, 2) match {
case Left(x) => println("Result: " + x)
case Right(e) => Println("Error: " + e)
}
This would print "Result: 2". In this case, we're using Either to simulate an exception. We return an instance of Left which contains the value we want, unless that value cannot be computed for some reason, in which case we return an error message wrapped up inside an instance of Right.
So if I want to assign to variable boolean value of whether flag is found I have to do like below?
val opt1 = result(opt1Option) match {
case Positive(_) => true
case Negative(_) => false
}
Isn't there a way to write this common case with less code than that?