score:12
I'm going to answer the title question for more coverage. Unit
gets special treatment in a few places, more than what's going on in those code examples. In part, this is because Unit
is a figment of the compiler that reduces to void
on the JVM.
Value Discarding
This is the most surprising case for people. Any time the expected type of some value is Unit
, the compiler tacks on Unit
at the end of the expression that produces the value, according to the SLS - 6.26.1:
If
ee
has some value type and the expected type isUnit
,ee
is converted to the expected type by embedding it in the term{ ee; () }
.
Thus,
def foo3(): Unit = "foo"
becomes:
def foo3(): Unit = { "foo" ; () }
Likewise,
def foo: Future[Unit] = save(customer1).map(_ => save(customer2))
becomes:
def foo: Future[Unit] = save(customer1).map(_ => { save(customer2); () })
The benefit of this is that you don't need to have the last statement of a method have the type Unit
if you don't want to. This benefit is small however, because if the last statement of your method that returns Unit
isn't a Unit
, that usually indicates an error, which is why there is a warning flag for it (-Ywarn-value-discard
).
In general, I find it better to return a more specific type, if possible, rather than returning Unit
. For example, when saving to a database, you may be able to return the saved value (perhaps with a new ID, or something).
Value Class
Unit
is a value class created by the Scala compiler, with only one instance (if it needs to be instantiated as a class at all). This means that it compiles down to the primitive void
on the JVM, unless you treat it as a class (e.g. ().toString
). It has its very own section in the specification, SLS - 12.2.13.
Empty Block Type
From the SLS - 6.11, the default type of an empty block is assumed to be Unit
. For example:
scala> val x = { }
x: Unit = ()
Equals
When comparing a Unit
to another Unit
(which must be the same object, since there is only one), the compiler will emit a special warning to inform you something is likely wrong in your program.
scala> ().==(())
<console>:12: warning: comparing values of types Unit and Unit using `==' will always yield true
().==(())
^
res2: Boolean = true
Casting
You can cast anything to a Unit
, as the compiler will optimize it away (though it's unclear to me if value discarding takes over after type inference).
object Test {
val a = "a".asInstanceOf[Unit]
val b = a
}
becomes:
object Test extends Object {
def <init>(): Test.type = {
Test.super.<init>();
()
};
private[this] val a: scala.runtime.BoxedUnit = scala.runtime.BoxedUnit.UNIT;
<stable> <accessor> def a(): Unit = ();
private[this] val b: scala.runtime.BoxedUnit = scala.runtime.BoxedUnit.UNIT;
<stable> <accessor> def b(): Unit = ()
}
score:14
rethab's answer already gave you the link to the spec; just let me add that
- you can disable this (make the warning an error) through the
-Xfatal-warnings
compiler flag - you'll get better messages with the
-Ywarn-value-discard
flag; forfoo3
the compiler warning will be the more informativediscarded non-Unit value
Note that this "any to Unit" conversion is compiler magic, so neither -Yno-predef
or -Yno-imports
will disable it; you do need the flags above. I consider this being part of the language specification an error, as if for some reason you want this dubious behavior you can just add something like
implicit def any2Unit(a: Any): Unit = ()
while opting-out of it requires an unsupported (by definition, as it breaks the specification) compiler flag.
I also recommend wartremover, where you have this and much more.
score:15
As written in the scala language specification chapter 6.26.1:
Value Discarding
If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }.
Source: stackoverflow.com
Related Query
- What special rules does the scala compiler have for the unit type within the type system
- Why does the Scala compiler fail with missing parameter type for filter with JavaSparkContext?
- What is the efficient way to create Spark DataFrame in Scala with array type columns from another DataFrame that does not have an array column?
- What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?
- Should I use Unit or leave out the return type for my scala method?
- What does the 'optimise' scala compiler flag do?
- What advantages does Scala have over Java for concurrent programming?
- Why does Scala choose the type 'Product' for 'for' expressions involving Either and value definitions
- What is the Scala type mapping for all Spark SQL DataType
- What return type should a Scala method have if it can throw/return errors but has Unit return type?
- What instance of CanBuildFrom does the Scala compiler find out?
- Why does Scala compiler for .NET ignore the meaning of val?
- What does the new scala Dynamic type do?
- Why does the Scala API have two strategies for organizing types?
- What mechanisms does Scala have for generics and wildcards compared to Java?
- what should a scala implicit macro have to return to tell the compiler "forget my result, continue your search"
- How does the scala compiler locate the positions for variance annotation
- Why does the Scala compiler give "value registerKryoClasses is not a member of org.apache.spark.SparkConf" for Spark 1.4?
- What is the best way to assert for a scala method whose return type is Future[Unit]
- Why does the compiler infer incorrectly return type for Future.sequence declaration in function?
- How do I have the scala compiler infer one type from another?
- What are the rules for when trait/class type parameters take precedence vs method type parameters
- In Scala, why does a type annotation must follow for the function parameters ? Why does the compiler not infer the function parameter types?
- What are the way/s of telling scala compiler that type TableQuery[T] can map to somthing has the attribute id
- Why does the Scala compiler recognize a generic type twice
- What is the Unit Type Behavior in Scala
- What is the Scala implementation of Hashcode for objects of type Any?
- Scala what does the "def function = Type {" mean?
- How does one write a scala unit test for the "filter" function?
- What suport does Scala have for class/object level access control?
More Query from same tag
- Scala type members variance
- How to inject multi dependencies when I use "Reader monad" for dependency injection?
- how can i refactor this using functional programming ideas
- Configure scaladoc to include extension methods
- How to split a Play application into several parts
- scala _.validate error message
- Future[Option] in Scala for-comprehensions
- Upgrading to Scala 2.13 giving scalaoptions error
- In Scala, why can't I explicitly use a parameter type here?
- How to translate type projections into PDTs in implicits?
- Spark Scala - Rolling window with merge
- How do I create a 2d int array with different lengths in scala?
- How to make isInfoEnabled disabled in Log4J XML configuration
- Simplest way to sum two Lists in Scala?
- Getting name of parameterized class in scala using shapeless
- Count elements of array A in array B with Scala
- spec2 tests failing for scalatra app with swagger support
- Linearly reading a multi-dimensional array obeying dimensional sub-sectioning
- How to override Java's ArrayList's addAll(Collection<? extends E> c) method in Scala? Naive approach does not compile
- Spark files not found in cluster deploy mode
- Curried type "does not take type parameters"
- Definition of Nil List in Scala
- Adding Sparse Vectors 3.0.0 Apache Spark Scala
- How override loglevel from application.conf in sbt tests?
- Exclude a specific implicit from a Scala project
- Build Actions for all classes that mixin a trait
- UDF to check is non zero vector, not working after CountVectorizer through spark-submit
- Mockito verify fails when method takes a function as argument
- Merge non-null fields in two case classes
- Why are type checks and type casts considered poor style in Scala?