I learn Scala for some time and can't clearly understand the usage of Option. It helps me to avoid null checks when I chain functions (according to docs). That's clear for me :)
Next I see that Option can be kind of indicator for developer that null value is possible here and it must be handled. Is it true? If yes should I use Option whereever it's possible? For example
class Racer {
val car = new Car()
}
I have Racer class and I'm sure that car field can't be null (because it's constant and get a value when I create Racer instance). No need for Option here.
class Racer {
var car = new Car()
}
Here I make it so that the car can change. And it's possible for someone to assign null to car. Should I use Option here? If yes I notice that all my class fields are candidates for Option. And my code looks like this
class Racer {
var car: Option[Car] = None
var currentRace: Option[Race] = None
var team: Option[Team] = None
...
}
Does it look good? For me it seems kind of Option overusing.
def foo(): Result = {
if( something )
new Result()
else
null
}
I have a method which can return null. Should I return Option instead? Should I always do it if it's possible for method to return null?
Any thoughts about it would be helpful. Thanks in advance!
My question is similiar to Why option but I think it's not the same. It's more about when, not why. :)
Put options are in the money when the stock price is below the strike price at expiration. The put owner may exercise the option, selling the stock at the strike price. Or the owner can sell the put option to another buyer prior to expiration at fair market value.
Definition of option (Entry 1 of 2) 1 : an act of choosing hard to make an option between such alternatives. 2a : the power or right to choose : freedom of choice He has the option to cancel the deal. b : a privilege of demanding fulfillment of a contract on any day within a specified time.
As per theory, buying option has a limited liability where a trader's loss is restricted to the premium paid while selling option has unlimited liability. But due to the new rules, even a buyer of option has to bear unlimited liability in case she could not square off positions before expiry and option becomes an ITM.
You should avoid null
as much as possible in Scala. It really only exists for interoperability with Java. So, instead of null
, use Option
whenever it's possible that a function or method can return "no value", or when it's logically valid for a member variable to have "no value".
With regard to your Racer
example: Is a Racer
really valid if it doesn't have a car
, currentRace
and team
? If not, then you shouldn't make those member variables options. Don't just make them options because it's theoretically possible to assign them to null
; do it only if logically you consider it a valid Racer
object if any of those member variables has no value.
In other words, it's best to pretend as if null
doesn't exist. The use of null
in Scala code is a code smell.
def foo(): Option[Result] = if (something) Some(new Result()) else None
Note that Option
has many useful methods to work with.
val opt = foo()
// You can use pattern matching
opt match {
case Some(result) => println("The result is: " + result)
case None => println("There was no result!")
}
// Or use for example foreach
opt foreach { result => println("The result is: " + result) }
Also, if you want to program in the functional style, you should avoid mutable data as much as possible, which means: avoid the use of var
, use val
instead, use immutable collections and make your own classes immutable as much as possible.
When it comes to functional programming in Scala, Option
is much preferable than null
since it is type-safe and plays nice with other constructs in the functional paradigm.
Especially, you can easily write idiomatic code using high-order functions on Option
. This Scala Option Cheat Sheet is a helpful read on the topic.
While Option
can makes your class definition look verbose, the alternative is to not know when you need to test whether a variable is defined. I think that in your example, if your class were immutable (all the fields were val
s), you would not need so many Option
s.
For your method foo
, if you return null, you need to document it and the client needs to read that documentation. Then the client will write a bunch of code like:
val result = foo(x)
if (result != null) {
println(result)
}
If instead you define foo
to return an Option[Result]
, the type system forces the client to handle the possibility of an undefined result. They also have the full power of the collections classes.
result foreach println
An additional advantage of using the collections method with an Option
instead of testing for null
is that if your method is extended to a multi-element collection (such as a List
), you might not need to change your code at all. For example, you might initially assume your Racer
can only have a single crew, so you define val crew: Option[Crew]
and you might test if the crew is older than 30 with crew.forall(_.age > 30).getOrElse(false)
. Now if you changed the definition to val crew: List[Crew]
your old code would still compile and now you would check if all of your crew members are over 30.
Sometimes you need to deal with null
because libraries you are using may return it. For example, when you get a resource, you might get a null
result. Fortunately, it is easy to defensively wrap results so they are transformed into an option.
val resource = Option(this.getClass.getResource("foo"))
If getResource
returned null
then resource
equals None
, and otherwise it is a Some[URL]
. Cool!
Unfortunately, Option
is likely to have some overhead because it involves an extra object creation. However, that overhead is minimal compared to a null pointer exception!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With