Arrays And Collections: Mutating Values

Hack arrays are value types. This makes your code easier to reason about, faster (no work required on a fresh web request), and well suited for caches.

If you really need mutation, Hack provides you with several options.

Updating value types

Updating an element in a value type creates a new copy.

function update_value(vec<int> $items): vec<int> {
  // Both of these operations set $items a modified copy of the
  // original value.
  $items[0] = 42;
  $items[] = 100;
  return $items;
}

function demo(): void {
  $v = vec[1, 2];
  // $v is unaffected by this function call.
  $v2 = update_value($v);
  
  PHP\var_dump($v); // vec[1, 2]
  PHP\var_dump($v2); // vec[42, 2, 100]
}

Value types are shallow. A mutable type inside a value type is mutated by reference.

class Person {
  public function __construct(public string $name) {}
}

function update_person(vec<Person> $items): void {
  $items[0]->name = "new";
}

function demo(): void {
  $v = vec[new Person("old")];
  
  update_person($v);
  
  PHP\var_dump($v); // vec[Person { name: "new" }]
}

Using inout to simulate mutability

You can often use inout parameters instead of mutation. This copies the modified parameters back to the locals of the caller.

function update_value(inout vec<int> $items): void {
  $items[0] = 42;
  $items[] = 100;
}

function demo(): void {
  $v = vec[1, 2];
  update_value(inout $v);

  PHP\var_dump($v); // vec[42, 2, 100]
}

Using Ref for shallow mutability

The Ref class provides a single value that can be mutated.

function update_value(Ref<vec<int>> $items): void {
  $inner = $items->get();
  $inner[0] = 42;
  $inner[] = 100;
  $items->set($inner);
}

function demo(): void {
  $v = new Ref(vec[1, 2]);
  update_value($v);

  PHP\var_dump($v->get()); // vec[42, 2, 100]
}

Using Collections for mutability

All the Collection classes are mutable. We recommend using Hack arrays wherever possible, but you can use Vector, Set or Map if you really need to.

function update_value(Vector<int> $items): void {
  $items[0] = 42;
  $items[] = 100;
}

function demo(): void {
  $v = Vector {1, 2};
  update_value($v);

  PHP\var_dump($v); // Vector {42, 2, 100}
}