I have not understood the following code snippet why afterDelay(0) {...}, a locally defined function can be stored into agenda? Can someone help me understand the afterDelay(0) {...} in the run function?
abstract class Simulation {
type Action = () => Unit
case class WorkItem(time: Int, action: Action)
private var curtime = 0
def currentTime: Int = curtime
private var agenda: List[WorkItem] = List()
private def insert(ag: List[WorkItem], item: WorkItem): List[WorkItem] = {
if (ag.isEmpty || item.time < ag.head.time) item :: ag
else ag.head :: insert(ag.tail, item)
}
def afterDelay(delay: Int)(block: => Unit) {
val item = WorkItem(currentTime + delay, () => block)
agenda = insert(agenda, item)
}
private def next() {
(agenda: @unchecked) match {
case item :: rest =>
agenda = rest
curtime = item.time
item.action()
}
}
def run() {
afterDelay(0) {
println("*** simulation started, time = "+
currentTime +" ***")
}
while (!agenda.isEmpty) next()
}
}
Is equivalent to the following:
The function
afterDelayis invoked a newWorkItem(item) is added to the list, not the function itself. The parameterblock: => Unitis a “By-Name Parameter” (see the Scala Language Specification section 4.6.1): the expression used as the argument is implicitly converted into a “parameterless method” (without being evaluated first) that will be invoked whenever the variable inside the method is accessed (no()required).In this case that is when the function resulting from
() => blockis invoked: it is invoked atitem.action()which occurs at some point after the newWorkItemis added to the list (andafterDelayreturns).If it was written as (taking in a function paramater, not a by-name/thunk):
Then it would need to be invoked passing in a function:
Or, alternative syntax, still a function of
() => Unit, but the outside parenthesis can be avoided:Extract from the SLS, 4.6.1 By-Name Parameters: