Reputation: 349
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
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