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

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

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...))

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}

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

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

Check for None in Scala Option type isEmpty method

I'm using the Option Type's isEmpty method to check if there is no value. I do not want to use the case match as in my situation, I just want to check if there is None as I would throw an error to the caller. But the isEmpty method fails even though the value is None.
Here is what I tried!
val questionOption = Question.getQuestionForQuestionId(userExam.get.examId, currQuesId + 1)
if(questionOption.isEmpty) {
Left(Failure(FailureCode.NO_DATA_FOUND, "Cannot get next exam question you tampered your cookie or cookie is lost.... >> TODO... modify the exception message"))
}
It is not getting inside the if condition. I tried to do a println on the questionOption and it prints None. So wondering why I'm not getting inside the if condition.
From the comment under the question, the real problem emerges:
val questionOption = Question.getQuestionForQuestionId(userExam.get.examId, currQuesId + 1)
if(questionOption.isEmpty) {
Left(Failure(FailureCode.NO_DATA_FOUND, "Cannot get next exam question you tampered your cookie or cookie is lost.... >> TODO... modify the exception message"))
}
By itself, if returns type Unit so that your statement is returning nothing useful. If you want to return something you need to add in either an else which then returns the least upper bound of the result types. Hence
>>> val yo = if(1 != 0) 4
yo: Unit
>>> val ya = if(1 != 0) Left(1) else Right("got it")
ya: Either[Int, String]
You could just do a boolean check to see of the value is None and throw the error to the caller if it is, otherwise continue processing:
scala> val o: Option[Any] = None
o: Option[Any] = None
scala> println(o == None)
true
scala> println(o != None)
false
But maybe a better way to accomplish what you're trying to do, alert the caller of the error or continue processing, would be to use Scala's Try idiom to handle errors.

How to make this first-not-null-result function more elegant/concise?

getFirstNotNullResult executes a list of functions, until one of them returns a not null value.
How to implement getNotNullFirstResult more elegantly/concise?
object A {
def main(args: Array[String]) {
println(test());
}
def test(): String = {
getFirstNotNullResult(f1 _ :: f2 _ :: f3 _ :: Nil);
}
def getFirstNotNullResult(fs: List[() => String]): String = {
fs match {
case head::tail =>
val v = head();
if (v != null) return v;
return getFirstNotNullResult(tail);
case Nil => null
}
}
// these would be some complex and slow functions; we only want to execute them if necessary; that is, if f1() returns not null, we don't want to execute f2 nor f3.
def f1(): String = { null }
def f2(): String = { "hello" }
def f3(): String = { null }
}
I like Rex's answer, but your question brings up so many things, I'd like to expand on it, to add:
Using Scala's Option/Some/None classes to clarify what should be returned when no match is found. Your example returned null, Rex's threw an exception. Using Option makes it immediately clear that we will return a match or "None".
Use type parameters so you don't have to operate just on functions that return a String.
Here's the code:
object A extends App {
def getFirstNNWithOption[T](fs: List[() => Option[T]]): Option[T] = fs
.view //allows us to evaluate your functions lazily: only evaluate as many as it takes to find a match
.flatMap(_()) //invoke the function, discarding results that return None
.headOption // take the first element from the view - returns None if empty
def f1 = { println("f1"); None }
def f2 = Some("yay!")
def f3 = { println("f2"); None }
println(getFirstNNWithOption(List(f1 _, f2 _, f3 _)))
}
Note that when this code runs, f2 never prints, demonstrating that, thanks to the .view call, we evaluate the minimum number of functions before returning a match.
Note that callers of this method now must consider the fact that a match might not be found: instead of returning T, we return Option[T]. In our case above, it would return Some("yay"). When all functions return None, the return value would be None. No more NullPointerExceptions when you mistake a null for an actual match!
def getFirstNN(fs: List[() => String]): String = fs.iterator.map(_()).find(_ ne null).get
You'll probably want the type passed into getFirstNotNullResult to be a Stream[String] instead of List[() => String] and construct it something like:
Stream.cons(f1, Stream.cons(f2, Stream.cons(f3, Stream.empty)))
Then getFirstNotNullResult changes to be:
fs.filter(_ != null).headOption
Which will also mean that it should really return Option[String] as well, as you can't guarantee that something will be non-null.
As suggested, the reason why I suggest a Stream is that it only evaluates the "tail" of the Stream on demand. So if getFirstNotNullResult finds that the first element is not null then the second parameter to the first Stream.cons call is never actually executed.