How to do null checks in Scala in an idiomatic way? - scala

case class Account(
val name: String,
val uuid: String,
val lat: Double,
val lng: Double
)
}
object Account {
def create(row: Row): Option[YellowAccount] = {
val name = row.getAs[String]("store_name")
val uuid = row.getAs[String]("uuid")
val latO = row.getAs[String]("latitude")
val lngO = row.getAs[String]("longitude")
// How do you do null checks here in an idiomatic way?
if (latO == null || lngO == null) {
return None
}
Some(YellowAccount(name, uuid, latO.toDouble, lngO.toDouble))
}
}
lat/long are compulsory fields in Account. How do you do null checks in an idiomatic way?

You can use Option type to handle null values. You just wrap a nullable value in Option and then you can pattern match on it or something else. In your example, I think the most concise way to combine 4 nullable values is for-comprehension:
import scala.util.Try
object Account {
def create(row: Row): Option[YellowAccount] = {
for {
name <- Option( row.getAs[String]("store_name") )
uuid <- Option( row.getAs[String]("uuid") )
latO <- Try( row.getAs[String]("latitude").toDouble ).toOption
lngO <- Try( row.getAs[String]("longitude").toDouble ).toOption
} yield
YellowAccount(name, uuid, latO, lngO)
}
}
EDIT
Another thing here is _.toDouble conversion, which may throw an exception if it fails to parse the string, so you can wrap it in Try instead (I updated the code above).
EDIT2
To clarify what's happening here:
when you wrap a value in Option it becomes None if the value is null, or Some(...) with the value otherwise
similarly when wrapping something that may throw an exception in Try, it becomes either Failure with the exception, or Success with the value
toOption method converts Try to Option in a straightforward way: Failure becomes None, Success becomes Some
in the for-comprehension if any of the four Options returns None (i.e. one of them was null of failed to parse a number), the whole statement returns None, and only if each of the four yields a value, they are passed to the YellowAccount constructor

As the other answer suggests, you can use Option to handle possible nulls. You can't use for comprehension the way it is suggested there, but there are several ways around it. The easiest, probably is to .zip the two Options together, and then map over the result:
Option(row.getAs[latitude])
.zip(Option(row.getAs[String]("longitude")))
.map { case (lat, long) =>
YellowAccount(
row.getAs[String]("store_name"),
row.getAs[String]("uuid"),
lat.toDouble,
long.toDouble
)
}

Related

Using Option with .map() and .getOrElse()

I am trying to read a value from a Map[String, String] given a key.
This key|value is optional, in that it might not be there
So, I want to use Option and then map & getOrElse as below to write the value if it's there, or set it to some default in case it's not there.
val endpoint:String = Option(config.getString("endpoint"))
.map(_.value())
.getOrElse()
The code above fails with "Symbol value is inaccessible from this place"
config is a Map[String, Object]
getString is a method on config that takes in the key, and returns the value
public String getString(String key){
<...returns value...>
}
I could just drop the Option() and do, but then I have to deal with the exception that will be throw by getString()
val endpoint:String = config.getString("endpoint")
Any ideas what's wrong with this, or how to fix this?
Better ways of writing this?
UPDATE: I need to mention that config is an object in an imported Java library. Not sure if that makes a difference or not.
If I understand your question correctly, config.getString will throw an exception when the key is not present. In this case, wrapping the call in Option() will not help catch that exception: you should wrap in Try instead and convert that to an Option.
Try[String] represents a computation that can either succeed and become a Success(String), or fail and give you a Failure(thrownException). If you're familiar with Option, this is very similar to the two possibilities of Some and None, except that Failure will wrap the exception so that you know what caused the problem. The Try(someComputation) method will just do something like this for you:
try {
Success(someComputation)
} catch {
case ex: Exception => Failure(ex)
}
The second thing to consider is what you actually want to happen when there is no value. One sensible idea would be to provide a default configuration, and this is what getOrElse is for: you can't use without giving it the default value!
Here is an example:
val endpoint = Try(config.getString("endpoint"))
.toOption
.getOrElse("your_default_value")
We can do even better: now that we're using Try to catch the exception, there is no need to convert to Option if we're going to access the value right away.
val endpoint = Try(config.getString("endpoint")).getOrElse("your_default_value")
You can get a value from a map like this.
val m: Map[String, String] = Map("foo" -> "bar")
val res = m.get("foo").getOrElse("N.A")
val res2 = m.getOrElse("foo", "N.A") // same as above but cleaner
But perhaps if you want to use pattern matching:
val o: Option[String] = m.get("foo")
val res: String = o match {
case Some(value) => value
case None => "N.A"
}
Finally, a safe way to handle reading from config.
val endpoint:String = config.getString("endpoint") // this can return null
val endpoint: Option[String] = Option(config.getString("endpoint")) // this will return None if endpoint is not found
I suspect the config object might even have a method like
val endpoint: Option[String] = config.getStringOpt("endpoint")
Then you can use pattern matching to extract the value in the option. Or one of the many combinators map, flatMap, fold etc
val endPoint = Option(config.getString("endpoint"))
def callEndPoint(endPoint: String): Future[Result] = ??? // calls endpoint
endPoint match {
case Some(ep) => callEndPoint(ep)
case None => Future.failed(new NoSuchElementException("End point not found"))
}
Or
val foo = endPoint.map(callEndPoint).getOrElse(Future.failed(new NoSuchElement...))

