OCaml 的局部变量、返回值与区域

原标题OCaml Local Variables, Return Values and Regions

通过一个实例,了解 `local_` 和 `exclave_` 如何让函数接收局部值,并在调用方区域中返回局部结构。

频道
Jane Street
发布
2024年1月23日
视频
12:52
阅读
4 分钟
幻灯片
7
原文
英语
在 YouTube 打开
往下滚动阅读时,视频会缩到右下角继续播放。字幕跟随阅读语言。
阅读语言共 2 种语言可读
由 AI 从英语原文翻译。打开“对照原文”可以逐段核对。
摘要

30 秒看懂

在 OCaml Unboxed 关于实验性局部值的第二期中,讲者将局部标注从参数扩展到变量和返回值。编译器示例展示了逃逸错误、尾位置的特殊处理,以及 `exclave_` 和局部返回标注如何让问候列表在调用方区域中分配。

  1. 1局部变量不能逃逸将局部变量 `x` 赋给生命周期更长的字符串引用会产生逃逸错误。
  2. 2局部元组可以包含局部值当元组本身不逃逸时,编译器会推断包含局部值的元组也是局部的。
  3. 3尾位置的特殊规则同一个 `ignore` 调用放在返回位置时可能失败;讲者留待以后解释详细规则。
  4. 4辅助函数的类型需要标注局部性普通的 `string -> string list` 签名不保证实参保持局部。
  5. 5提前结束区域`exclave_` 让问候列表成为外层区域的一部分,返回值上的 `local_` 则传达调用约定和结果的局部性。
  6. 6参数与局部别名不同示例编译器允许在 exclave 中使用参数,但拒绝使用函数内部定义的局部别名。

要点建议

  1. 局部变量不能逃出其区域,包括通过生命周期更长的引用逃逸。
  2. 包含局部值的结构如果不逃逸,本身也可以是局部的。
  3. 返回位置或尾位置有特殊的局部性规则,讲者留待之后解释。
  4. `exclave_` 提前结束函数的区域,让后续表达式可以在外层区域分配。
  5. 局部返回标注表明函数可能在调用方区域分配,返回结果也不能逃出该区域。
  6. 在示例中,局部参数可以在 exclave 内使用,而局部绑定的别名不可以。
全文

按章节阅读整理后的全文

只看原始文稿
01

局部变量与逃逸

讲者回顾局部参数,并在命令式函数中添加局部变量。将该变量存入引用会产生逃逸错误。

上次我们看到了局部参数:作为实参接收的值不会逃出其区域,因此函数不会将它存起来,也不会把它放进以后会存到别处的结构中。今天我想将这个概念推广到局部变量,并解释为什么可能需要局部返回值。

我从一个类型为 `unit -> unit` 的小型命令式函数开始,用 `let local_ x = "you"` 绑定 `x`。这个标注告诉我,即使函数包含复杂的命令式代码,它也不能把这个局部值存到会让它逃逸的地方。

例如,我在函数外创建一个字符串引用,并尝试将 `x` 赋给它。编译器报告该值逃出了其区域,这正是局部标注应当阻止的情况。去掉赋值后,程序又可以正常工作。

局部值与引用
幻灯片 1 / 7局部值与引用示例尝试将局部变量 `x` 存入外部引用,展示了逃逸问题。
02

忽略局部值与尾位置

示例中的实验性编译器需要一个带局部类型的 `ignore`,并能推断局部元组。返回位置遵循特殊规则,之后会进一步解释。

在这里展示的实验性编译器中,即便使用内置的 `ignore x` 也会产生逃逸错误:内置函数还不了解局部值。我另外定义一个类型为 `local_ 'a -> unit` 的 `ignore`,程序便能工作。这一功能仍在开发中,因此还有一些不完善之处。

我再添加一个局部变量 `y`,并将 `(x, y)` 传给支持局部值的 `ignore`。两个值不会仅仅因为放进元组就逃逸:元组本身并不逃逸。编译器会推断包含局部值的结构本身也必须是局部的。

包含局部值的元组
幻灯片 2 / 7包含局部值的元组当元组不逃逸时,支持局部值的 `ignore` 可以接收它。
尾位置的逃逸错误
幻灯片 3 / 7尾位置的逃逸错误在演示所用的编译器中,将同一个调用放在返回位置会触发局部性错误。

如果把 `ignore (x, y)` 直接放在函数的返回位置,就会出现问题:编译器报告逃逸。返回位置也称为尾位置,它有特殊的局部性规则。我会在之后的视频中解释这些规则;现在先把调用移出返回位置,然后返回 `()`。

03

重构问候函数

构建列表的辅助函数揭示了参数和返回值局部性的重要性。最初的函数签名允许或导致逃逸。

接下来,我为 `x` 和 `y` 构建局部问候列表,每个列表都包含 `"Hello,"` 和对应的值。代码可以工作,但重复了相同的操作。为了避免重复,我提取一个接收字符串并返回字符串列表的辅助函数 `greet`。

