How do I return a None in scala? - scala

I've been learning Scala recently and one of the things I've seen most is talk about how you shouldn't use null but instead use None. I've had to resort to using null some times because I don't understand how None works exactly.
My biggest problem is when I have methods which return an object say:
def func: SomeObjType = {
if(something)
new SomeObjType
else
null or None
If I return null, it works perfectly well but whenever I try to return None it doesn't work.
What am I doing wrong?

def func : Option[SomeObjType] = {
if (cond)
Some(new SomeObjType)
else
None
}

None, as you can see in the scaladocs here, is an extension of Option. It only checks out if your return type is expected to be an Option.
You can alter your code as Marth suggests, but in practice, Option makes for rather ugly code if it is used constantly.
If you are dealing with Lists, returning a Nil would be quite suitable.
I personally just return Nothing, just because it sounds cool, and because its autoinheritence of every class (including SomeObjType) makes it simple to deal with.
The following article is a very useful piece about these absentee-types in Scala:
A Post About Nothing, by Matt Malone
And really, with all these alternatives, there's little appeal for a lower-case null. It even pales in the face of the aesthetically-pleasing Null. Quirks aside, null and Null can be used more or less interchangeably.

Related

(Scala) Am I using Options correctly?

I'm currently working on my functional programming - I am fairly new to it. Am i using Options correctly here? I feel pretty insecure on my skills currently. I want my code to be as safe as possible - Can any one point out what am I doing wrong here or is it not that bad? My code is pretty straight forward here:
def main(args: Array[String]): Unit =
{
val file = "myFile.txt"
val myGame = Game(file) //I have my game that returns an Option here
if(myGame.isDefined) //Check if I indeed past a .txt file
{
val solutions = myGame.get.getAllSolutions() //This returns options as well
if(solutions.isDefined) //Is it possible to solve the puzzle(crossword)
{
for(i <- solutions.get){ //print all solutions to the crossword
i.solvedCrossword foreach println
}
}
}
}
-Thanks!! ^^
When using Option, it is recommended to use match case instead of calling 'isDefined' and 'get'
Instead of the java style for loop, use higher-order function:
myGame match {
case Some(allSolutions) =>
val solutions = allSolutions.getAllSolutions
solutions.foreach(_.solvedCrossword.foreach(println))
case None =>
}
As a rule of thumb, you can think of Option as a replacement for Java's null pointer. That is, in cases where you might want to use null in Java, it often makes sense to use Option in Scala.
Your Game() function uses None to represent errors. So you're not really using it as a replacement for null (at least I'd consider it poor practice for an equivalent Java method to return null there instead of throwing an exception), but as a replacement for exceptions. That's not a good use of Option because it loses error information: you can no longer differentiate between the file not existing, the file being in the wrong format or other types of errors.
Instead you should use Either. Either consists of the cases Left and Right where Right is like Option's Some, but Left differs from None in that it also takes an argument. Here that argument can be used to store information about the error. So you can create a case class containing the possible types of errors and use that as an argument to Left. Or, if you never need to handle the errors differently, but just present them to the user, you can use a string with the error message as the argument to Left instead of case classes.
In getAllSolutions you're just using None as a replacement for the empty list. That's unnecessary because the empty list needs no replacement. It's perfectly fine to just return an empty list when there are no solutions.
When it comes to interacting with the Options, you're using isDefined + get, which is a bit of an anti pattern. get can be used as a shortcut if you know that the option you have is never None, but should generally be avoided. isDefined should generally only be used in situations where you need to know whether an option contains a value, but don't need to know the value.
In cases where you need to know both whether there is a value and what that value is, you should either use pattern matching or one of Option's higher-order functions, such as map, flatMap, getOrElse (which is kind of a higher-order function if you squint a bit and consider by-name arguments as kind-of like functions). For cases where you want to do something with the value if there is one and do nothing otherwise, you can use foreach (or equivalently a for loop), but note that you really shouldn't do nothing in the error case here. You should tell the user about the error instead.
If all you need here is to print it in case all is good, you can use for-comprehension which is considered quite idiomatic Scala way
for {
myGame <- Game("mFile.txt")
solutions <- myGame.getAllSolutions()
solution <- solutions
crossword <- solution.solvedCrossword
} println(crossword)

Throwaway values - what is the best practice in Scala?