How should I throw an exception if Some(null) is called?

I've done Some(Option(null).get) but it looks a little strange.
Updated with sample. I can't compile check that the text is not null.
object Code {
def main(args: Array[String]): Unit = {
println(computeSomething("good"))
println(computeSomething(null))
def computeSomething(text: String): Option[String] =
Some(Option(text).get).map("not null text was [" + _ + "]")
}
}
//System.out:
//
//Some(not null text was [good])
//Exception in thread "main" java.util.NoSuchElementException: None.get
// at scala.None$.get(Option.scala:347)
// at scala.None$.get(Option.scala:345)
// at Code$.computeSomething$1(ZipInputLocation.scala:13)
// at Code$.main(ZipInputLocation.scala:11)
// at Code.main(ZipInputLocation.scala)
Updated with a second sample.
object Code {
def main(args: Array[String]): Unit = {
println(computeSomething("good"))
println(computeSomething(null))
def computeSomething(text: String): String = {
require text != null
//or
//if(text == null)
// throw new RuntimeException("You broke the contract")
"not null text was [" + text + "]"
}
}
}
//System.out:
//
//not null text was [good]
//Exception in thread "main" RuntimeException:
// at Code$.computeSomething$1(ZipInputLocation.scala:13)
// at Code$.main(ZipInputLocation.scala:11)
// at Code.main(ZipInputLocation.scala)
Don't use Option.get. Instead, use the Option.apply and map on that, since it will return None for null values:
def computeSomething(text: String): Option[String] =
Option(text).map("not null text was [" + _ + "]")
Even better, if you want to disallow someone to compile code explicitly passing Some(null) at compile time, use a tool like WartMover, which has a specific rule for it that generates a compile time warning.
If I understand you correctly, you want Some(null) to throw an exception, instead of storing null as a value, correct?
Unfortunately, that's not going to happen. The only option you have is to put the creation of the Some instance inside a function and check for null explicitly. For example:
def wrapSome(s: String): Some[String] = {
if(s eq null) throw new NullPointerException("Can't have null string!")
Some(s)
}
Probably not what you wanted to hear, and not particularly useful either...
Alternatively, you could wrap the value in an Option (resulting in None, if the value is null), instead of in Some (which results in Some(null) if the value is null), and then call .get: None.get throws a NoSuchElementException. Indeed, this is exactly what you're doing in your example. (Is there a reason why you want to wrap the value explicitly with Some when that will happen automatically to non-null values wrapped in Option?)
One of the primary objectives of Option is to protect against null values. Clearly, it would depend upon what you're trying to achieve, but functional programing discourages both null values and throwing of exceptions. If you're coming from Java, this can seem very strange, at first.
A more functional approach would be something like this:
// Return None if s is null; otherwise, Some(s). Both are Option[String] values.
def computeSomething(s: String): Option[String] = Option(s)
// Use this function to create an optional string.
val os = computeSomething(x) // x is some string. Could be null.
// Provide a default value if wrapped value is null (i.e. if os is None).
val a = os.getOrElse("some default value") // a is a string, never null.
// Do something with the value if it's not null; do nothing otherwise.
os.foreach(doSomething) // Calls doSomething(x), but only if x wasn't null/os isn't None.
// Process the string to something else. If os is None, result is None too.
val len = os.map(_.length) // Returns an Option[Int], None or Some(length of x)
// etc.
There's a whole host of idioms for using Option values like this, none of which involve throwing exceptions. If you could tell us more about what you're trying to do, I'll show you the Scala/functional way of doing it.
In the meantime, here's a reworked version of your program using this idiom with the fold method:
object Code
extends App { // No need for main function! ;-)
println(computeSomething("good"))
println(computeSomething(null))
def computeSomething(text: String): String =
Option(text).fold("text was null")(t => s"not null text was [$t]")
}
// System.out:
// not null text was [good]
// text was null

