Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

OCaml  Module 15 – Web services, migration and the ecosystem

OCaml 5 migration, versions and the ecosystem

What changed from OCaml 4.14 to 5.5, why a 4.14 program stops compiling, how a Stream tokenizer moves to Seq, and the oldest compiler each library accepts.

  • Intermediate
  • 15 minutes
  • Examples run with ocaml 5.5.1, opam 2.6.0, dune 3.24.2 and Python 3.14.8
  • By MySmartCoPilot
Free core, Pro depth: 4 of 15 minutes free
Free: Six feature releases followed 4.14, and 5.0 removed what 4.14 deprecated · A 4.14 tokenizer stops at Stream; the Seq port prints the same tokens · An OCaml 5 migration has three parts, and the ecosystem sets a compiler floor · Practise: releases, the Seq port and compiler floors. With a pass: 2 in-depth parts and 3 interview answers, about 11 minutes.

What you will learn

  • List what each release from OCaml 4.14 to 5.5 added, and what 5.0 removed
  • Rewrite a Stream-based 4.14 program with Seq so that it builds on OCaml 5.5.1 and prints the same output
  • Plan the migration of a 4.14 codebase, including global mutable state under domains and C stubs
  • Choose libraries for a project: the standard library or Base, Eio or Lwt, and tools for tests, CLIs and the web
  • Follow point releases and security advisories, and check the oldest compiler each dependency accepts

Before you start

What you’ll learn · Before you start

What you will learn

  • List what each release from OCaml 4.14 to 5.5 added, and what 5.0 removed
  • Rewrite a Stream-based 4.14 program with Seq so that it builds on OCaml 5.5.1 and prints the same output
  • Plan the migration of a 4.14 codebase, including global mutable state under domains and C stubs
  • Choose libraries for a project: the standard library or Base, Eio or Lwt, and tools for tests, CLIs and the web
  • Follow point releases and security advisories, and check the oldest compiler each dependency accepts

Before you start

On this page

A tokenizer written for OCaml 4.14 stops on OCaml 5.5.1 at line 12 with Unbound module Stream. Six feature releases separate the two compilers, and the first of them, 5.0, removed modules and functions that 4.14 had only marked deprecated.

An OCaml 5 migration therefore starts with the names that are gone, then the mutable state that domains can now share and the C stubs the new runtime treats differently. The ecosystem moved as well: every library has an oldest compiler it installs on, and security fixes keep arriving in point releases. You will list each release’s changes, port the tokenizer to Seq and map the rest of a move.

Six feature releases followed 4.14, and 5.0 removed what 4.14 deprecated

OCaml’s Changes file marks each entry that can break existing programs with an asterisk, a breaking change: A change in a new release of a compiler or library after which some programs that worked with the previous release no longer build or no longer behave the same; OCaml's Changes file marks such entries with an asterisk.. In the 5.0 section, entries #10896 and #10867 remove Stream, Genlex, Pervasives, the standalone bigarray library and dozens of long-deprecated values such as String.set and Thread.kill. Most of them already carried a deprecation: A notice that a function or module is due to be removed in a later release, shown as an alert wherever code uses it; OCaml 4.14 deprecated Stream and Genlex before OCaml 5.0 removed them. alert in 4.14, whose stdlib.mli tells Stream users to “Use the camlp-streams library instead.” Walk through the releases in order:

