ksc0pe
ksc0pe

Reputation: 113

Usage of () vs Unit when creating a function to call a parameterless constructor

I came across a situation recently where I needed to create a function to call a parameterless constructor. The following code demonstrates

class NoNumber() {}
val create : Unit => NoNumber = Unit => new NoNumber()
val nn = create()

This code compiles and creates a new instance of NoNumber and assigns it to nn as expected. However, there are a couple of things I wasn't expecting.

my first attempt (which doesn't compile), was as follows

val create : Unit => NoNumber = () => new NoNumber()

Why is it that Unit works and () does not work in the above example? I was under the impression that () was the one and only instance of Unit and as such the () seems to make the most sense.

Secondly I see the following warning when compiling the code

Warning:(3, 22) Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. signature: Function1.apply(v1: T1): R given arguments: after adaptation: Function1((): Unit) lazy val nn = create()

What does this mean and how should the code be changed to remove the warning?

Thanks

Upvotes: 1

Views: 236

Answers (1)

Michael Zajac
Michael Zajac

Reputation: 55569

Unit => A and () => A are not the same thing.

Unit => A is syntactic sugar for Function1[Unit, A], a function with a single argument of Unit that returns A. You're confusing the type Unit with the value () that has type Unit. i.e., you cannot say:

scala> val a: () = ()
<console>:1: error: '=>' expected but '=' found.
       val a: () = ()
             ^

() => A is syntactic sugar for Function0[A], a parameter-less function that returns A. They are similar, but not quite the same.


As for the warning with this:

val create : Unit => NoNumber = Unit => new NoNumber()

If you were to have val nn = create, then nn would actually be a function, Unit => NoNumber. When you have:

val nn = create()

You are actually are doing:

val nn = create.apply(())

Confusing, yes? Hence, the deprecation warning. The former is simply passing () to a Function1[Unit, NoNumber], but it looks awfully like a Function0. What you probably want is:

val create : () => NoNumber = () => new NoNumber()

Upvotes: 7

Related Questions