在 Elixir 中构建枚举有哪些好的做法?

What are some good practices for building enumerations in Elixir?

显然原子是枚举值的最佳选择。但是这些与整数无关或不可转换为整数。

我认为结构可能是可行的方法。下面的代码有效。

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

但是,结构的用户可以重新分配整数值。我相信甚至重新分配给非整数值。如果暴露在 API.

中,这是不可接受的

考虑 api 例如 this:

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

或者在数学意义上使用整数值(转换为毫秒——这是一个虚构的函数):

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

关键字列表可能是替代方法。还有其他建议吗?

我们通常为此使用模式匹配。

@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

这条路乍一看可能不熟悉,但这是必经之路。您明确禁止调用此函数时将有点未知作为第一个参数,并且您只接受整数作为第二个参数。