By Malvolio


2010-12-28 02:14:58 8 Comments

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!

3 comments

@Jeff Xu 2018-09-14 20:55:15

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.

@Daniel C. Sobral 2010-12-28 11:32:36

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

@som-snytt 2012-12-26 01:57:34

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?

@Daniel C. Sobral 2012-12-26 13:03:05

@som-snytt Well, the question didn't ask about case ... =>, so I didn't mention it. Sad but true. :-)

@nish1013 2013-09-04 10:39:24

@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?

@Daniel C. Sobral 2013-09-04 13:06:44

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

@nish1013 2013-09-04 13:17:34

@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. github.com/nraychaudhuri/scalainaction/blob/master/chap02/… So isn't it pass around a "block of code" ?

@Daniel C. Sobral 2013-09-05 02:55:37

@nish1013 No, it isn't. See pass-by-name at the beginning of my answer.

@アレックス 2014-03-17 17:54:27

what's the difference between Unit => Type and () => Type?

@Daniel C. Sobral 2014-03-17 21:22:00

@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].

@Ben Jackson 2010-12-28 02:49:44

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 = [email protected]

scala> Scheduled(1234, println("x")).doit
x

@Viktor Klang 2010-12-28 11:56:39

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

@Sawyer 2012-07-20 07:54:44

@ViktorKlang How can you override a case class's default apply method? stackoverflow.com/questions/2660975/…

@Viktor Klang 2012-07-20 10:54:59

object ClassName { def apply(…): … = … }

@Malvolio 2015-04-11 07:14:57

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

Related Questions

Sponsored Content

14 Answered Questions

[SOLVED] Difference between object and class in Scala

  • 2009-11-18 11:21:58
  • Steve
  • 175617 View
  • 596 Score
  • 14 Answer
  • Tags:   scala class object

16 Answered Questions

[SOLVED] What is the difference between Scala's case class and class?

4 Answered Questions

[SOLVED] What's the difference between Unit and Nothing?

  • 2012-11-24 09:08:39
  • Reactormonk
  • 15999 View
  • 55 Score
  • 4 Answer
  • Tags:   scala

12 Answered Questions

[SOLVED] What is the difference between a var and val definition in Scala?

  • 2009-11-24 16:57:39
  • Derek Mahar
  • 103890 View
  • 289 Score
  • 12 Answer
  • Tags:   scala

1 Answered Questions

[SOLVED] Passing function as block of code between curly braces

  • 2014-03-26 18:47:04
  • Piotr Sobczyk
  • 12643 View
  • 34 Score
  • 1 Answer
  • Tags:   scala syntax

6 Answered Questions

[SOLVED] Difference between case object and object

  • 2011-03-11 08:45:58
  • Wojciech Durczyński
  • 50823 View
  • 216 Score
  • 6 Answer
  • Tags:   scala

11 Answered Questions

[SOLVED] What is the difference between self-types and trait subclasses?

2 Answered Questions

[SOLVED] Scala case class private constructor isn't private

  • 2016-06-29 10:53:02
  • Artem Malinko
  • 1847 View
  • 7 Score
  • 2 Answer
  • Tags:   scala

1 Answered Questions

[SOLVED] How can I specify multiple constructors in the case class?

  • 2015-11-01 15:42:13
  • Finkelson
  • 6402 View
  • 4 Score
  • 1 Answer
  • Tags:   scala

3 Answered Questions

[SOLVED] Use Class Variables As Constants In Scala

  • 2009-04-29 16:32:17
  • Onorio Catenacci
  • 21318 View
  • 20 Score
  • 3 Answer
  • Tags:   syntax scala

Sponsored Content