Arrays And Collections: Collections

The Hack Collection types are Vector, ImmVector, Map, ImmMap, Set, ImmSet and Pair. There are also a range of helper interfaces, discussed below.

Hack Collection types are objects. They have reference semantics, so they can be mutated.

Collections define a large number of methods you can use. They also support array style syntax. Idiomatic Hack prefers array access syntax over methods, e.g. $v[0] is better than $v->at(0).

This page focuses on the core operations available, which all have array access syntax. Consult the reference pages (e.g. Vector) for the full list of methods.

Vector and ImmVector

Where possible, we recommend using vec instead.

A Vector is a mutable ordered data structure.

// Creating a Vector.
function get_items(): Vector<string> {
  $items = Vector {'a', 'b', 'c'};
  return $items;
}

// Accessing items by index.
$items[0]; // 'a'
$items[3]; // throws OutOfBoundsException

// Accessing items that might be out-of-bounds.
idx($items, 0); // 'a'
idx($items, 3); // null
idx($items, 3, 'default'); // 'default'

// Modifying items. This mutates the Vector in place.
$items[0] = 'xx'; // Vector {'xx', 'b', 'c'}
$items[] = 'd'; // Vector {'xx', 'b', 'c', 'd'}

// Getting the length.
C\count($items); // 4

// Iterating.
foreach ($items as $item) {
  echo $item;
}
// Iterating with the index.
foreach ($items as $index => $item) {
  echo $index; // e.g. 0
  echo $item; // e.g. 'a'
}

// Equality checks compare references.
$items === $items; // true
Vector {} === Vector {}; // false

// Converting from an Iterable.
new Vector(vec[1, 2]); // Vector {1, 2}
new Vector(Set {1, 2}); // Vector {1, 2}
new Vector(dict['key1' => 'value1']); // Vector {'value1'}

// Type checks
$items is Vector<_>; // true

ImmVector is an immutable version of Vector.

// Creating an ImmVector.
function get_items(): ImmVector<string> {
  $items = ImmVector {'a', 'b', 'c'};
  return $items;
}

Set and ImmSet

Where possible, we recommend using keyset instead.

A Set is a mutable, ordered, data structure without duplicates. It can only contain string or int values.

// Creating a Set.
function get_items(): Set<string> {
  $items = Set {'a', 'b', 'c'};
  return $items;
}

// Checking if a Set contains a value.
C\contains_key($items, 'a'); // true

// Modifying items. This mutates the Set in place.
$items[] = 'd'; // Set {'a', 'b', 'c', 'd'}
$items[] = 'a'; // Set {'a', 'b', 'c', 'd'}

// Getting the length.
C\count($items); // 4

// Iterating.
foreach ($items as $item) {
  echo $item;
}

// Equality checks compare references.
$items === $items; // true
Set {} === Set {}; // false

// Converting from an Iterable.
new Set(vec[1, 2, 1]); // Set {1, 2}
new Set(Vector {20, 21}); // Set {20, 21}
new Set(dict['key1' => 'value1']); // Set {'value1'}

// Type checks.
$items is Set<_>; // true

ImmSet is an immutable version of Set.

// Creating an ImmSet.
function get_items(): ImmSet<string> {
  $items = ImmSet {'a', 'b', 'c'};
  return $items;
}

Map and ImmMap

Where possible, we recommend using dict instead.

A Map is a mutable, ordered, key-value data structure. Keys must be strings or ints.

// Creating a Map.
function get_items(): Map<string, int> {
  $items = Map {'a' => 1, 'b' => 3};
  return $items;
}

// Accessing items by key.
$items['a']; // 1
$items['z']; // throws OutOfBoundsException

// Accessing keys that may be absent.
idx($items, 'a'); // 1
idx($items, 'z'); // null
idx($items, 'z', 'default'); // 'default'

// Modifying items. This mutates the Map in place.
$items['a'] = 42; // Map {'a' => 42, 'b' => 3}
$items['z'] = 100; // Map {'a' => 42, 'b' => 3, 'z' => 100}

// Getting the keys.
Vec\keys(Map {'a' => 1, 'b' => 3}); // vec['a', 'b']

// Getting the values.
vec(Map {'a' => 1, 'b' => 3}); // vec[1, 3]

// Getting the length.
C\count($items); // 3

// Iterating values.
foreach ($items as $value) {
  echo $value;
}
// Iterating keys and values.
foreach ($items as $key => $Value) {
  echo $key;
  echo $value;
}

// Equality checks compare references.
$items === $items; // true
Map {} === Map {}; // false

// Converting from an Iterable.
new Map(dict['key1' => 'value1']); // Map { 'key1' => 'value1'}
new Map(vec['a', 'b']); // Map {0 => 'a', 1 => 'b'}

// Type checks
$items is Map<_>; // true

ImmMap is an immutable version of Map.

// Creating an ImmMap.
function get_items(): ImmMap<string, int> {
  $items = ImmMap {'a' => 1, 'b' => 3};
  return $items;
}

Pair

Where possible, we recommend using tuple instead.

A Pair is an immutable data structure with two items.

function get_items(): Pair<int, string> {
  $items = Pair {42, 'foo'};
  return $items;
}

// Destructuring a Pair value.
list($x, $y) = $items; // $x: 42, $y: 'foo'

// Accessing elements by index.
$items[0]; // 42
$items[1]; // 'foo'

Interfaces

Hack Collections implement a range of helper interfaces, so your code can handle multiple Hack Collection types.

If you want to handle both Hack arrays and Hack Collections, use Traversable. If you want to read and write a Hack Collection, use Collection. If you only want to read a Hack Collection, use ConstCollection.

The ConstCollection interface represents Hack Collections that be can read from.

 ConstCollection
  +-- ConstVector
  |    +-- ImmVector
  |    +-- Pair
  +-- ConstSet
  |    +-- ImmSet
  +-- ConstMap
  |    +-- ImmMap
  +-- Collection
       +-- MutableVector
       |    +-- Vector
       +-- MutableMap
       |    +-- Map
       +-- MutableSet
            +-- Set

The OutputCollection interface represents Hack Collections that be can written to.

 OutputCollection
  +-- Collection
       +-- MutableVector
       |    +-- Vector
       +-- MutableMap
       |    +-- Map
       +-- MutableSet
            +-- Set