OCaml Local Types: Regional Parameters and Loop Regions

A demonstration explains why some local parameters can cross a function boundary and how loop regions reclaim allocations.

チャンネル
Jane Street
公開日
2024年6月13日
動画
11:28
読了時間
3 分
スライド
5
原文
英語
YouTube で開く
スクロールすると動画は右下に小さくなって再生を続けます。字幕は閲覧言語に合わせて切り替わります。
閲覧言語2 言語で読めます
この記事はまだ日本語に翻訳されていないため、英語の原文を表示しています。
要約

30 秒でわかる

A Jane Street presenter continues a series on local types in the firm’s OCaml compiler branch. Using identity and iteration functions, the episode explains the hidden regional treatment of local parameters, tail calls and per-iteration regions.

  1. 1An apparent escapeAn identity function can accept and return a local string, despite the rule that local values must not escape their region.
  2. 2The hidden regional modeA local parameter is regional within its function and can escape one region, because the caller supplied it.
  3. 3Losing regional informationPassing a regional function through an identity function returns a local value that cannot be passed to the tail call.
  4. 4Regions around loopsEach loop-body region can reclaim local allocations before the next iteration.

ポイント

  1. A parameter marked local is treated as regional inside the function.
  2. A regional value may cross one region boundary because it originated outside that region.
  3. Returning such a value exposes it as local to the caller rather than preserving regional information.
  4. Passing a regional value through a local-returning identity function can lose the information needed for a tail call.
  5. Loop bodies create regions that allow local allocations to be reclaimed on each iteration.
全文

チャプターごとに整えた全文を読む

文字起こしのみ
01

Two surprising examples

A local identity function returns its input, while a recursive iterator passes a local function into a tail call. Both appear to conflict with the region rules.

This episode continues the series on local values in Jane Street’s publicly available OCaml compiler branch. I want to explain regions and a hidden mode called regional, using examples that initially appear to violate the rules from earlier videos.

Consider an identity function with a parameter annotated as a local string. It compiles, and the inferred type takes a local string and returns a local string. That seems surprising: every function defines a region, and a local value is not supposed to escape its region.

A local identity function
スライド 1 / 5A local identity functionThe inferred function type accepts and returns a local string.

A second example is a recursive iterator over a list. It accepts a function, applies it to each head and makes a tail-recursive call on the remainder. Marking the function parameter local permits a caller to provide a closure without necessarily allocating that closure on the heap.

A local function parameter in an iterator
スライド 2 / 5A local function parameter in an iteratorThe recursive list iterator takes a local function and passes it into a tail call.

The iterator still compiles even though the recursive call is a tail call, which lies outside the current function’s region. Why can the function parameter be passed there? The identity function’s return and the iterator’s tail call both seem to allow local values to escape.

02

The regional mode

Local parameters are treated as regional within a function and can cross one region boundary. Passing one through a local-returning function loses that information.

The explanation is that a parameter marked local is treated as regional inside the function. Regional is a hidden mode, not a keyword that can be written in the program. A regional value may escape one region, though it does not have to escape at all.

Local parameters are regional
スライド 3 / 5Local parameters are regionalThe code annotations identify the hidden mode used for parameters inside their function.

A parameter must have been supplied by a caller, so it already lives beyond the callee’s own region. Letting it cross that one boundary is safe. In the identity example, the returned string is local to the caller: it cannot simply become global, which would allow an actually local value to escape too far.

In the iterator, the function argument is also regional within the current invocation. It can therefore cross the boundary at the tail call and be passed to the next invocation, even though the current function’s region ends before that call.

To show the distinction, I pass the iterator’s function argument through an identity function whose type takes and returns a local value. Its result is known only as local; the type does not preserve the fact that the original argument was regional. Passing that result to the tail call now produces an escaping-local error.

Regional information lost through identity
スライド 4 / 5Regional information lost through identityThe compiler rejects the local result passed to a tail call.
03

Regions in loop bodies

The presenter rewrites the iterator as an array loop. Its per-iteration region determines when local allocations can be reclaimed.

Regions also surround loop bodies. I rewrite the iterator to traverse an array with a for loop and call the function for each element. The example is about the lifetime of local allocations made while the loop runs.

If the called function returns locally, its local allocations are made in its parent’s region—in this case, the loop-body region. Each time an iteration ends, that region can be reclaimed before the next iteration. Without such a boundary, repeated work could accumulate space across the loop.

A loop-body region
スライド 5 / 5A loop-body regionThe array iterator calls a local-returning function within a loop.

The presenter notes that the loop rule is less consequential for typing in this example because loops do not normally return a value except via mechanisms such as references. It is still useful for understanding allocation behavior: local allocations in a loop’s region end with the iteration.

同じチャンネルの記事

スライド 6 枚15:33EN
JSJane Street· 2026年10月26日Figgie Strategy: Reading Hands, Winning Majorities and Pricing CardsBradley, Mike · Jane StreetJane Street traders Bradley and Mike analyze three games to show how private information, market competition and timing affect card prices.Decision MakingMathematicsFintech
1:48:29EN
JSJane Street· 2026年10月16日How AI Is Changing Programming: John Krazit and Ron MinskyRon Minsky, John Krazit · Jane StreetJane Street’s AI tooling lead and the Signals and Threads host examine agent infrastructure, security, code review and the changing experience of writing software.コーディングエージェントDeveloper productivity評価(Evals)+2
1:36:37EN
JSJane Street· 2026年9月23日Aaron Bauer on Teaching Software Engineering in the Age of AIRon Minsky, Aaron Bauer · Jane StreetHow learning goals, active practice and editor design shape engineering education when models can generate the code.AI in EducationSoftware engineeringEducation+2
スライド 9 枚1:05:45EN
JSJane Street· 2026年9月11日Cyrus Omar on Live Programming and a Computational Commons for Humans and AICyrus OmarA demonstration of Hazel shows how immediate feedback, structured collaboration and carefully scoped permissions could support people and AI agents working together.Programming LanguagesHuman-AI Collaboration開発ワークフローとテスト+2
1:25:00EN
JSJane Street· 2026年9月2日Eric Mannes on Turning Messy External Data Into Trading ResearchRon, Eric Mannes · Jane StreetFrom commodity futures and an Excel risk system to point-in-time datasets and AI, Eric Mannes explains the domain knowledge behind data engineering at Jane Street.Data quality & curation開発ワークフローとテストInvesting+2
スライド 7 枚1:16:29EN
JSJane Street· 2026年8月26日Grant Sanderson and Alok Puranik: Positional Encodings Through Group TheoryGrant Sanderson, Alok Puranik · 3Blue1BrownStarting with assumptions about attention, they derive matrix exponentials and connect rotations, decay and Jordan blocks to RoPE and ALiBi.Transformers & attentionMathematics機械学習の基礎+1