OCaml Locals, Modes, and Submoding

A worked explanation of how local and global modes control escaping values, and how those modes interact with function types.

Canal
Jane Street
Publicado
31 ene 2024
Vídeo
15:17
Lectura
5 min
Diapositivas
5
Original
inglés
Abrir en YouTube
Al desplazarte, el vídeo se reduce a la esquina inferior derecha y sigue reproduciéndose. Los subtítulos siguen tu idioma de lectura.
Idioma de lecturaDisponible en 2 idiomas
Este artículo aún no está en español, así que se muestra el original en inglés.
RESUMEN

En 30 segundos

In this OCaml Unboxed lesson, the speaker explains modes as properties of expressions and variables, then uses compiler examples to show why a global value can be treated as local but not the reverse. The lesson also distinguishes a local parameter's promise from a requirement on callers and examines the four combinations of modes on a function arrow.

  1. 1Modes describe expressionsLocal and global are modes. Like types, modes apply to every expression and variable and can be inferred from how values are used.
  2. 2A local value cannot flow into a global contextPassing a local value through another variable to a function requiring a global argument is rejected because the value might escape its region.
  3. 3Global is a submode of localA global value may be treated as local, giving up the capability to escape. Treating a local value as global would improperly gain that capability.
  4. 4A local parameter is a promiseThe function promises not to let the argument escape; the annotation does not prevent a caller from passing a global value.
  5. 5Four function arrow typesInput and output can each be local or global. These are distinct types, and references expose their incompatibility by preventing the conversions the compiler can sometimes perform.

Conclusiones

  1. Every expression and variable has a mode, much as it has a type, and the compiler can infer modes from usage.
  2. A local value cannot escape its region or flow into a global context that might let it escape.
  3. Global is a submode of local: a global value can be used locally by giving up its ability to escape.
  4. A local parameter promises that the function implementation will not let the argument escape; callers may pass local or global values.
  5. The input and output modes form four distinct function arrow types, even though the compiler can sometimes convert between them.
TEXTO COMPLETO

Lee el texto editado por capítulos

Solo la transcripción
01

Modes and expressions

The speaker steps back from earlier examples of local parameters, variables and return values to explain modes. Every expression and variable has a mode as well as a type.

In the previous videos we looked at local parameters, then local variables and return values. This time I want to step back from writing functions and look at the theory that helps us understand how locals and globals interact. Local and global are called modes.

A mode is somewhat like a type, although there are differences. Every OCaml expression has a type: 5 has type int, while a larger expression might have type string list option. Every variable also has a type because it stands for an expression, which is evaluated to a value before it is stored. Similarly, every expression and every variable has a mode.

02

Inferring local and global

A local binding and a function requiring a global argument demonstrate mode inference. The compiler rejects a local value that could escape through a global use.

Local and global modes
DIAPOSITIVA 1 / 5Local and global modesThe editor lists the mode terminology and the region rules recalled from earlier lessons.

For example, in `let local_ x = "hello"`, the annotation forces x into local mode, and the expression `"hello"` is local too. The code compiles. I can suppress the unused-variable warning while experimenting.

If I introduce y, there is no corresponding annotation I can put on that variable to say that I want it to be global. Instead, I can define `mark_global : 'a -> unit` to ignore its argument. Its parameter is not marked local, so calling `mark_global y` forces y to be global through inference.

A local value escapes through a global use
DIAPOSITIVA 2 / 5A local value escapes through a global useThe compiler rejects passing y to a global parameter when y receives local x.

If I then write `let y = x` and pass y to `mark_global`, the compiler reports that the value escapes its region. The use of y requires a global value, while the locally declared x flows into it. Local values cannot escape, and allowing one to flow into a global value would give it a way to escape indirectly.

The actual program happens to be safe: `mark_global` simply ignores its argument. But its type does not promise that it will not store the argument somewhere. The compiler relies on the function's type, so it must reject the call even though the binding itself is not at the end of the region.

03

The submoding relationship