Timeline · 7 events in order From OCaml 4.14 to 5.5: what each release changed Walk through the releases in order. Each card says what the release added and, for 5.0, what it took away from code written for 4.14.
  1. 4.14

    The last 4.x series prepares the way deprecations

    New In_channel and Out_channel modules and many new Seq functions, Seq.uncons among them. Stream and Genlex are marked deprecated ahead of their removal, and tail modulo cons arrives as an experiment. The 4.14 series still gets point releases.

  2. 5.0

    A new runtime with domains and effect handlers removals

    Domain runs OCaml code in parallel on several cores and Effect adds effect handlers. Stream, Genlex, Pervasives and the standalone bigarray library are removed, with dozens of long-deprecated values such as String.set, and a C pointer may no longer stand in for an OCaml value.

  3. 5.1

    Tail-recursive List.map, and fewer regressions

    Tail-recursion modulo cons makes 14 standard library functions, List.map and List.append among them, safe on very long lists. Many performance regressions and memory leaks of the new runtime are fixed, and In_channel gains input_lines.

  4. 5.2

    Compaction, Dynarray and ThreadSanitizer

    Heap compaction returns, Dynarray adds an array that grows, raw identifiers such as \#match let a keyword serve as a name, and the compiler can be built with ThreadSanitizer, a data-race detector, on FreeBSD, Linux and macOS.

  5. 5.3

    Syntax for effect handlers

    Effects are handled with effect cases inside an ordinary match, source files may be UTF-8 encoded, and the MSVC port for Windows is back.

  6. 5.4

    Labelled tuples and immutable arrays

    Tuple positions may carry labels, the iarray type adds immutable arrays, a record field can be marked [@atomic], and Pair, Pqueue, Repr and Iarray join the standard library.

  7. 5.5

    Module-dependent functions

    A function can take a module and name it in its own type, a parameter can be polymorphic, the installed compiler can be moved to another folder and still work, and about 60 functions join the standard library, such as String.split_all.

The timeline has 7 events, from 4.14 to 5.5.

Compiling one line of each release shows which versions a codebase needs. The probe below holds files for every release, each using something that release added, and four files that use a name 5.0 removed:

A feature probe: one file per release, compiled on OCaml 5.5.1 Python · probe_session.py
from pathlib import Path

from session import files, run

# A feature probe recorded on OCaml 5.5.1: one small file per release from 4.14
# to 5.5, each using one thing that release added, and four files that use
# something 5.0 removed. probe.sh compiles each file on its own and prints the
# file's first comment with the result. No OCaml 4.14 compiler is run here: what
# 4.14 itself accepted comes from the Changes file the lesson cites.
files(*sorted(str(p) for p in Path("probe").iterdir()))
run(
    """
cat probe/p53_effect_match.ml
bash probe/probe.sh
""",
)

Output

$ cat probe/p53_effect_match.ml
(* 5.3: effect cases inside match *)
type _ Effect.t += Ask : int Effect.t
let run f = match f () with v -> v | effect Ask, k -> Effect.Deep.continue k 42
$ bash probe/probe.sh
4.14: In_channel reads a whole file        compiles
5.0: Domain runs code in parallel          compiles
5.0: Effect.perform and effect types       compiles
5.1: In_channel.input_lines                compiles
5.2: Dynarray grows as you append          compiles
5.2: raw identifiers such as \#match       compiles
5.3: effect cases inside match             compiles
5.4: [@atomic] record fields               compiles
5.4: immutable arrays, type int iarray     compiles
5.4: labelled tuples                       compiles
5.5: module-dependent functions            compiles
5.5: polymorphic parameters                compiles
removed in 5.0: Genlex                     Error: Unbound module Genlex
removed in 5.0: Pervasives                 Error: Unbound module Pervasives
removed in 5.0: Stream                     Error: Unbound module Stream
removed in 5.0: String.set                 Error: Unbound value String.set

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 probe_session.py

All twelve feature files compile on 5.5.1, and the four removed names fail with Unbound module or Unbound value. No 4.14 compiler ran here, so what the older versions lacked comes from the Changes file.

A 4.14 tokenizer stops at Stream; the Seq port prints the same tokens

The 4.14 tokenizer reads characters with Stream.peek, which looks at the next one, and Stream.junk, which consumes it, so the stream itself moves forward. The port keeps the structure on a sequence: A value of type 'a Seq.t: a function that, called with (), returns Seq.Nil at the end or Seq.Cons with the next element and the rest, so each element is computed only when a consumer asks for it. More in “Sequences, laziness and memoization” of type char Seq.t: Seq.uncons returns the next character with the rest, so take_while hands back the word and the rest, and String.to_seq replaces Stream.of_string. Compare the two files:

The tokenizer before and after the port

tokens_stream.ml (4.14) · port/tokens_stream.ml

(* A tokenizer as it was written for OCaml 4.14: it reads characters from a
   Stream, looking at the next one with Stream.peek and consuming it with
   Stream.junk, so the stream itself moves forward. *)
type token = Ident of string | Int of int | Sym of char

let is_digit c = c >= '0' && c <= '9'
let is_letter c = (c >= 'a' && c <= 'z') || c = '_'

let take_while p s =
  let b = Buffer.create 8 in
  let rec go () =
    match Stream.peek s with
    | Some c when p c ->
        Stream.junk s;
        Buffer.add_char b c;
        go ()
    | _ -> Buffer.contents b
  in
  go ()

let rec tokens s =
  match Stream.peek s with
  | None -> []
  | Some (' ' | '\t') ->
      Stream.junk s;
      tokens s
  | Some c when is_digit c ->
      let n = take_while is_digit s in
      Int (int_of_string n) :: tokens s
  | Some c when is_letter c ->
      let w = take_while is_letter s in
      Ident w :: tokens s
  | Some c ->
      Stream.junk s;
      Sym c :: tokens s

let show = function
  | Ident w -> "IDENT " ^ w
  | Int n -> "INT " ^ string_of_int n
  | Sym c -> "SYM " ^ String.make 1 c

let () =
  Stream.of_string "total = price * qty + 40"
  |> tokens
  |> List.iter (fun t -> print_endline (show t))

tokens_seq.ml (Seq port) · port/tokens_seq.ml

(* The same tokenizer for OCaml 5: a char Seq.t replaces the Stream. Seq.uncons
   returns the next character together with the rest of the sequence, so each
   function hands the rest on instead of moving a stream forward. *)
type token = Ident of string | Int of int | Sym of char

let is_digit c = c >= '0' && c <= '9'
let is_letter c = (c >= 'a' && c <= 'z') || c = '_'

(* The word made of characters that satisfy p, and the sequence after it. *)
let take_while p seq =
  let b = Buffer.create 8 in
  let rec go seq =
    match Seq.uncons seq with
    | Some (c, rest) when p c ->
        Buffer.add_char b c;
        go rest
    | _ -> (Buffer.contents b, seq)
  in
  go seq

let rec tokens seq =
  match Seq.uncons seq with
  | None -> []
  | Some ((' ' | '\t'), rest) -> tokens rest
  | Some (c, _) when is_digit c ->
      let n, rest = take_while is_digit seq in
      Int (int_of_string n) :: tokens rest
  | Some (c, _) when is_letter c ->
      let w, rest = take_while is_letter seq in
      Ident w :: tokens rest
  | Some (c, rest) -> Sym c :: tokens rest

let show = function
  | Ident w -> "IDENT " ^ w
  | Int n -> "INT " ^ string_of_int n
  | Sym c -> "SYM " ^ String.make 1 c

let () =
  String.to_seq "total = price * qty + 40"
  |> tokens
  |> List.iter (fun t -> print_endline (show t))

On OCaml 5.5.1, dune stops the old file at its first use of Stream and builds the port, whose seven tokens match the list kept in expected_tokens.txt:

The 4.14 tokenizer fails on OCaml 5.5.1, and the Seq port prints the same tokens Python · port_session.py
from session import files, run

