Scala,将本地定义的函数传递到列表中?

Scala,将本地定义的函数传递到列表中?,scala,programming-languages,Scala,Programming Languages,我不明白下面的代码片段为什么afterDelay(0){…},本地定义的函数可以存储到议程中?有人能帮我理解run函数中的afterDelay(0){…}吗 abstract class Simulation { type Action = () => Unit case class WorkItem(time: Int, action: Action) private var curtime = 0 def currentTime: Int = curtime

我不明白下面的代码片段为什么
afterDelay(0){…}
,本地定义的函数可以存储到议程中?有人能帮我理解
run
函数中的
afterDelay(0){…}

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()
  }
}
抽象类模拟{
类型Action=()=>Unit
案例类工作项(时间:Int,动作:动作)
私有变量curtime=0
定义当前时间:Int=curtime
私有变量议程:List[WorkItem]=List()
专用def插入(ag:List[WorkItem],item:WorkItem):List[WorkItem]={
如果(ag.isEmpty | | item.time单位){
val项=工作项(当前时间+延迟,()=>块)
议程=插入(议程,项目)
}
私有def next(){
(议程:@未选中)匹配{
案例项::rest=>
议程=休息
curtime=item.time
项目.行动()
}
}
def运行(){
后延迟(0){
println(“***模拟已开始,时间=”+
当前时间+“***”)
}
而(!agenda.isEmpty)next()
}
}
相当于以下内容:

afterDelay(0)({
    println(...)
})
调用函数
afterDelay
,并将新的
工作项
)添加到列表中,而不是函数本身。参数
块:=>Unit
是一个“按名称参数”
(参见第4.6.1节):用作参数的表达式隐式转换为“无参数方法”(无需首先求值),每当访问方法内的变量时将调用该方法(无需
()

在这种情况下,即当调用由
()=>块产生的函数时:它在
项中被调用。action()
在新的
工作项添加到列表后的某个点发生(并且
afterDelay
返回)

如果它写为(接受函数参数,而不是按名称/thunk):

然后需要通过传入函数调用它:

或者,另一种语法仍然是
()=>单元的函数,但可以避免使用外括号:

afterDelay(0) { () => // need a function
    println(...)
} 

按名称参数从SLS 4.6.1中提取:

值参数的类型可以通过
=>
预先确定,例如
x:=>T
。这样一个参数的类型就是无参数方法类型
=>T
。这表明相应的参数不会在函数应用时求值,而是在函数中的每次使用时求值。也就是说,参数是使用名称调用进行计算的

相当于以下内容:

afterDelay(0)({
    println(...)
})
调用函数
afterDelay
,并将新的
工作项
)添加到列表中,而不是函数本身。参数
块:=>Unit
是一个“按名称参数”
(参见第4.6.1节):用作参数的表达式隐式转换为“无参数方法”(无需首先求值),每当访问方法内的变量时将调用该方法(无需
()

在这种情况下,即当调用由
()=>块产生的函数时:它在
项中被调用。action()
在新的
工作项添加到列表后的某个点发生(并且
afterDelay
返回)

如果它写为(接受函数参数,而不是按名称/thunk):

然后需要通过传入函数调用它:

或者,另一种语法仍然是
()=>单元的函数,但可以避免使用外括号:

afterDelay(0) { () => // need a function
    println(...)
} 

按名称参数从SLS 4.6.1中提取:

值参数的类型可以通过
=>
预先确定,例如
x:=>T
。这样一个参数的类型就是无参数方法类型
=>T
。这表明相应的参数不会在函数应用时求值,而是在函数中的每次使用时求值。也就是说,参数是使用名称调用进行计算的


您将afterDelay定义为一个。这意味着它有两个参数列表。在scala中,可以用
{…}
替换围绕参数列表的括号
(…)
。在第二个参数列表中,您使用的是。每次在函数中使用这些参数时,都会对其进行求值。一个很好的例子是。
“按名称调用”参数通常用于定义您自己的控制结构

def do(until: Int)(body: => Unit) {
  body
  if (until > 1) do(until - 1)(body)
}

do(0)(println("test"))
do(5)(println("test2"))

这是do-until的一个示例。它将打印一次
test
,并打印五次
test2

您将afterDelay定义为。这意味着它有两个参数列表。在scala中,可以用
{…}
替换围绕参数列表的括号
(…)
。在第二个参数列表中,您使用的是。每次在函数中使用这些参数时,都会对其进行求值。一个很好的例子是。
“按名称调用”参数通常用于定义您自己的控制结构

def do(until: Int)(body: => Unit) {
  body
  if (until > 1) do(until - 1)(body)
}

do(0)(println("test"))
do(5)(println("test2"))

这是do-until的一个示例。它将打印一次
test
和五次
test2

“这里是调用函数结果()=>块的时候。这里发生在afterDelay函数返回后的某个点(在item.action()上)。”--您是说在item.action()期间调用afterDelay吗?我觉得println(“***模拟已启动,time=“+currentTime+”***”)即afterDelay的()=>Unit参数在item期间被调用。action()否,
afterDelay
在被调用时被调用。它创建一个新的函数对象(成为
WorkItem.action
),它关闭
参数(将其绑定在一个闭包中)。然后创建新的
工作项
,并对其进行排队;调用新函数时(通过
item.action()
其他地方