用局部变量 `x` 调用辅助函数会失败。它的普通类型 `string -> string list` 没有承诺实参不会被存到某处或以其他方式逃逸。将参数标为 `local_` 就作出了这个承诺,但编译器随后报告另一个错误:函数实现把局部参数放进了返回的列表。

普通辅助函数不能接收局部值
幻灯片 4 / 7普通辅助函数不能接收局部值编译器拒绝 `greet x`,因为原始函数签名不保证局部性。
在列表中返回局部参数
幻灯片 5 / 7在列表中返回局部参数将参数标为局部后,返回列表又产生了一个逃逸错误。

我希望这个列表属于外层区域,而不是辅助函数自己的区域。一般规则是局部值不能逃出其区域。每个函数都定义一个区域,如果不作改变,将局部参数放进返回列表看起来就像一次逃逸。

04

Exclave 与局部返回值

讲者使用 `exclave_` 提前结束辅助函数的区域,再在调用方区域中分配列表。局部返回标注说明这种分配,并阻止结果逃逸。

关键字 `exclave_` 在构建列表之前提前结束 `greet` 的区域。参数 `z` 来自外层区域,因此在内层区域结束后使用它不会使它逃出该区域。新构建的列表也在 `greet` 区域之外,即调用方的区域内分配。

在我将返回值标为局部之前,仍然会出现错误。编译器报告一个值逃出了其区域;我认为这个例子中的错误信息有误导性,虽然类型错误本身有充分的理由。函数必须表明它可能在调用方区域分配,以便调用约定正确工作。

局部返回值与 `exclave_`
幻灯片 6 / 7局部返回值与 `exclave_`可编译的签名和函数体将列表分配在调用方区域中。

返回值上的 `local_` 标注传达两件事:函数可能在调用方区域分配,返回值也是局部的,不能逃出该区域。加上这个标注和 `exclave_` 后,示例可以编译。我可以对两个局部变量都使用 `greet`。

回顾一下:局部参数让 `greet` 能够接收 `x`;`exclave_` 在构建列表之前结束辅助函数的区域;局部返回标注则表明结果在父区域中局部分配,不能继续逃逸。编译器知道参数来自外层区域。

05

Exclave 内的局部别名

在示例中,参数的局部别名不能在 exclave 内使用。讲者指出局部参数和局部变量存在区别。

局部参数和局部变量之间有一个微妙的区别。如果我在 `greet` 内绑定 `let local_ a = z`,并在 exclave 中使用 `a`,编译器会拒绝:局部变量不能在那里使用。我们失去了这个绑定来自外层区域的信息。我会在之后的视频中进一步探讨这一区别。

Exclave 中的局部别名
幻灯片 7 / 7Exclave 中的局部别名示例改为在返回列表中使用本地定义的别名,编译器拒绝了这一做法。

同频道的其他文章

1:48:29EN → 简体中文
JSJane Street· 2026年10月16日AI 如何改变编程:John Krazit 与 Ron Minsky 的对话Ron Minsky, John Krazit · Jane StreetJane Street 的 AI 工具负责人和 Signals and Threads 主持人探讨智能体基础设施、安全、代码审查,以及软件开发体验的变化。编程智能体Developer productivity评估+2
1:36:37EN → 简体中文
JSJane Street· 2026年9月23日Aaron Bauer:在 AI 时代教授软件工程Ron Minsky, Aaron Bauer · Jane Street当模型能够生成代码时,学习目标、主动练习和编辑器设计如何影响工程教育。AI in EducationSoftware engineeringEducation+2
9 张幻灯片1:05:45EN → 简体中文
JSJane Street· 2026年9月11日Cyrus Omar:实时编程与人与 AI 共享的计算公共空间Cyrus Omar通过 Hazel 演示,探讨即时反馈、结构化协作和精细权限如何帮助人类与 AI 智能体共同工作。Programming LanguagesHuman-AI Collaboration开发流程与测试+2
1:25:00EN → 简体中文
JSJane Street· 2026年9月2日Eric Mannes:如何将杂乱的外部数据用于交易研究Ron, Eric Mannes · Jane Street从商品期货和 Excel 风险系统,到时点数据集和 AI,Eric Mannes 解释 Jane Street 数据工程背后的领域知识。Data quality & curation开发流程与测试Investing+2
7 张幻灯片1:16:29EN → 简体中文
JSJane Street· 2026年8月26日Grant Sanderson 与 Alok Puranik:从群论看位置编码Grant Sanderson, Alok Puranik · 3Blue1Brown从注意力机制的假设出发,他们推导矩阵指数,并将旋转、衰减和 Jordan 块与 RoPE、ALiBi 联系起来。Transformers & attentionMathematics机器学习基础+1
27:39EN → 简体中文
JSJane Street· 2026年8月21日3Blue1Brown 与 Jane Street 谈交易、机器学习和文化Grant Sanderson, Nitya, In Young, Craig, Alok · 3Blue1BrownGrant Sanderson 与 Jane Street 的同事讨论做市、共享算力、研究,以及他们加入公司的不同经历。Machine LearningFintechCompany Culture+2