# The free part's worked example. The tokenizer written for OCaml 4.14 stops at
# its first use of Stream on OCaml 5.5.1; the Seq rewrite builds, and its output
# is compared with the token list the project's test file keeps.
files(
    "port/dune-project=dune-project",
    "port/dune=dune",
    "port/tokens_stream.ml=tokens_stream.ml",
    "port/tokens_seq.ml=tokens_seq.ml",
    "port/expected_tokens.txt=expected_tokens.txt",
)
run(
    """
ocamlopt -version
!dune build ./tokens_stream.exe
dune build ./tokens_seq.exe
dune exec ./tokens_seq.exe
dune exec ./tokens_seq.exe | diff - expected_tokens.txt && echo "same tokens as expected_tokens.txt"
""",
)

Output

$ ocamlopt -version
5.5.1
$ dune build ./tokens_stream.exe
File "tokens_stream.ml", line 12, characters 10-16:
12 |     match Stream.peek s with
               ^^^^^^
Error: Unbound module Stream
[exit status 1]
$ dune build ./tokens_seq.exe
$ dune exec ./tokens_seq.exe
IDENT total
SYM =
IDENT price
SYM *
IDENT qty
SYM +
INT 40
$ dune exec ./tokens_seq.exe | diff - expected_tokens.txt && echo "same tokens as expected_tokens.txt"
same tokens as expected_tokens.txt

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 port_session.py

A string's Seq does not move forward when you read it

A Stream passed to two functions was consumed by the first. The sequence String.to_seq builds starts from the same place each time it is read, so a port that drops the rest reads the word twice; return the rest, as take_while returns (word, rest).

Seq.uncons and String.to_seq are both documented in 4.14, so the port can land while the project still builds there.

Checkpoint

Check: What each release added, and what 5.0 removed · Porting Stream code to Seq

  1. Question 1 of 2 A 4.14 file calls Pervasives.print_endline, Stream.of_string, Seq.uncons and In_channel.input_all. Which of these calls stop the build on OCaml 5.5.1? Choose every one that does.

    Choose every answer that is right.

    Show the answer: Question 1 of 2

    Answer:

    • Stream.of_string
    • Pervasives.print_endline

    5.0 removed Stream, Genlex, Pervasives, the standalone bigarray library and dozens of long-deprecated values. Seq.uncons and In_channel are 4.14 additions that every 5.x release still has, so only the first two calls fail.

  2. Question 2 of 2 Suppose take_while in the port returned only the word, and tokens went on with the sequence it had passed in. What would tokens do with the input "qty + 40"?

    Choose one answer.

    A hint

    Ask where the next call to Seq.uncons starts reading.

    Show the answer: Question 2 of 2

    Answer: Read qty again and again, and never reach the end

    Seq.uncons gives the next element and the rest, and reading the sequence String.to_seq built does not change it. Code that used to rely on a Stream being consumed must return the rest, which is why take_while returns (word, rest).

An OCaml 5 migration has three parts, and the ecosystem sets a compiler floor

Removed names are the first part, and the compiler points at each one. The other two compile cleanly and can go wrong only at run time. Global mutable state, such as a module-level ref or Hashtbl that was safe in one domain: An OCaml 5 unit of parallel execution: Domain.spawn starts a function on a new domain, which runs OCaml code on another processor, and Domain.join waits for its result. More in “Parallelism with domains and atomics”, needs Atomic or Mutex once code runs on several. C stub: A small C function that connects OCaml to a C routine: it reads its OCaml arguments with the runtime's macros, does the work in C, and returns an OCaml value, cooperating with the garbage collector when it allocates. More in “Interfacing with C” must stop handing OCaml a naked pointer: A pointer to memory outside the OCaml heap stored directly as an OCaml value, with no block around it. OCaml 4 allowed it in C stubs; OCaml 5 does not, so the pointer goes inside a block the runtime knows.; the C pointer goes into a custom block instead. For code not ported yet, the camlp-streams package restores Stream and Genlex unchanged.

The ecosystem sets the floor of an OCaml 5 migration, because every package’s opam file fixes the oldest compiler it installs on, directly or through its dependencies, and newer versions of a library often need more:

Package Oldest OCaml
camlp-streams 5.0.1 4.02.3
Alcotest 1.9.1 4.08
Lwt 6.1.2 4.14
Base v0.16.3 4.14.0
Base v0.17.3 5.1.0
Eio 1.6 5.2.0

A project that must keep building on 4.14 during the move keeps Lwt and A library that replaces OCaml's standard library as a whole, with conventions of its own; Core is a larger library built on top of it. v0.16, and adopts Eio 1.6 once every build is on 5.2. The same floors guide the other choices: Base and Core or the standard library, the lwt_eio bridge that runs Lwt and Eio code together, and tools like Cmdliner and Dream. Security fixes arrive in a point release: A release that changes only the last number of a version, such as 5.5.1 after 5.5.0: it fixes bugs and security problems in one release series instead of adding features. such as 5.5.1, and ocaml.org/security describes how each security advisory: A public notice that some versions of a compiler or library have a security flaw, saying which versions are affected and which release or change fixes it. is published.

Key idea

Fix the names 5.0 removed first, then the shared state and C stubs that compile but can still go wrong, and keep only dependencies that accept every compiler your builds use.

Checkpoint

Check: The parts of a migration and compiler floors

  1. One question Your CI builds every commit on OCaml 5.1 and on 5.5. Going by the floor table, which package cannot go into the 5.1 build?

    Choose one answer.

    Show the answer: One question

    Answer: Eio 1.6

    A package can be used only in builds whose compiler meets its floor. Eio 1.6 needs 5.2.0, so a matrix that keeps 5.1 has to wait for Eio until 5.1 leaves it.

Practise: releases, the Seq port and compiler floors

Each question uses the timeline, the probe, the tokenizer or the floor table above, and the idea you know least comes first.

Practice that adapts to you

Practise this lesson