A global value can be assigned to a local binding. The speaker explains global as a submode of local in terms of giving up the capability to escape.

Now suppose y is global and I write `let local_ z = y`. This compiles. The `mark_global y` call can be farther down in the program and still determine y's mode, just as a distant use can affect inferred types. A global annotation would be convenient for this demonstration, although we generally do not need one.

Using a global value in a local binding
DIAPOSITIVA 3 / 5Using a global value in a local bindingThe example assigns global y to local z and compiles, demonstrating the permitted direction of submoding.

Why can a global y flow into local z? Global is a submode of local, written `global < local`. As with assigning a subtype to a supertype, a global expression can be used in a local context. Local says the value does not escape; treating a global value locally says this use of it will not escape, which is safe.

The reverse does not work. Think of global as having the capability to escape. We may voluntarily give up a capability when we use a global value locally, but turning a local value into a global one would invent a capability it did not have. I find the ordering a little counterintuitive because global sounds bigger than local, yet we write global less than local.

04

Local function parameters

A function with a local parameter can accept both local and global values. Its annotation is a promise about the implementation, which cannot let the argument escape.

Modes also interact with functions. I can define `mark_local : local_ 'a -> unit`, again with an implementation that ignores its argument. Calling it with the local x, the global y, or the local z all works. Passing y is fine because a global value can be used in a local context.

Calling a function with a local parameter
DIAPOSITIVA 4 / 5Calling a function with a local parameterThe example passes local and global values to `mark_local`.

The local annotation on the parameter means that the parameter does not escape. It is a promise made by the function's implementation, not a requirement that callers provide a value originally declared local. A caller can pass either a local or a global value.

That promise limits the implementation: for example, storing the parameter in a reference is rejected as an escape. Even if I immediately ignore the reference, the escape analysis is not clever enough to accept this case. It may therefore make sense to mark parameters local wherever possible; I will discuss locality inference in a later video.

This is a difference from an ordinary type annotation on a function, which describes both the implementation and a requirement at use sites. Because of submoding, a local parameter imposes no meaningful restriction on whether the caller's value was global or local. My `mark_local` example is essentially just `ignore`.

05

Modes on function arrows

The four possible input and output mode combinations give distinct arrow types. A reference example shows the distinctions, and the speaker explains that local annotations belong to the arrow.

There is another detail about modes and function types. Each side of an arrow can be local or global, giving four arrow types: `string -> string`, `local_ string -> string`, `string -> local_ string`, and `local_ string -> local_ string`. The case with a local input and a global output requires more care in its implementation.

These are four different types, with no subtyping relationship between them, although OCaml can perform some conversions in certain situations. To show the distinction, I put a function in a reference whose declared contents have type `string -> string`. A reference to the matching function works, but references to the other function types produce errors. The reference prevents conversions that the compiler might otherwise apply.

Distinct function arrow types
DIAPOSITIVA 5 / 5Distinct function arrow typesThe four mode combinations are shown alongside a reference type mismatch.

The key ideas are that modes describe every expression and variable, and that submoding lets any global value be treated as local, but not the other way around. We can annotate the input and output modes of a function arrow.

It is useful to remember that `local_ string` is not an independent type. The `local_` annotation is really describing the arrow. In a theoretical notation we might instead use four different arrow symbols; the concrete syntax places the word `local_` beside the input or output. I will return to these topics in a future video.

Más de este canal

6 diapositivas15:33EN
JSJane Street· 26 oct 2026Figgie 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· 16 oct 2026How 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.Agentes de programaciónDeveloper productivityEvaluaciones+2
1:36:37EN
JSJane Street· 23 sept 2026Aaron 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 diapositivas1:05:45EN
JSJane Street· 11 sept 2026Cyrus 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 CollaborationFlujos de desarrollo y pruebas+2
1:25:00EN
JSJane Street· 2 sept 2026Eric 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 & curationFlujos de desarrollo y pruebasInvesting+2
7 diapositivas1:16:29EN
JSJane Street· 26 ago 2026Grant 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 & attentionMathematicsFundamentos de ML+1