Transform Int to Option[Int]

This is my code:
package net.claritysales.api.helper
import net.claritysales.api.models.UserEntity
import scala.util.Random
trait TestData {
def userInfo(
id : Long = randomLong(),
username : String = randomString(),
password : String = randomString()
) : UserEntity = {
var user : UserEntity = new UserEntity(
id = id, //Error is Long and recived Optional[Long]
username = username,
password = password)
return user}
def randomString(): String = Random.alphanumeric.take(10).mkString("")
def randomLong(): Long = Random.nextLong()
}
and UserEntity:
case class UserEntity(id: Option[Long] = None, username: String, password: String) {
require(!username.isEmpty, "username.empty")
}
and the error message: Type mismatch, expected: Option[Long], actual: Long
How do I transform Optional[Long] to Long ? Id is Optiona[Long] randomLong() and id must is Long. Thanks!
I'm not sure where exactly the issue in your code is, but I'll cover the usual ways to deal with Option. Option solves the same problem that Java's null solves, but it does so in a way that is orders of magnitude better, safer, and easier to work with. So I'm going to work with a hypothetical function here, that just received a Option[A]. The question you need to ask yourself is: what does it mean if I get a None? Scala forces you to ask this question, where making all class types implicitly nullable (as in Java) does not.
Option 1: Propagate the Error Quietly
Perhaps None indicates a failure in the place where we got the A from. Something went wrong, the random generator failed, maybe we divided by zero. Then we want to indicate that we failed. So, in this case, we change our function's return type from A to Option[A] and return a None.
In Java, this would look like this.
if (arg == null)
return null;
return doSomething(arg);
In Scala,
arg map { x => doSomething(x) }
If arg is None, then this returns None. If arg contains a value, it runs doSomething on the value and returns the result, inside an Option[A].
Option 2: None indicates Different Behavior
Perhaps None indicates, in some sense, that we want the function to behave differently. In Java, this would look something like this.
if (arg != null) {
return doSomething(arg);
} else {
return doSomethingElse();
}
In Scala, we do this in a typesafe way.
arg match {
case None => doSomethingElse()
case Some(x) => doSomething(x) // Note that x is A, not Option[A]
}
Option 3: None is Just a Default
Sometimes None just indicates that we want to use a default value. If we're adding up a bunch of numbers, and some of them might be None, we want None to equate to the numerical value 0 so that it doesn't alter our results.
In Java, we might write,
int x = 0;
if (arg != null)
x = arg;
return doSomething(x);
In Scala, we can do this more concisely with getOrElse.
doSomething(arg.getOrElse(0))
Option 4: Propagate the Error Loudly
Maybe None is really bad in our case. Perhaps it's an error in the invoked code that we're just not at all equipped to handle. Perhaps our function is just waaaay too important, and if it fails then everything else is forfeit. Then we can raise an exception. Note that this approach is not very idiomatic in Scala, so it should be used very sparingly, only when it doesn't make sense to do any of the above.
In Java,
if (arg == null)
throw new RuntimeException("Oops!");
return doSomething(arg);
In Scala,
arg match {
case None => sys.error("Oops!")
case x => doSomething(x)
}
The problem isn't that you have an Option[Int] and need an Int (as you've claimed in the title and body of your question). It's that you have an Int and need an Option[Int]. This is because userInfo takes an Int, but UserEntity takes an Option[Int].
To solve this problem, you can simply pass Some(id) as the argument.
Use get or else, i dont know in your case what give in None case
var user : UserEntity = new UserEntity(
id = id.getOrElse(0l)
username = username,
password = password)
return user}

“Convert” Option[x] to x