12 questions about 8 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 12 Which release added the Dynarray module?

    Choose one answer.

    Show the answer: Question 1 of 12

    Answer: 5.2

    5.2 brought back heap compaction and added Dynarray, raw identifiers and ThreadSanitizer support.

  2. Question 2 of 12 Since which release can an ordinary match handle effects with effect cases?

    Choose one answer.

    Show the answer: Question 2 of 12

    Answer: 5.3

    Effects arrived in 5.0 as library calls, and 5.3 gave them syntax: effect Ask, k -> ... as a case of a match.

  3. Question 3 of 12 Why is it worth building and testing on 4.14 before trying any 5.x compiler?

    Choose one answer.

    Show the answer: Question 3 of 12

    Answer: Most names 5.0 removed already print a deprecation alert there, so the 4.14 build lists them in advance

    A deprecation is a warning about a later removal: the 4.14 build shows most of the errors 5.0 would show, while the code still builds.

  4. Question 4 of 12 The probe compiled its labelled-tuple file on OCaml 5.5.1. What does that run tell you about OCaml 4.14?

    Choose one answer.

    Show the answer: Question 4 of 12

    Answer: Nothing by itself: that 4.14 lacks labelled tuples comes from the Changes file, which places them in 5.4

    A recorded run is evidence for the toolchain that produced it. Claims about other versions need their own run or a primary source, here the compiler's Changes file.

  5. Question 5 of 12 What does Seq.uncons return for a sequence that is not empty?

    Choose one answer.

    Show the answer: Question 5 of 12

    Answer: Some (x, rest): the first element and the sequence after it

    Seq.uncons : 'a Seq.t -> ('a * 'a Seq.t) option, documented since 4.14, is the Seq counterpart of a Stream.peek followed by Stream.junk.

  6. Question 6 of 12 The port uses only String.to_seq, Seq.uncons and Buffer. Can it be merged while the project still builds on 4.14?

    Choose one answer.

    Show the answer: Question 6 of 12

    Answer: Yes: all three are documented in 4.14, so the same file builds with both compilers

    A port that needs nothing newer than 4.14 can land first, so the switch to 5.x later changes only the compiler.

  7. Question 7 of 12 Where did dune stop the 4.14 tokenizer on OCaml 5.5.1?

    Choose one answer.

    Show the answer: Question 7 of 12

    Answer: At line 12, the first Stream.peek, with Unbound module Stream

    The compiler stops at the first unbound name, so a large file shows its removed names one at a time unless the build keeps going, which is one reason the 4.14 alerts are the better list.

  8. Question 8 of 12 A 4.14 config reader passes one Stream to read_header and then the same stream to read_body, relying on read_header to consume the header. How should the Seq version be shaped?

    Choose one answer.

    Show the answer: Question 8 of 12

    Answer: read_header returns the header and the rest of the sequence, and read_body receives that rest

    Every function that used to consume part of a stream returns what it read together with the rest, and the caller passes the rest on.

  9. Question 9 of 12 Which of these problems compile cleanly on OCaml 5 and can go wrong only at run time? Choose every one that does.

    Choose every answer that is right.

    Show the answer: Question 9 of 12

    Answer:

    • A module-level ref used by several domains
    • A C stub that returns a naked pointer

    Removed names are the easy part because the compiler finds them. Shared state and C stubs build without a word, so they need audits and tests.

  10. Question 10 of 12 Which package restores Stream and Genlex for code that is not ported yet?

    Choose one answer.

    Show the answer: Question 10 of 12

    Answer: camlp-streams

    camlp-streams 5.0.1 accepts every compiler from 4.02.3, so it can sit in a build on both sides of the move.

  11. Question 11 of 12 A project must keep building on 4.14 while it moves. Which packages from the floor table can stay in its 4.14 build? Choose every one that can.

    Choose every answer that is right.

    Show the answer: Question 11 of 12

    Answer:

    • Base v0.16.3
    • camlp-streams 5.0.1
    • Lwt 6.1.2

    Read the floor of every dependency against the oldest compiler a build must keep. Each newer version can raise the floor, as Base did from v0.16 to v0.17.

  12. Question 12 of 12 A security fix for the compiler is released. In what form does it reach a project on the 5.5 series?

    Choose one answer.

    Show the answer: Question 12 of 12

    Answer: As a point release of the series, such as 5.5.1 after 5.5.0

    A point release fixes a series rather than extending it, so taking it is a small step; ocaml.org/security describes how the advisories that go with such releases are published.

Porting a 4.14 codebase to OCaml 5, step by step Pro: opens with a Pro, Premium or Ultimate pass

A 4.14 codebase meets OCaml 5 in three places: names the standard library dropped, mutable state that domains can now share, and C stubs that gave the runtime raw pointers. Each one is reproduced on OCaml 5.5.1 with its fix, followed by the order to work in and the commands for each step.

In this part:

  • Removed names: camlp-streams keeps old code building while you port it
  • Shared mutable state: a measured race and two fixes that hold
  • C stubs: a pointer from malloc goes into a custom block
  • The order that keeps the build green, with the commands to run

4 runnable examples (Python, dune, main.ml, tally_stubs.c (5.x), tally_stubs_414.c (4.14)) · about 11 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Choosing libraries, and following releases and advisories Pro: opens with a Pro, Premium or Ultimate pass

Library choices decide which compilers a project can use, and compiler point releases carry security fixes that a pinned build does not pick up by itself. Both are shown with recorded runs on OCaml 5.5.1 and the numbers in each package’s opam file.

In this part:

  • Stdlib or Base: one program written both ways
  • Eio or Lwt, chosen from your builds, your libraries and your work
  • Point releases carry the security fixes, and advisories say which

2 runnable examples (Python) · about 11 minutes

Opening this part with your pass…Pro part. It opens with the same pass as the part above.

Interview questions

A warm-up for freshers and 2–5 years: which parts of the standard library did 5.0 drop, and what takes their place?

