161

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!

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144
  • 5
    Another way to use case classes with by-name parms, is to put them in a secondary parameter list, e.g. `case class Scheduled(time: Int)(callback: => Unit)`. This works because the secondary parameter list is not exposed publicly, nor is it included in the generated `equals`/`hashCode` methods. – nilskp Mar 05 '15 at 17:48
  • A few more interesting aspects regarding the differences between by-name parameters and 0-arity functions are found in [this question](http://stackoverflow.com/q/32802104/302793) and the answer. It's actually what I was looking for when I found this question. – lex82 Jan 31 '16 at 13:41

4 Answers4

253

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).

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • I may have to be the first to down-vote after two years. Somebody is wondering about case => syntax on Christmas, and I can't recommend this answer as canonical and complete! What is the world coming to? Maybe the Mayans were just off by a week. Did they figure in leap years correctly? Daylight savings? – som-snytt Dec 26 '12 at 01:57
  • 1
    @som-snytt Well, the question didn't ask about `case ... =>`, so I didn't mention it. Sad but true. :-) – Daniel C. Sobral Dec 26 '12 at 13:03
  • 1
    @Daniel C. Sobral could you please explain " That is a block of code, not a literal." part. So what is the exact different between two? – nish1013 Sep 04 '13 at 10:39
  • 3
    @nish1013 A "literal" is a value (the integer `1`, the character `'a'`, the string `"abc"`, or the function `() => println("here")`, for some examples). It can be passed as argument, stored in variables, etc. A "block of code" is a syntactical delimitation of statements -- it isn't a value, it can't be passed around, or anything like that. – Daniel C. Sobral Sep 04 '13 at 13:06
  • @DanielC.Sobral many thanks for your respond."A "block of code" is a syntactical delimitation of statements -- it isn't a value, it can't be passed around" Please refer to breakable function call in below link's example. https://github.com/nraychaudhuri/scalainaction/blob/master/chap02/breakable.scala So isn't it pass around a "block of code" ? – nish1013 Sep 04 '13 at 13:17
  • @nish1013 No, it isn't. See pass-by-name at the beginning of my answer. – Daniel C. Sobral Sep 05 '13 at 02:55
  • what's the difference between `Unit => Type` and `() => Type`? – Incerteza Mar 17 '14 at 17:54
  • 3
    @Alex That's the same difference as `(Unit) => Type` vs `() => Type` -- the first is a `Function1[Unit, Type]`, while the second is a `Function0[Type]`. – Daniel C. Sobral Mar 17 '14 at 21:22
39
case class Scheduled(time : Int, callback :  => Unit)

The case modifier makes implicit val out of each argument to the constructor. Hence (as someone noted) if you remove case you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it created val callback instead of morphing into lazy val callback.

When you change to callback: () => Unit now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored in val callback so there's no problem.

The easiest way to get what you want (Scheduled(40, println("x") ) where a call-by-name parameter is used to pass a lambda) is probably to skip the case and explicitly create the apply that you couldn't get in the first place:

class Scheduled(val time: Int, val callback: () => Unit) {
    def doit = callback()
}

object Scheduled {
    def apply(time: Int, callback: => Unit) =
        new Scheduled(time, { () => callback })
}

In use:

scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled@5eb10190

scala> Scheduled(1234, println("x")).doit
x
Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • 3
    Why not keep it a case-class and just override the default apply? Also, the compiler cannot translate a by-name to a lazy val, since they have inherently different semantics, lazy is at-most-once and by-name has at-every-reference – Viktor Klang Dec 28 '10 at 11:56
  • @ViktorKlang How can you override a case class's default apply method? http://stackoverflow.com/questions/2660975/scala-is-it-possible-to-override-default-case-class-constructor – Sawyer Jul 20 '12 at 07:54
  • object ClassName { def apply(…): … = … } – Viktor Klang Jul 20 '12 at 10:54
  • Four years later and I realize that the answer I selected only answered the question in the title, not the one I actually had (which this one does answer). – Michael Lorton Apr 11 '15 at 07:14
1

In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:

class Scheduled(time: Int, cb: => Unit) {
  private def runCb = cb
}

object Scheduled {
  def apply(time: Int, cb: => Unit) = {
    val instance = new Scheduled(time, cb)
    Thread.sleep(time*1000)
    instance.runCb
  }
}

In REPL, we can get something like this:

scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b

Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.

Jeff Xu
  • 43
  • 4
0

I do it this way (just don't want to break apply):

case class Thing[A](..., lazy: () => A) {}
object Thing {
  def of[A](..., a: => A): Thing[A] = Thing(..., () => a)
}

and call it

Thing.of(..., your_value)