What's the difference between => , ()=>, and Unit=>

scala

Solution

Call-by-Name: => Type

The `=> Type` notation stands for call-by-name, which is one of the many ways parameters can be passed. If you aren't familiar with them, I recommend taking some time to read that wikipedia article, even though nowadays it is mostly call-by-value and call-by-reference.

What it means is that what is passed is substituted for the value name inside the function. For example, take this function:

def f(x: => Int) = x * x

If I call it like this

var y = 0
f { y += 1; y }

Then the code will execute like this

{ y += 1; y } * { y += 1; y }

Though that raises the point of what happens if there's a identifier name clash. In traditional call-by-name, a mechanism called capture-avoiding substitution takes place to avoid name clashes. In Scala, however, this is implemented in another way with the same result -- identifier names inside the parameter can't refer to or shadow identifiers in the called function.

There are some other points related to call-by-name that I'll speak of after explaining the other two.

0-arity Functions: () => Type

The syntax `() => Type` stands for the type of a `Function0`. That is, a function which takes no parameters and returns something. This is equivalent to, say, calling the method `size()` -- it takes no parameters and returns a number.

It is interesting, however, that this syntax is very similar to the syntax for a anonymous function literal, which is the cause for some confusion. For example,

() => println("I'm an anonymous function")

is an anonymous function literal of arity 0, whose type is

() => Unit

So we could write:

val f: () => Unit = () => println("I'm an anonymous function")

It is important not to confuse the type with the value, however.

Unit => Type

This is actually just a `Function1`, whose first parameter is of type `Unit`. Other ways to write it would be `(Unit) => Type` or `Function1[Unit, Type]`. The thing is... this is unlikely to ever be what one wants. The `Unit` type's main purpose is indicating a value one is not interested in, so doesn't make sense to receive that value.

Consider, for instance,

def f(x: Unit) = ...

What could one possibly do with `x`? It can only have a single value, so one need not receive it. One possible use would be chaining functions returning `Unit`:

val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g

Because `andThen` is only defined on `Function1`, and the functions we are chaining are returning `Unit`, we had to define them as being of type `Function1[Unit, Unit]` to be able to chain them.

Sources of Confusion

The first source of confusion is thinking the similarity between type and literal that exists for 0-arity functions also exists for call-by-name. In other words, thinking that, because

() => { println("Hi!") }

is a literal for `() => Unit`, then

{ println("Hi!") }

would be a literal for `=> Unit`. It is not. That is a block of code, not a literal.

Another source of confusion is that `Unit` type's value is written `()`, which looks like a 0-arity parameter list (but it is not).

Problem

I'm trying to represent a function that takes no arguments and returns no value (I'm simulating the setTimeout function in JavaScript, if you must know.) ``` case class Scheduled(time : Int, callback : => Unit) ``` doesn't compile, saying " `val' parameters may not be call-by-name" ``` case class Scheduled(time : Int, callback : () => Unit) ``` compiles, but has to be invoked strangely, instead of ``` Scheduled(40, { println("x") } ) ``` I have to do this ``` Scheduled(40, { () => println("x") } ) ``` What also works is ``` class Scheduled(time : Int, callback : Unit => Unit) ``` but is invoked in an even-less-sensible way ``` Scheduled(40, { x : Unit => println("x") } ) ``` (What would a variable of type Unit be?) What I want of course is a constructor that can be invoke the way I would invoke it if it were an ordinary function: ``` Scheduled(40, println("x") ) ``` Give baby his bottle!

Original source

Related problems