exercism/elixir/grade-school/lib/school.ex

45 lines
1.1 KiB
Elixir

defmodule School do
@moduledoc """
Simulate students in a school.
Each student is in a grade.
"""
@type school :: any()
@doc """
Create a new, empty school.
"""
@spec new() :: school
def new(), do: %{}
@doc """
Add a student to a particular grade in school.
"""
@spec add(school, String.t(), integer) :: {:ok | :error, school}
def add(school, name, grade) do
if Enum.any?(roster(school), &(&1 == name)) do
{:error, school}
else
{:ok, Map.put(school, grade, [name | Map.get(school, grade, [])])}
end
end
@doc """
Return the names of the students in a particular grade, sorted alphabetically.
"""
@spec grade(school, integer) :: [String.t()]
def grade(school, grade) when not is_map_key(school, grade), do: []
def grade(school, grade), do: Enum.sort(Map.get(school, grade))
@doc """
Return the names of all the students in the school sorted by grade and name.
"""
@spec roster(school) :: [String.t()]
def roster(school) do
for grade <- Enum.sort(Map.keys(school)), reduce: [] do
acc -> acc ++ grade(school, grade)
end
end
end