15

In Scala, when I want to set something to None, I have a couple of choices: using None or Option.empty[A].

Should I just pick one and use it consistently, or are there times when I should be using one over the other?

Example:

scala> def f(str: Option[String]) = str
f: (str: Option[String])Option[String]

scala> f(None)
res0: Option[String] = None

scala> f(Option.empty)
res1: Option[String] = None
Jonik
  • 80,077
  • 70
  • 264
  • 372
cdmckay
  • 31,832
  • 25
  • 83
  • 114

5 Answers5

19

I would stick to None whenever possible, which is almost always. It is shorter and widely used. Option.empty allows you to specify the type of underlying value, so use it when you need to help type inference. If the type is already known for the compiler None would work as expected, however while defining new variable

var a = None

would cause infering a as None.type which is unlikely what you wanted.

You can then use one of the couple ways to help infer what you need

@ var a = Option.empty[String]
a: Option[String] = None
@ var a: Option[String] = None
a: Option[String] = None
@ var a = None: Option[String] // this one is rather uncommon
a: Option[String] = None

Another place when compiler would need help:

List(1, 2, 3).foldLeft(Option.empty[String])((a, e) => a.map(s => s + e.toString))

(Code makes no sense but just as an example) If you were to omit the type, or replace it with None the type of accumulator would be infered to Option[Nothing] and None.type respectively.

And for me personally this is the place I would go with Option.empty, for other cases I stick with None whenever possible.

Łukasz
  • 8,555
  • 2
  • 28
  • 51
5

Short answer use None if talking about a value for example when passing parameter to any function, use Option.empty[T] when defining something.

var something = Option.empty[String] means something is None for now but can become Some("hede") in the future. On the other hand var something = None means nothing. you can't reassign it with Some("hede") compiler will be angry: found : Some[String] required: None.type So, this means None and Option.empty[T] are not alternatives. You can pass None to any Option[T] but you can't pass Some[T] to None.type

Hüseyin Zengin
  • 1,216
  • 11
  • 23
  • But if you assign to None with declaring the type it's equal. x: Option[String] = None. Empty let you set a type. – idan ahal Jan 17 '22 at 12:33
1

Following are worksheet exports using Scala and Scalaz .

def f(str: Option[String]) = str              //> f: (str: Option[String])Option[String]
f(None)                                       //> res1: Option[String] = None
var x:Option[String]=None                     //> x  : Option[String] = None
x=Some("test")
x                                             //> res2: Option[String] = Some(test)
x=None
x      

Now using Scalaz ,

def fz(str: Option[String]) = str             //> fz: (str: Option[String])Option[String]
fz(none)                                      //> res4: Option[String] = None
var xz:Option[String]=none                    //> xz  : Option[String] = None
xz=some("test")
xz                                            //> res5: Option[String] = Some(test)
xz=none
xz         

Note that all the statements evaluate in the same way irrespective of you use None or Option.Empty. How ?

As you can see it is important to let Scala know of your intentions via the return type in the var x:Option[String]=None statement. This allows a later assignment of a Some. However a simple var x=None will fail in later lines because this will make the variable x resolve to None.type and not Option[T].

I would think that one should follow the convention. For assignments i would go for the var x:Option[String]=None option. Also whenever using None it is good to use a return type (in this case Option[String]) so that the assignment does not resolve to None.type.
Only in cases where i have no way to provide a type and i need some assignment done will i go for Option.empty

Som Bhattacharyya
  • 3,972
  • 35
  • 54
  • I can't think of any sense in which "both of them resolve to Option[Nothing]". And as other answers show, they _can't_ always be used interchangeably. – Alexey Romanov Mar 28 '16 at 09:26
  • Yes you are correct i was talking about Scalaz but the meaning was not clear. Thanks. I have updated the answer. – Som Bhattacharyya Mar 28 '16 at 09:33
  • 2
    Even there, you actually get `none[A]: Option[A]`. This is the same type as `Option.empty`, not `Option[Nothing]`; that's _why_ it can be used interchangeably. You only get `Option[Nothing]` if it's used without type argument in a position where Scala can't infer it, same as with `Option.empty`. – Alexey Romanov Mar 28 '16 at 12:18
  • Now i am confused. I see in worksheet Scalaz's `none` and `Option.empty` both resolve to `Option[Nothing]` . Are you suggesting something else? – Som Bhattacharyya Mar 28 '16 at 12:25
  • "if it's used without type argument in a position where Scala can't infer it". You normally wouldn't write `val x = none`, but `val x = none[String]` (or use `none` where the compiler expects a specific type, such as `f(none)` in the question). – Alexey Romanov Mar 28 '16 at 12:49
  • agree and updated the answer with current understanding. :) Thanks. – Som Bhattacharyya Mar 29 '16 at 05:55
1

Given that Option[A].empty simply returns None:

/** An Option factory which returns `None` in a manner consistent with
 *  the collections hierarchy.
 */
def empty[A] : Option[A] = None

I'd say:

  1. As you said, be consistent throughout the codebase. Making it consistent would mean that programmers entrying your codebase have one less thing to worry about. "Should I use None or Option.empty? Well, I see @cdmckay is using X throughout the call base, I'll use that as well"
  2. Readability - think what conveys the point you want the most. If you were to read a particular method, would it make more sense to you if it returned an empty Option (let's disregard for a moment the fact that the underlying implementation is simply returning None) or an explicit None? IMO, I think of None as a non-existent value, as the documentation specifies:

    /** This case object represents non-existent values.
     *
     *  @author  Martin Odersky
     *  @version 1.0, 16/07/2003
     */
    
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • Downvoting, as it doesn't answer the question (whether sometimes one is preferred for reasons other than consistency). Furthermore, the point about an empty option making more or less sense than an explicit None seems cryptic to me. – Sergey Orshanskiy Jul 13 '17 at 19:52
0

As everyone else pointed out, it's more a matter of personal taste, in which most of the people prefer None, or, in some cases, you explicitly need to put the type because the compiler can't infer.

This question can be extrapolated to other Scala classes, such as Sequences, Map, Set, List and so on. In all of them you have several ways to define empty state. Using sequence:

  • Seq()
  • Seq.empty
  • Seq.empty[Type]

From the 3, I prefer the second, because:

  • The first (Seq()) is error prone. It looks like if someone wanted to create a sequence and forgot to add the elements
  • The second (Seq.empty) is explicit about the desire of having an empty sequence
  • While the third (Seq.empty[Type]) is as explicit as the second, it is more verbose, so I don't use typically
pedrorijo91
  • 7,635
  • 9
  • 44
  • 82