Enuma
View SourceRust-like Enums for Elixir. Enuma makes it easy to define rich enumeration types similar to Rust, while maintaining Elixir's pattern matching capabilities.
Features
- Define structured enum types with named variants
- No runtime performance overhead due to compile-time evaluation of macros
- Variants can contain no data or structured data
- Pattern matching on enum variants
- Guard-compatible matching with
is_*
macros - Optional Ecto integration for database storage
Installation
Add enuma
to your list of dependencies in mix.exs
:
def deps do
[
{:enuma, "~> 0.1.0"}
]
end
Usage
Enuma uses atoms for simple items and tuples for complex items (items with arguments). All Enuma enuma helpers are macros so it will not have any runtime impact on performance.
Basic Usage
defmodule Shape do
use Enuma
defenum do
item :circle, args: [float()] # Circle with radius
item :rectangle, args: [float(), float()] # Rectangle with width and height
item :triangle
end
end
# Creating enum values
circle = Shape.circle(5.0) # {:circle, 5.0}
rect = Shape.rectangle(4.0, 3.0) # {:rectangle, 4.0, 3.0}
triangle = Shape.triangle() # :triangle
# Require is needed to use the Enuma helpers since they are macros
require Shape
def calculate_area(shape) do
case shape do
Shape.circle(r) -> :math.pi() * r * r
Shape.rectangle(w, h) -> w * h
Shape.triangle() -> raise "Area calculation for triangle not implemented"
end
end
# Guard expressions
def print_shape(shape) when Shape.is_circle(shape) do
Shape.circle(radius) = shape
IO.puts("Circle with radius #{radius}")
end
Ecto Integration
Enuma provides Ecto integration for storing enum values in the database:
defmodule DrawingObject do
use Ecto.Schema
schema "drawing_objects" do
# Using map serialization to support all shape variants including those with parameters
# Using string serialization only works with enums only holding simple types (no arguments)
field :shape, Enuma.Ecto, type: Shape, ecto_type: :map
timestamps()
end
end
The :map
serialization format supports all variant types, storing them in the database as JSON-compatible maps:
- Simple variants like
:triangle
are stored as%{"key" => "triangle", "values" => []}
- Complex variants like
{:circle, 5.0}
are stored as%{"key" => "circle", "values" => [5.0]}
- Multi-parameter variants like
{:rectangle, 4.0, 3.0}
are stored as%{"key" => "rectangle", "values" => [4.0, 3.0]}
Using with changesets:
import Ecto.Changeset
# Valid values include all variants from your enum definition
params = %{
shape: Shape.circle(5.0)
}
# Cast and validate enum values
changeset =
%DrawingObject{}
|> cast(params, [:shape])
|> validate_required([:shape])
Read more about Ecto integration in the Enuma.Ecto
module documentation.
Documentation
Complete documentation is available at https://hexdocs.pm/enuma.
License
MIT License. See LICENSE file for details.