WartRemover's NonUnitStatements requires that statements that aren't returning unit must have an assignment. OK, but sometimes we have to use annoying Java APIs that both mutate and return a value, and we don't actually hardly ever care about the returned value.
So I end up trying this:
val _ = mutateSomething(foo)
But if I have multiple of these, _ is actually a legit val that has been assigned to, so I cannot reassign. Wartremover also rightly will admonish for gratuitous var-usage, so I can't just do var _ =.
I can do the following (need the ; to avoid Scala thinking it is a continue definition unless I add a full newline everytime I do this).
;{val _ = mutateSomething(foo)}
Is there a better way?
My general thoughts about linting tools is that you should not jump through hoops to satisfy them.
The point is to make your code better, both with fewer bugs and stylistically. But just assigning to var _ = does not achieve this. I would first be sure I really really don't care about the return value, not even asserting that it is what I expect it to be. If I don't, I would just add a #SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements")) and maybe a comment about why and be done with it.
Scala is somewhat unique in that it's a somewhat opinionated language that also tries to integrate with another not-so-opinionated language. This leads to pain points. There are different philosophies to dealing with this, but I tend to not sweat it, and just be aware of and try to isolate the boundaries.
I'm posting an answer, but the real credit goes to Shane Delmore for pointing this out:
def discard(evaluateForSideEffectOnly: Any): Unit = {
val _: Any = evaluateForSideEffectOnly
() //Return unit to prevent warning due to discarding value
}
Alternatively (or see #som-snytt's comments below):
#specialized def discard[A](evaluateForSideEffectOnly: A): Unit = {
val _: A = evaluateForSideEffectOnly
() //Return unit to prevent warning due to discarding value
}
Then use it like: discard{ badMutateFun(foo) }.
Unlike the ;{ val _ = ... } solution, it looks way better, and also works in the beginning of a block without needing to alter style (a ; can't come at the start of a block, it must come after a statement).

Scala Try's toOption method returns Some(null)

Should Success (the child of Try) return Some(null) when converting it to Option?
E.g.
Try(null).toOption in scala 2.11.7 returns Some(null)
Success's toOption method implemented simply by returning Some(value).
Why doesn't it return None when converting Try to option using toOption method if underlying value of try is null?
Here's the source of toOption from Scala 2.11.7:
def toOption: Option[T] = if (isSuccess) Some(get) else None
I agree with Bruno that this is confusing, it should probably read
def toOption: Option[T] = if (isSuccess) Option(get) else None
Absolutely not. Option is NOT a null-safety container, it is a Functor, a Monad, and a Collection of size 0 or 1. It can contain null, just like a List can. Just like Try can.
Although it is often used for null-safety, due to Option.apply converting null to None and general Scala best practices avoiding the use of null.
Furthermore, the language does not allow you to define a type parameter that is not null, so Try[A] is implicitly saying that A can be null, according to the language, and Option[A] means that the value can be null too. It is only by convention that A usually is not null.
It would be incorrect to convert a Try containing a null value to None, as it would be truncating the range of A implicitly. Some[A](null) is valid, for any A that is an AnyRef
The language design is at odds with its own best practices here. The language does next-to-nothing to help enforce it. Null is a valid bottom type. An ideal world would allow users to define non-nullable types and the compiler to track null introduction and elimination, which would eliminate these sorts of surprises.
Note that if we made toOption convert null values to None, then the following equality would not hold:
val t: Try = ...
t.toOption.map(f) == t.map(f).toOption
which could lead to other surprises in your code when seemingly harmless refactorings were done, perhaps some minor for comprehension rearrangement that suddenly changes a result from None to something else because of the order of operations that appear to be order independent.
Scala should have had two types for this, one which is a null safety container (Maybe ?) and breaks the law above in general, because it can not contain null, and another that is just like today's Option, but without Option.apply -- an optional value.
Option.apply is the odd man out, and should be removed, IMO.
For example, consider the following, all of which evaluate to Some(null):
Some(Some(null)).flatten
List("a", null).find(s != "a")
List(null, "blah").headOption
Try(null).toOption
Option is used all across the collections library to be a collection of size 0 or 1, and not a null safety device. It makes no sense for these to return None as long as Option is a primarily collection of size 0 or 1, and not a 'non-null' wrapper. If Option was such a thing, then it would not be used across the collections library to represent optional values, such as with find and headOption above.
If anyone truly wants to get into the weeds on the topic, have fun:
https://groups.google.com/forum/#!msg/scala-internals/1DXdknjt9pY/_moEcbNd4noJ
5 years ago I thought it was a great idea to get rid of Some(null). Now I would propose getting rid of Option.apply and creating a different type for non-nullness. Call it Maybe. Then one could have Try.toMaybe along side Try.toOption

Scala: Try .getOrElse vs if/else

I'm a fairly new Scala developer. I am an experienced Java developer and so far I've been enjoying Scala's simplicity. I really like the functional constructs and quite often they force you to write cleaner code. However recently I noticed due to comfort and simplicity I end up using constructs I wouldn't necessarily use in Java and would actually be considered a bad practice e.g.
private def convertStringToSourceIds(value: String) : Seq[Integer] = {
Try(value.split(",").toSeq.map(convertToSourceId(_))).getOrElse(Seq())
}
The same code snippet can be written as
private def convertStringToSourceIds(value: String) : Seq[Integer] = {
if(value!=null) value.split(",").toSeq.map(convertToSourceId(_)) else Seq()
}
A part of me realizes that the Try/getOrElse block is designed with Options in mind but quite often it makes code more readable and handles cases you might have missed (which of course isn't always a good thing).
I would be interested to know what is the opinion of an experienced Scala developer on the matter.
I am not claiming any "experience" title but I much prefer your second construct for a few reasons
Throwing an exception (an NPE in this case) is expensive and best avoided; it should remain just that, exceptional
if are expressions in Scala, which avoids declaring "dangling" variables to hold the result of the test (just like ternary operators). Alternatively the match..case construct provides for very readable code.
I would personally return an Option[Seq[Integer]] to "pass back" the information that the values was null and facilitate further chaining of your function.
Something like
private def convertStringToSourceIds(value: String) : Option[Seq[Integer]] = value match {
case null => None
case _ => Some(value.split(",").map(convertToSourceId(_)))
}
note 1: not sure you need the toSeq
note 2: for good or bad, looks a bit Haskellish
The combination of Scala + FP makes it almost doubly certain you will get different opinions :)
Edit
Please read comments below for additional reasons and alternatives, i.e,
def convertStringToSourceIds(value: String): Option[Array[String]] = Option(value).map(_.split(",").map(convertToSourceId(_)))
If you can, use Options instead of null to show when a value is missing.
Assuming that you can't use Options, a more readable way to handle this could be
private def convertStringToSourceIds(value: String) : Seq[Integer] = value match {
case null => Seq();
case s => s.split(",").toSeq.map(convertToSourceId(_));
}

Scala proper use of break to return

I have the following code:
private def hasRole(role: String): Boolean = {
var hasRole = false;
if(getUserDetails.isDefined){
// getAuthorities returns java.util.Collection<GrantedAuthority>
val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities
// Wrap the collection is a Scala class
val authoritiesWrapper = JCollectionWrapper.apply(authorities);
for(authority <- authoritiesWrapper.iterator){
if(authority.getAuthority == role){
hasRole = true;
scala.util.control.Breaks.break
}
}
}
hasRole
}
The question is, is scala.util.control.Breaks.break the correct way toreturn when I've found the role? Doesn't look right to me.
If you want to use breakable, you need to do it like so:
import scala.util.control.Breaks._
breakable {
for (i <- 0 to 10000) { if (i>3) break }
}
But if you find yourself doing that often, you're probably not using the collections library to its full extent. Try instead
authoritiesWrapper.iterator.exists(_.getAuthority == role)
Also, in the example you gave, you could also
if (authority.getAuthority == role) return true
When to choose which? In general, you should use the control-flow options in the collections library if you can. They generally are the fastest and clearest. Wait, fastest--why is that? Both break and return (from within a for or other context that requires a closure--basically anything but if and while and match) actually throw a stackless exception which is caught; in the break case it's caught by breakable and in the return case it's caught by the method. Creating a stack trace is really slow, but even stackless exceptions are kind of slow.
So using the correct collections method--exists in this case--is the best solution.
The question is, is scala.util.control.Breaks.break the correct way
toreturn when I've found the role? Doesn't look right to me.
Since your just looking for the first instance of authority.getAuthority == role you can use find which does exactly that and is the idiomatic way to do this.
authoritiesWrapper.iterator.find(authority => authority.getAuthority == role)
or more concisely
authoritiesWrapper.iterator.find(_.getAuthority == role)
These return an Option type which you can get the value of authority from if it exists.
I can only offer you generalities, but I hope it's at least a little helpful...
Unfortunately, your sample code contains free identifiers, so it's not possible for me to understand what it does without guessing and assuming.
You're thinking about the problem wrong. What is it you're doing here? You're finding a element of a collection. Use the library! It has all manner of such things off-the-shelf.
When it comes to dealing with Option[Something] the preferred approach is to map over it. If it's a None, you get a None out. If it's Some(thing) then the function you pass to map will be applied to thing and the result will be Some(what-your-function-returned-for-thing).
Alternatively, and what newcomers to Scala often find more palatable, you can use pattern matching on an Option to effectively distinguish the None case from the Some(thing) case.
When it comes to dealing with Java libraries, it's best to push the conversions from and to the Java collections to the very periphery of your code and keep the bulk of your code idiomatic Scala using native Scala collections.
The same goes for nulls coming from Java. Turn them into Option at the earliest possible time. As a convenience, the Option(thing) factory will turn a thing that is null into a None and wrap a non-null thing in a Some
Addendum
The upshot is that you really should not be using these control flow mechanisms in this code. They're all based on exceptions (other than return) and are rather at odds with Scala's emphasis on using functional programming. The library supports a clean, succinct, efficient implementation of the essetial logic you're trying for. Don't go against the grain like this.
Why not just return true and return false replacing hasRole?
Thanks Everyone, based on #Rex Kerr answer I now have this:
private def hasRole(role: String): Boolean = {
var hasRole: Boolean = false;
if(getUserDetails.isDefined){
val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities
val authoritiesWrapper = JCollectionWrapper.apply(authorities);
hasRole = authoritiesWrapper.iterator.exists(_.getAuthority == role)
}
hasRole
}
which seems to look and feel right. I'm using exists to see of the role exists in the collection and then returning that result. By default false is returned if the user is not defined (not logged in).
Please comment if this is still not perfect.