Quick StartTryGuideAPICommunityBlogGitHub

List & ArraySuggest an edit


Lists are:

  • homogeneous
  • immutable
  • fast at prepending items
let myList = [1, 2, 3];

Reason lists are simple, singly linked list.


You'd use list for its resizability, its fast prepend (adding at the head), and its fast split, all of which are immutable yet efficient!

The standard lib provides a List module (and its counterpart with labeled arguments, ListLabels).

Immutable Prepend

Use the spread syntax, which is just List.cons:

let myList = [1, 2, 3];
let anotherList = [0, ...myList];

myList didn't mutate. anotherList is now [0, 1, 2, 3]. This is efficient (constant time, not linear). anotherList's last 3 elements are shared with myList!

Note that [a, ...b, ...c] is a syntax error. We don't support multiple spread for a list. That'd be an accidental linear operation (O(b)), since each item of b would be one-by-one added to the head of c. You can use List.concat for this.

Updating an arbitrary item in the middle of a list is discouraged, since its performance and allocation overhead would be linear (O(n)).


switch (described in the pattern matching section) is usually used to access list items:

let message = switch myList {
| [] => "This list is empty"
| [a,] => "The head of the list is the string " ^ a

To access an arbitrary list item, use List.nth.

Tips & Tricks

Feel free to allocate as many empty lists as you'd like. As explained in the variant section for list, an empty list is actually a parameter-less variant constructor under the hood, which compiles to a mere integer. No extra memory allocation needed.

To understand how prepend can be immutable and O(1) at the same time, see the explanation of list's underlying representation.

Design Decisions

In the future, we might provide an out-of-the-box list data structure that's immutable, resizable and features all-around fast operations, such as Immutable-re (still work in progress!).


Arrays are like lists, except they are:

  • mutable
  • fast at random access & updates
  • fix-sized on native (flexibly sized on JavaScript)

You'd surround them with [| and |].

let myArray = [|"hello", "world", "how are you"|];


Standard library Array and ArrayLabel module. For JS compilation, you also have the familiar Js.Array bindings API.

Access & update an array item like so:

let myArray = [|"hello", "world", "how are you"|];

let firstItem = myArray.(0); /* "hello" */

myArray.(0) = "hey";

/* now [|"hey", "world", "how are you"|] */

The above array access/update is just syntax sugar for Array.get/Array.set.

Tips & Tricks

If you're compiling to JavaScript, know that Reason arrays map straightforwardly to JavaScript arrays, and vice-versa. Thus, even though arrays are fix-sized on native, you can still use the Js.Array API to resize them. This is fine.