What is the proper way to explicitly return the Unit
type from a method, using ()
or Unit
? It appears to me that both work in all cases I've tried myself.
For context, this often occurs if I'm writing a method with side effects and returns Unit
that calls another method, which also performs side effects but returns some value instead of Unit
. e.g.
def effectAndReturn(): String = {
val msg = "Hello, SO"
println(msg)
msg
}
def doEffect(): Unit = {
val _ = effectAndReturn()
() // `Unit` also works here
}
From my understanding ()
is the only value of type Unit
that exists. Returning the token Unit
in doEffect()
is referencing the Unit
companion object; I'm confused how this would return a value as there's not even an apply
method defined on it. Returning the companion object for a given abstract class's type isn't valid as a return value as far as I know.
Plugging these into a Scala REPL is also interesting
scala> val parenUnit = ()
parenUnit: Unit = ()
scala> parenUnit
// Returns blank line
scala> val wordUnit = Unit
wordUnit: Unit.type = object scala.Unit
scala> wordUnit
res1: Unit.type = object scala.Unit
scala> res1
res2: Unit.type = object scala.Unit
()
is simply a Unit
value, whereas Unit
gives back a type, which doesn't make sense to me as no other companion objects do this as far as I can tell. My guess is that the compiler handles Unit
in a particular and unique way compared to any other type, but how exactly?
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value — Unit.VALUE. This value does not have to be returned explicitly: fun printHello(name : String?) : Unit { if (name != null) print("Hello, $name!")
In Scala we use the Unit return type to indicate "no return value." This is a "void" function.
The Unit is Scala is analogous to the void in Java, which is utilized as a return type of a functions that is used with a function when the stated function does not returns anything.
So, we have:
Unit
type
()
which is of type Unit
Unit
companion object which causes the confusion. It is not of type Unit
. It is of type Unit.type
(its own singleton type). However... Scala automatically implicitly converts everything to Unit
and that's why you can use it where Unit
type is expected.TLDR: Use ()
Suppose we have two methods in a class called TestUnit
:
class TestUnit {
def foo(): Unit = 2217
def bar(): Int = 1478
}
Let's look at its bytecode:
// access flags 0x1
public foo()V
L0
LINENUMBER 4 L0
SIPUSH 2217
POP
RETURN // returns void
L1
LOCALVARIABLE this Lunit/TestUnit; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public bar()I
L0
LINENUMBER 5 L0
SIPUSH 1478
IRETURN // returns integer because it is declared in method
L1
LOCALVARIABLE this Lunit/TestUnit; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
My assumption is - the Scala compiler just put RETURN
instruction (which returns void) in every method where Unit
is declared as returning type. (you can look listings here)
So you can return any type in doEffect()
. But as @ghik said, it's better to use ()
.
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