Enums

Tag-only and payload enums in Chasm, and pattern matching with case/when.

Enums define a type with a fixed set of variants. They compile to C tagged unions.

Tag-only Enums

The simplest form: a named set of variants with no attached data.

enum State { Idle, Running, Jumping, Dead }

@state :: script = State.Idle

def on_tick(dt :: float) do
  if @state == State.Idle do
    print("waiting")
  end
end

Compare enum values with == and !=.

Payload Enums

Variants can carry data. Each variant can have a different payload type:

enum Shape {
  Circle(float),
  Rect(float, float),
  Point
}

Point carries no data. Circle carries a float (the radius). Rect carries two floats (width and height).

Payload enums are most useful with case/when pattern matching, see Pattern Matching.

Pattern Matching on Enums

defp describe(s :: Shape) :: string do
  case s do
    when Circle -> "a circle"
    when Rect   -> "a rectangle"
    _           -> "a point"
  end
end

State Machines

Tag-only enums are the natural fit for game state machines:

enum GameState { Menu, Playing, Paused, GameOver }

@gs :: script = GameState.Menu

def on_tick(dt :: float) do
  if @gs == GameState.Menu do
    if key_pressed(:enter) do
      @gs = GameState.Playing
    end
  end

  if @gs == GameState.Playing do
    update_game(dt)
    if @lives <= 0 do
      @gs = GameState.GameOver
    end
  end

  if @gs == GameState.Paused do
    if key_pressed(:escape) do
      @gs = GameState.Playing
    end
  end
end

Atoms vs Enums

Atoms (:idle, :running) and enums both represent named constants. The practical difference:

AtomsEnums
DeclarationNone, write them anywhereRequires enum block
Type checkedNo (type is atom)Yes (type is EnumName)
PayloadNoYes (payload enums)
Best forQuick tags, case armsDefined sets of variants with type safety

Use atoms for quick prototyping or when the set of values is open-ended. Use enums when you want the compiler to enforce the valid set.