Enums: Functions

Enums are scalar types, but they act like objects in a couple of ways. First, they are namespaceable. Secondly, you access enum member values like you do class constants. Thirdly, there are 6 static functions available to every enum.

assert()

assert() takes a value, tries to cast it to the underlying enum type. If it can, it returns the casted value (e.g., the type of which is the enum name); otherwise it will throw an UnexpectedValueException.

<?hh

namespace Hack\UserDocumentation\API\Enums\AssertFunc;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

class MyCalendar {
  public static function get_next_day_int(int $day): Day {
    if ($day > 0 && $day < 8) {
      // We know that $day is in the enum value range, so we can assert that
      // we are converting to one that exists.
      return self::get_next_day(Day::assert($day));
    }
    return Day::SUNDAY;
  }

  public static function get_next_day(Day $day): Day {
    // assert here two since we want to cast to add the days
    return $day !== Day::SATURDAY ? Day::assert((int) $day + 1) : Day::SUNDAY;
  }
}

var_dump(MyCalendar::get_next_day_int(4)); // int(5)
var_dump(MyCalendar::get_next_day(Day::SATURDAY)); // int(1)
Output
int(5)
int(1)

This example shows how assert() can be used to get the Day enum member value given a value of its underlying type int. Since there is a check making sure the provided int is in the proper range, we can be confident that we won't get a runtime exception for using a value that doesn't exist in the enum.

assertAll()

assertAll() takes a container of values, tries to cast each one to the underlying enum type. If it can for all values, it returns a container of casted values; otherwise it will throw an UnexpectedValueException.

<?hh

namespace Hack\UserDocumentation\API\Enums\AssertAllFunc;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

class MyCalendar {
  public static function get_latest_day_int(Vector<int> $days): Day {
    if (min($days) > 0 && max($days) < 8) {
      // We know that all values in $days are in the enum value range,
      // so we can assert that we are converting to one that exists.
      // assertAll returns a Container, so make sure to create a new
      // Vector from it.
      return self::get_latest_day(new Vector(Day::assertAll($days)));
    }
    return Day::SUNDAY;
  }

  public static function get_latest_day(Vector<Day> $days): Day {
    return max($days);
  }
}

var_dump(MyCalendar::get_latest_day_int(Vector {4, 6, 3})); // int(6)
var_dump(MyCalendar::get_latest_day(
  Vector {Day::WEDNESDAY, Day::SATURDAY})
); // int(7)
Output
int(6)
int(7)

This example shows how assertAll() can be used to get the Day enum member values given a Vector of its underlying type int. Since there is a check making sure the provided ints in the Vector are in the proper range, we can be confident that we won't get a runtime exception for using a value that doesn't exist in the enum.

Note that assertAll() returns a Container (which is a child of Traversable, so in order we need to create a new Vector from that Container and pass it to get_latest_day().

coerce()

Similar to assert(), but instead of throwing an exception when the cast cannot happen, it returns null.

<?hh

namespace Hack\UserDocumentation\API\Enums\Coerce;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

class MyCalendar {
  public static function get_next_day_int(int $day): ?Day {
    // coerce will return null if the underlying type value isn't an enum
    // member value
    $coerced = Day::coerce($day);
    return $coerced ? self::get_next_day($coerced) : null;
  }

  public static function get_next_day(Day $day): ?Day {
    // assert here two since we want to cast to add the days
    return $day !== Day::SATURDAY ? Day::assert((int) $day + 1) : Day::SUNDAY;
  }
}

var_dump(MyCalendar::get_next_day_int(4)); // int(5)
var_dump(MyCalendar::get_next_day(Day::SATURDAY)); // int(1)
Output
int(5)
int(1)

This example shows how coerce() can be used to get the Day enum member value given a value of its underlying type int. Since coerce() returns null if the given int is not a member value of the enum Day, we just return null from get_next_day_int() if it can't be found.

getNames()

getNames() returns an array mapping the enum member values to their names. An InvariantException is thrown if the enum values are not unique.

<?hh

namespace Hack\UserDocumentation\API\Enums\GetNames;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

function check_name(string $name): bool {
  return in_array($name, Day::getNames());
}

var_dump(check_name("SUNDAY")); // bool(true)
var_dump(check_name("NOPE")); // bool(false)

/*

Day::getNames() returns this:

array(7) {
  [1]=>
  string(6) "SUNDAY"
  [2]=>
  string(6) "MONDAY"
  [3]=>
  string(7) "TUESDAY"
  [4]=>
  string(9) "WEDNESDAY"
  [5]=>
  string(8) "THURSDAY"
  [6]=>
  string(6) "FRIDAY"
  [7]=>
  string(8) "SATURDAY"
}

*/
Output
bool(true)
bool(false)

This example shows how you can use getNames() to get the names of the Day enum (e.g., "SUNDAY") and check that array against a provided name to determine existence.

getValues()

getValues() returns an array mapping the enum member names to their values.

<?hh

namespace Hack\UserDocumentation\API\Enums\GetValues;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

var_dump(Day::getValues());

/*

Day::getValues() returns this:

array(7) {
  ["SUNDAY"]=>
  int(1)
  ["MONDAY"]=>
  int(2)
  ["TUESDAY"]=>
  int(3)
  ["WEDNESDAY"]=>
  int(4)
  ["THURSDAY"]=>
  int(5)
  ["FRIDAY"]=>
  int(6)
  ["SATURDAY"]=>
  int(7)
}

*/
Output
array(7) {
  ["SUNDAY"]=>
  int(1)
  ["MONDAY"]=>
  int(2)
  ["TUESDAY"]=>
  int(3)
  ["WEDNESDAY"]=>
  int(4)
  ["THURSDAY"]=>
  int(5)
  ["FRIDAY"]=>
  int(6)
  ["SATURDAY"]=>
  int(7)
}

This example simply shows the format of what a call to getValues() would output on the Day enum.

isValid()

isValid takes a value and returns a bool depending on whether that value exists in the enum.

<?hh

namespace Hack\UserDocumentation\API\Enums\isValid;

enum Day: int {
  SUNDAY = 1;
  MONDAY = 2;
  TUESDAY = 3;
  WEDNESDAY = 4;
  THURSDAY = 5;
  FRIDAY = 6;
  SATURDAY = 7;
}

function check_value(int $value): bool {
  return Day::isValid($value);
}

var_dump(check_value(3)); // bool(true)
var_dump(check_value(9)); // bool(false)
Output
bool(true)
bool(false)

This example shows how isValid() can be used to determine whether a given underlying value of the Day enum type (in this case int) is a member value of Day.