1

I was going through Learning Concurrency With Scala It had a following piece of Code.

package week_parallel.week1.SC_Book

import scala.collection.mutable

object SyncPoolArgs extends App {
  private val tasks = mutable.Queue[() => Unit]()
  object Worker extends Thread {
    setDaemon(true)
    def poll() = tasks.synchronized {
      while (tasks.isEmpty) tasks.wait()
      tasks.dequeue()
    }
    override def run() = while (true) {
      val task = poll()
      task()
    }
  }
  Worker.start()
  def asynchronous(body: =>Unit) = tasks.synchronized {
    tasks.enqueue(() => body)
    tasks.notify()
  }

  def sum(x: Int, y:Int) = {println("USING SUM")
    x+y}

  asynchronous { log("Hello ") }
  asynchronous { log("World!") }
  asynchronous { sum(4,5) }
  Thread.sleep(500)
}

So, my question is if we have tasks of type function that takes no arguments and returns nothing, why does tasks.enqueue(() => body) put sum in the queue, shouldn't it check that the body method signature is wrong in case of sum.

Also, I am particularly unable to grasp how does tasks.enqueue(() => body) confine to the private val tasks = mutable.Queue[() => Unit]() type?

Ishan Bhatt
  • 9,287
  • 6
  • 23
  • 44
  • Possible duplicate of [What's the difference between => , ()=>, and Unit=>](https://stackoverflow.com/questions/4543228/whats-the-difference-between-and-unit) – Dmytro Mitin Apr 08 '19 at 12:13

1 Answers1

3

I think you may be confused by the declaration

body: => Unit

This means that body is a pass-by-name parameter of type Unit. This does not mean that body is a function that returns Unit, which would be body: () => Unit.

"pass by name" means that the expression that is passed to body will not be evaluated until the value is required. When it is evaluated, it will return Unit.

Since body is of type Unit, the expression () => body has type () => Unit which is what is required.

In this case the actual value of body is sum(4,5) which is type Int, but Int is compatible with Unit so there is no error.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Tim
  • 26,753
  • 2
  • 16
  • 29
  • 2
    pass-by-value param or pass-by-name? – Ishan Bhatt Apr 08 '19 at 09:44
  • 3
    It's pass-by-name. – Dmytro Mitin Apr 08 '19 at 09:56
  • Many apologies for my error, it is, of course, "pass by name". Thanks to @DmytroMitin for fixing my error. – Tim Apr 08 '19 at 10:31
  • @DmytroMitin, I was checking Alvin's tutorial https://alvinalexander.com/scala/fp-book/how-to-use-by-name-parameters-scala-functions In which he defines following def timer(blockOfCode: => theReturnType), That indicates the return type.. Any ideas on that? – Ishan Bhatt Apr 08 '19 at 11:33
  • @Tim, I was checking Alvin's tutorial https://alvinalexander.com/scala/fp-book/how-to-use-by-name-parameters-scala-functions In which he defines following def timer(blockOfCode: => theReturnType), That indicates the return type.. Any ideas on that? – Ishan Bhatt Apr 08 '19 at 11:33
  • @IshanBhatt What is your question? – Dmytro Mitin Apr 08 '19 at 11:36
  • In the answer as @Tim points out body:=>Unit , body is type of Unit, but in the post by alvin it looks like blockOfCode(body) is something that returns theReturnType. So which one is true? – Ishan Bhatt Apr 08 '19 at 11:41
  • 1
    @IshanBhatt You can call type as you want `def timer(blockOfCode: => BlaBlaType)`. In some sense types `=> A`, `() => A`, `Unit => A` are similar. Inside method `def foo(body: => A)` `body` is of type `A`, inside method `def bar(body: () => A)` `body()` is of type `A`, inside method `def baz(body: Unit => A)` `body(())` is of type `A`. But in type system of Scala types `=> A` (by-name parameter of type `A`), `() => A` (function of zero arguments to type `A`), `Unit => A` (function of single argument of type `Unit` to `A`) are different. – Dmytro Mitin Apr 08 '19 at 12:03
  • In languages without by-name (lazy) calculations (like Javascript) lambdas is way 'for poors' to emulate those. – Dmytro Mitin Apr 08 '19 at 12:04