def f(x:Int => Unit):Unit = 1 :7: warning: a pure expression does ...">

In Scala, why can I use the "Unit" type here?

Codes below:

scala> def f(x:Int => Unit):Unit = 1
<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
       def f(x:Int => Unit):Unit = 1
                                   ^
f: (x: Int => Unit)Unit

scala> f(_=>2);
<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
              f(_=>2);
                   ^

scala> f(_=>List(1,2));

      

All three expressions above worked in the REPL (with some warnings), but they look a little confusing.

In the first expression, the return type f

Unit

, which is a subtype AnyVal

but not a supertype Int

, so I can't figure out why 1

it can be used as a return value.

In the second expression _=>2

also used 2

instead Unit

as a return value, which is contrary to the definition.

The third expression _=> List(1,2)

even uses the List

subtype AnyRef

as its return value, but the REPL still doesn't complain about that.

Does anyone have any idea why Unit

can tolerate no subtype type conversion here? Thank!

+2


source to share


3 answers


Scala will automatically insert ()

(singleton value Unit

) in this case to do the type checking operation. So you have the equivalent:

def f(x:Int => Unit):Unit = { 1; () }

      

This is called "dropping a value" in Scala. From the spec :



Value Drop

If it e

is of some value type and the expected type Unit

, e

converts to the expected type by inserting it into the member{ e; () }

As with many programming languages, this simply means "throwing out" the return value of the expression. This allows you to create a type method Unit

that only uses the side effects of the expression.

+12


source


Flag Implicit Conversions in SLS



ValueDiscarding. If e is of some value type and the expected type is Unit, e is converted to the expected type by inserting it into the {e; ()} member.

+2


source


In addition to Ben Reich's answer:

Conceptually, in Scala, a type Unit

is a supertype of any other type. Therefore, every value, including Int

, is assigned Unit

. Effectively, if used as the return type of a method, the compiler will throw out the result value by providing the JVM / Java method void

.

Nothing

is the exact opposite, by the way: conceptually it is a subtype of any other type. Since no instance Nothing

exists, no instance of any other type can be made compatible with Nothing

.

Java is void

somehow an incomplete mix of both of them.

0


source







All Articles