Skip to content

传值调用

Call by value · CBV

仅当实参先求值为值后才进行函数体替换的求值策略。

条目类型
模型

形式陈述

传值调用(call-by-value)要求函数应用的运算位置先求值为函数、实参位置再求值为值,之后才执行 β-替换。在 λ 演算中可写为值规则

(λx.t)vt[x:=v]

以及由小步语义的求值上下文 E::=[]EtvE 指定的左到右求值。这里“值”的定义属于语言本身,可能包括 λ 抽象、常量、构造器值等。传值调用不要求在 λ 抽象体内部预先归约。

直觉

传值调用把实参计算完成后再交给函数,因此函数体中每次使用参数都只是在使用一个已经得到的值。它与现实机器的栈式调用和严格语言的直觉接近,也让副作用顺序较易预测。关键不是“复制值”还是“传地址”的实现细节,而是函数体开始前是否必须完成实参求值;语言仍可用引用、对象或共享指针表示这个值。由于会求值即使未被函数使用的参数,传值可能在本可忽略的发散或异常上停住。

例子与边界

Ω=(λx.xx)(λx.xx)。项 (λx.0)Ω 在传值调用下必须先求值 Ω,因而发散;传名调用可直接替换并得到 0。另一方面,(λx.x+x)(1+2) 会先把 1+2 算成 3,再在函数体中使用两次 3,不会重复执行加法。

边界在于“传值”不等于“没有共享副作用”。若值是可变对象的引用,把引用作为值传入仍允许函数修改同一对象。求值顺序也不是由 call-by-value 一词完全决定:语言还必须规定多个实参是从左到右、从右到左还是未指定顺序求值。

推论与应用

多数严格函数式语言和命令式语言采用某种传值调用核心语义。求值上下文可精确规定其顺序;CBV CPS 变换把顺序翻译成显式续延,CEK 抽象机则用环境和 ar/fn 帧执行同一策略。递归编码也必须尊重这一顺序:直接运行 Y 会在自应用处发散,传值适用的 $Z$ 组合子通过额外 λ 延迟递归展开。

类型安全证明通常以调用值的值形式引理和 β 规则为中心。与传名调用比较同一程序,可揭示严格性分析、惰性求值和副作用语义的差异。

参考资料
  • Robert Harper, Practical Foundations for Programming Languages, 2nd ed., Cambridge University Press, 2016,Parts I–XVIII。
  • Gordon D. Plotkin, A Structural Approach to Operational Semantics, DAIMI FN-19, 1981; reprinted 2004,Full report。
关系图谱7 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

并列辨析