I working with play for Scala (2.1) and I need to convert an Option[Long] value to Long.
I know how to do the opposite, I mean:
def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value)
But in my case, I have to pass a value of Option[Long] as a type into a method that takes Long.
If you have x as Option[Long], x.get will give you Long.
First of all, your implementation of "the opposite" has some serious problems. By putting a type parameter named Long on the method you're shadowing the Long type from the standard library. You probably mean the following instead:
def toOption(value: Long): Option[Long] =
if (value == null) None else Some(value)
Even this is kind of nonsensical (since scala.Long is not a reference type and can never be null), unless you're referring to java.lang.Long, which is a recipe for pain and confusion. Finally, even if you were dealing with a reference type (like String), you'd be better off writing the following, which is exactly equivalent:
def toOption(value: String): Option[String] = Option(value)
This method will return None if and only if value is null.
To address your question, suppose we have the following method:
def foo(x: Long) = x * 2
You shouldn't generally think in terms of passing an Option[Long] to foo, but rather of "lifting" foo into the Option via map:
scala> val x: Option[Long] = Some(100L)
x: Option[Long] = Some(100)
scala> x map foo
res14: Option[Long] = Some(200)
The whole point of Option is to model (at the type level) the possibility of a "null" value in order to avoid a whole class of NullPointerException-y problems. Using map on the Option allows you to perform computations on the value that may be in the Option while continuing to model the possibility that it's empty.
As another answer notes, it's also possible to use getOrElse to "bail out" of the Option, but this usually isn't the idiomatic approach in Scala (except in cases where there really is a reasonable default value).
This method is already defined on Option[A] and is called get :
scala> val x = Some(99L)
x: Some[Long] = Some(99)
scala> x.get
res0: Long = 99
The problem is that calling get on None will throw a NoSucheElement Exception:
scala> None.get
java.util.NoSuchElementException: None.get
thus you will not gain any benefits from using an Option type.
Thus as stated before you can use getOrElse if you can provide a sensible default value or handle the Exception.
The idiomatic scala way would be using map or a for-comprehension
x map (_ + 1)
res2: Option[Long] = Some(100)
or
for (i <- x) yield i +1
res3: Option[Long] = Some(100)
Option is way to localise side-effect (your function can return empty value). And good style to lift your computation to Option (Option is Monad with map & flatMap methods).
val x = Option[Long](10)
x.map { a => a + 10 }
And extract value with manually processing of side effect:
val res = x match {
case Some(a) => s"Value: $a"
case None => "no value"
}
You need to decide what happens when the option is None. Do you provide a default value?
def unroll(opt: Option[Long]): Long = opt getOrElse -1L // -1 if undefined
unroll(None) // -> -1
You could also throw an exception:
def unroll(opt: Option[Long]): Long = opt.getOrElse(throw
new IllegalArgumentException("The option is expected to be defined at this point")
)
unroll(None) // -> exception
In case, refrain from using null, unless you have very good reasons to use it (opt.orNull).
As has already been mentioned getOrElse is probably what you're looking for in answering your question directly.
Please note also that to convert to an option you can simply:
val myOption = Option(1)
myOption will now be Some(1)
val myOption = Option(null)
myOption will now be None.

How to check for null or false in Scala concisely?

