Locality Mode OxCaml

let f () =
  let u @ local = [6; 2; 8] in (* mode *)
  let len = Base.List.length u in
  len;;
let f () =
  let local_ u = [6; 2; 8] in
  let len = Base.List.length u in
  len;;
let f () =
  let u : int list @@ local = stack_ [6; 2; 8] in (* modality *)
  let len = Base.List.length u in
  len;;
let f () =
  let u = local_ [6; 2; 8] in
  let len = Base.List.length u in
  len;;

Other keywords to spot: stack_, global_, @ global, exclave_ and [@local_opt]

Type: what it is -; Mode: how it's used

Mode

Lifetime

Allocation

global or missing

MAY outlive its region

MUST be on the heap

local

MUST NOT outlive its region

MAY be on the stack

  1. Function bodies
  2. Loop bodies
  3. Lazy expressions
  4. Module level bindings
let f () =
  let foo =
    let local_ bar = ("region", "scope") in
    bar in
  fst foo;;

What does local mean?

  1. Neither function result nor exception payload
  2. Not captured in closure, not referred from mutable area
  3. Not reachable from a heap allocated value
  4. Freed at its region's end, without triggering the GC
  1. Contract between caller and callee
  2. local means in the caller's region
  3. Parameter: callee respects caller's locality
  4. Result: callee stores in caller's region
  5. This really defines 4 arrows

    val global_global : s -> t * t                (* Legacy *)
    val local_global : local_ s -> t * t
    val global_local : s -> local_ t * t
    val local_local : local_ s -> local_ t * t

What is `local` for?

0. Low-latency code More importantly, stack allocations will never trigger a GC, and so they're safe to use in low-latency code that must currently be zero-alloc 1. Functions passed to higher-order iterators (such as `map`, `fold`, `bind` and others) are allocated on the stack 2. Safer callbacks

Hands-on

# let monday () = let str = "mon" ^ "day" in str;;
# let bye () = let ciao = "sorry" in failwith ciao;;
# let make_counter () =
    let counter = ref (-1) in
    fun () -> incr counter; !counter;;
# let state = ref "";;
# let set () = state := "disco";;
# let rec map f = function [] -> [] | x :: u -> f x :: map f u;;
# let f1 (local_ u : int list) = [1; 2; 3];;
# let f2 (local_ u : int list) = u;;
# let f3 (local_ u : int list) = 42 :: u;;