cppProgrammer
cppProgrammer

Reputation: 349

What are some good practices for building enumerations in Elixir?

Obviously atoms are the best choice for enumeration values. But these are not associated with or castable to integers.

I think struct might be the way to go. The code below works.

defmodule ElixirTesting do

  import ExUnit.Assertions

  defmodule IceCreamFlavorEnumeration do
    defstruct vanilla: 0, chocolate: 1, peanut_butter: 2
  end

  def test_enumeration do

    e = %IceCreamFlavorEnumeration{}

    v = e.vanilla
    c = e.chocolate
    p = e.peanut_butter

    assert v < c
    assert c < p

  end
end

However, integer values can be re-assigned by users of the struct. Even re-assigned to non-integer values I believe. That’s not acceptable if exposed in an API.

Consider an api such as this:

void addKeplerContribution(PositionAngle type, double gm, double[] pDot)

or one in which the integer value is used in a mathematical sense (to convert to milliseconds – this is a made-up function):

enum DurationType {
  MILLISECONDS = 1,
  SECONDS = 1e3,
  MINUTES = 60e3,
  ...
}
void addMilliseconds(DurationType type, double duration_value) {
  ...
  milliseconds = duration_value * (int)type;
  ...
}

A keyword list might be an alternative. Any other suggestions?

Upvotes: 0

Views: 163

Answers (1)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

We normally use pattern-matching for this.

@type interval :: :millis | :seconds | :minutes
@spec add_interval(interval(), integer()) :: integer()
def add_interval(:millis, duration) when is_integer(duration),
  do: duration
def add_interval(:seconds, duration) when is_integer(duration),
  do: duration * 1_000
def add_interval(:minutes, duration) when is_integer(duration),
  do: duration * 1_000 * 60

That way might look not familiar at the first glance, but it’s the way to go. You explicitly disallow calling this function with somewhat unknown as the first parameter and you accept integers only as the second parameter.

Upvotes: 3

Related Questions