In Groovy language, it is very simple to check for null or false like:
groovy code:
def some = getSomething()
if(some) {
// do something with some as it is not null or emtpy
}
In Groovy if some is null or is empty string or is zero number etc. will evaluate to false. What is similar concise method of testing for null or false in Scala?
What is the simple answer to this part of the question assuming some is simply of Java type String?
Also another even better method in groovy is:
def str = some?.toString()
which means if some is not null then the toString method on some would be invoked instead of throwing NPE in case some was null. What is similar in Scala?
What you may be missing is that a function like getSomething in Scala probably wouldn't return null, empty string or zero number. A function that might return a meaningful value or might not would have as its return an Option - it would return Some(meaningfulvalue) or None.
You can then check for this and handle the meaningful value with something like
val some = getSomething()
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
So instead of trying to encode the "failure" value in the return value, Scala has specific support for the common "return something meaningful or indicate failure" case.
Having said that, Scala's interoperable with Java, and Java returns nulls from functions all the time. If getSomething is a Java function that returns null, there's a factory object that will make Some or None out of the returned value.
So
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
... which is pretty simple, I claim, and won't go NPE on you.
The other answers are doing interesting and idiomatic things, but that may be more than you need right now.
Well, Boolean cannot be null, unless passed as a type parameter. The way to handle null is to convert it into an Option, and then use all the Option stuff. For example:
Option(some) foreach { s => println(s) }
Option(some) getOrElse defaultValue
Since Scala is statically type, a thing can't be "a null or is empty string or is zero number etc". You might pass an Any which can be any of those things, but then you'd have to match on each type to be able to do anything useful with it anyway. If you find yourself in this situation, you most likely are not doing idiomatic Scala.
In Scala, the expressions you described mean that a method called ? is invoked on an object called some. Regularly, objects don't have a method called ?. You can create your own implicit conversion to an object with a ? method which checks for nullness.
implicit def conversion(x: AnyRef) = new {
def ? = x ne null
}
The above will, in essence, convert any object on which you call the method ? into the expression on the right hand side of the method conversion (which does have the ? method). For example, if you do this:
"".?
the compiler will detect that a String object has no ? method, and rewrite it into:
conversion("").?
Illustrated in an interpreter (note that you can omit . when calling methods on objects):
scala> implicit def any2hm(x: AnyRef) = new {
| def ? = x ne null
| }
any2hm: (x: AnyRef)java.lang.Object{def ?: Boolean}
scala> val x: String = "!!"
x: String = "!!"
scala> x ?
res0: Boolean = true
scala> val y: String = null
y: String = null
scala> y ?
res1: Boolean = false
So you could write:
if (some ?) {
// ...
}
Or you could create an implicit conversion into an object with a ? method which invokes the specified method on the object if the argument is not null - do this:
scala> implicit def any2hm[T <: AnyRef](x: T) = new {
| def ?(f: T => Unit) = if (x ne null) f(x)
| }
any2hm: [T <: AnyRef](x: T)java.lang.Object{def ?(f: (T) => Unit): Unit}
scala> x ? { println }
!!
scala> y ? { println }
so that you could then write:
some ? { _.toString }
Building (recursively) on soc's answer, you can pattern match on x in the examples above to refine what ? does depending on the type of x. :D
If you use extempore's null-safe coalescing operator, then you could write your str example as
val str = ?:(some)(_.toString)()
It also allows you to chain without worrying about nulls (thus "coalescing"):
val c = ?:(some)(_.toString)(_.length)()
Of course, this answer only addresses the second part of your question.
You could write some wrapper yourself or use an Option type.
I really wouldn't check for null though. If there is a null somewhere, you should fix it and not build checks around it.
Building on top of axel22's answer:
implicit def any2hm(x: Any) = new {
def ? = x match {
case null => false
case false => false
case 0 => false
case s: String if s.isEmpty => false
case _ => true
}
}
Edit: This seems to either crash the compiler or doesn't work. I'll investigate.
What you ask for is something in the line of Safe Navigation Operator (?.) of Groovy, andand gem of Ruby, or accessor variant of the existential operator (?.) of CoffeeScript. For such cases, I generally use ? method of my RichOption[T], which is defined as follows
class RichOption[T](option: Option[T]) {
def ?[V](f: T => Option[V]): Option[V] = option match {
case Some(v) => f(v)
case _ => None
}
}
implicit def option2RichOption[T](option: Option[T]): RichOption[T] =
new RichOption[T](option)
and used as follows
scala> val xs = None
xs: None.type = None
scala> xs.?(_ => Option("gotcha"))
res1: Option[java.lang.String] = None
scala> val ys = Some(1)
ys: Some[Int] = Some(1)
scala> ys.?(x => Some(x * 2))
res2: Option[Int] = Some(2)
Using pattern matching as suggested in a couple of answers here is a nice approach:
val some = Option(getSomething())
some match {
case Some(theValue) => doSomethingWith(theValue)
case None => println("Whoops, didn't get anything useful back")
}
But, a bit verbose.
I prefer to map an Option in the following way:
Option(getSomething()) map (something -> doSomethingWith(something))
One liner, short, clear.
The reason to that is Option can be viewed as some kind of collection – some special snowflake of a collection that contains either zero elements or exactly one element of a type and as as you can map a List[A] to a List[B], you can map an Option[A] to an Option[B]. This means that if your instance of Option[A] is defined, i.e. it is Some[A], the result is Some[B], otherwise it is None. It's really powerful!