Stream and Genlex left the standard library and live on in the camlp-streams package; new code reads a Seq.t with Seq.uncons instead. Pervasives, an old name for Stdlib, is gone, so Pervasives.print_endline becomes print_endline. The standalone bigarray library went too, because Bigarray is part of the standard library. Values deprecated for years, such as String.set, whose job Bytes.set does on bytes, were removed in the same release, and 4.14’s alerts named most of them in advance.

Three harder questions follow; sketch an answer to each before you open it.

  1. Mid to senior

    A billing service runs on OCaml 4.14. Its config reader uses Stream, a module-level Hashtbl caches tariffs, two C stubs wrap a C library handle, and its web layer is Dream on Lwt. Plan its move to OCaml 5.5.1: what you do, in which order, and what has to keep building on 4.14 until when.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    After a move to OCaml 5.5.1, a service parses requests on four domains. A module-level Hashtbl memoises a slow tariff lookup: find_opt, then add on a miss. Under load the table ends with more bindings than distinct keys, and nothing failed at build time. Explain the cause, fix it and prove the fix.

    Model answer, Pro. First step and follow-ups

  3. Senior to staff

    Your services build with OCaml 5.5.1, pinned in CI, and a security advisory is published against the compiler's demarshaling. One service unmarshals a cache file that other machines write. What do you check, what do you ship today, and what do you change for good?

    Model answer, Pro. First step and follow-ups

Flashcards · 5 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. What did OCaml 5.0 remove that 4.14 had marked deprecated?

    Stream, Genlex, Pervasives, the standalone bigarray library and long-deprecated values such as String.set.

  2. Why does a 4.14 tokenizer stop on OCaml 5.5.1 with Unbound module Stream?

    OCaml 5.0 removed Stream. The Seq port, which returns the rest of the sequence instead of consuming it, printed the same seven tokens.

  3. Why must a Seq port of a tokenizer return the rest of the input?

    A Stream passed to two functions was consumed by the first, but the sequence String.to_seq builds starts from the same place each time it is read, so take_while returns (word, rest).

  4. In what order does an OCaml 5 migration go?

    The removed names first; then shared mutable state and C stubs, which compile cleanly but need Atomic or Mutex and custom blocks.

  5. What is a library's compiler floor, and where do OCaml's security fixes arrive?

    The oldest compiler it installs on: 4.14 for Lwt 6.1.2 and 5.2 for Eio 1.6. Security fixes arrive in point releases.

Key takeaways

  • Six feature releases followed 4.14, and 5.0 removed Stream, Genlex, Pervasives, the standalone bigarray library and long-deprecated values such as String.set, most of which 4.14 had marked deprecated.
  • On OCaml 5.5.1 the old tokenizer stopped at its first Stream call, and the Seq port, which returns the rest of the sequence instead of consuming it, printed the same seven tokens.
  • An OCaml 5 migration fixes the removed names first; shared mutable state and C stubs compile cleanly and need Atomic or Mutex and custom blocks.
  • Across the ecosystem, every dependency has an oldest compiler, from 4.14 for Lwt 6.1.2 to 5.2 for Eio 1.6, and security fixes arrive in point releases.

Terms in this lesson

breaking change
A change in a new release of a compiler or library after which some programs that worked with the previous release no longer build or no longer behave the same; OCaml's Changes file marks such entries with an asterisk.
deprecation
A notice that a function or module is due to be removed in a later release, shown as an alert wherever code uses it; OCaml 4.14 deprecated Stream and Genlex before OCaml 5.0 removed them.
naked pointer
A pointer to memory outside the OCaml heap stored directly as an OCaml value, with no block around it. OCaml 4 allowed it in C stubs; OCaml 5 does not, so the pointer goes inside a block the runtime knows.
point release
A release that changes only the last number of a version, such as 5.5.1 after 5.5.0: it fixes bugs and security problems in one release series instead of adding features.
security advisory
A public notice that some versions of a compiler or library have a security flaw, saying which versions are affected and which release or change fixes it.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.