Skip to content

变量绑定

Variable binding · Binding occurrence

把变量的使用出现关联到作用域内声明,并区分自由出现、绑定出现与遮蔽。

条目类型
定义

形式陈述

变量绑定是在抽象语法的出现位置之间建立的关系。一个绑定器声明变量名并确定作用域;作用域内每个同名使用出现,若没有先遇到更内层的同名绑定器,就由该声明绑定。没有关联到任何绑定器的出现称为自由出现。

以无类型 λ 项

t::=xλx.ttt

为例,λx.t 中的 λx 绑定 t 内未被遮蔽的 x。自由变量集合递归定义为

FV(x)={x},FV(tu)=FV(t)FV(u),FV(λx.t)=FV(t){x}.

FV(t)=,称 t闭项;否则它是开项。这里集合记录自由变量名,绑定关系则细化到具体出现位置:同一个名字的两次出现可能分别指向不同声明。

程序语言中的函数参数、let 声明、模式变量、类型变量和异常处理器都可按“绑定器—作用域—使用出现”分析。每种构造必须单独规定作用域;例如非递归 let x=e_1 in e_2x 通常只绑定 e2,而递归绑定还会覆盖 e1

直觉

变量名像连线旁的标签,绑定结构才说明一次使用取哪个声明的值。内层声明会遮蔽外层同名声明;只要改名同时更新它所绑定的全部出现,连线不变,项的绑定含义也不变。

把语法画成树时,可以想象每个变量使用节点都有一条回边指向其声明节点。普通树边给出作用域嵌套,回边给出名称解析。文本搜索只看标签,看不到回边,因而会在重命名、替换或宏展开时制造捕获。

例子与边界

λx.λy.xz 中,x 由外层 λ 绑定,y 被声明却没有使用,z 自由,因此

FV(λx.λy.xz)={z}.

λx.(λx.x)x 更能展示遮蔽:内层函数体中的 x 指向内层声明,最后一个 x 指向外层声明。三个相同字符涉及两个绑定器,不能按名字全局合并。

实线表示抽象语法树,蓝色虚线表示绑定关系;内层函数体的 x 指向内层 λx,应用右侧的 x 指向外层 λx。

闭项与值也不等同。λx.x 是闭项且在常见 λ 求值语义中是值;(λx.x)(λy.y) 同样闭合,却仍可归约。反过来,某些语义允许开 λ 抽象 λx.y 作为值,尽管其中 y 自由。闭合性描述名称是否都有声明,值描述语义是否把项视为结果。

本页默认词法作用域:绑定由源语法嵌套决定。动态作用域改按运行时调用链寻找声明,同一函数体中的名字可能随调用者改变含义,不能直接套用上述静态回边。未经卫生处理的宏也可能把展开后落入作用域的名字意外重新绑定。

推论与应用

绑定结构是α-等价无捕获替换的共同基础。前者忽略绑定标签而保留回边,后者移动子树时保持自由出现不被新绑定器接管。

编译器的名称解析把表面名字解析成符号表条目,随后可用唯一标识符或 de Bruijn 索引表示绑定。环境语义则把自由变量的解释交给环境;函数值若需保存定义处环境,就形成闭包。这些表示改变名称管理方式,不改变词法绑定应满足的关系。

类型系统把同一结构推广到类型变量和上下文。类型环境记录变量可用的类型或类型方案,运行时环境记录值;二者都处理作用域,却不能混作同一种映射。依赖类型与模块系统还会让绑定跨越项、类型与命名空间。

参考资料
  • Robert Harper, Practical Foundations for Programming Languages, 2nd ed., Cambridge University Press, 2016, Chapters 1–4。
  • Benjamin C. Pierce, Types and Programming Languages, MIT Press, 2002, Chapters 5–6。
  • Andrew M. Pitts, Nominal Sets: Names and Symmetry in Computer Science, Cambridge University Press, 2013, Chapters 1–3。
关系图谱52 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

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