defmodule SpaceAge do @type planet :: :mercury | :venus | :earth | :mars | :jupiter | :saturn | :uranus | :neptune @planets ~w(mercury venus earth mars jupiter saturn uranus neptune)a defguardp is_planet(planet) when planet in @planets defp factor(:mercury), do: 0.2408467 defp factor(:venus), do: 0.61519726 defp factor(:earth), do: 1.0 defp factor(:mars), do: 1.8808158 defp factor(:jupiter), do: 11.862615 defp factor(:saturn), do: 29.447498 defp factor(:uranus), do: 84.016846 defp factor(:neptune), do: 164.79132 @doc """ Return the number of years a person that has lived for 'seconds' seconds is aged on 'planet', or an error if 'planet' is not a planet. """ @spec age_on(planet, pos_integer) :: {:ok, float} | {:error, String.t()} def age_on(planet, seconds) when is_planet(planet), do: {:ok, seconds / (factor(planet) * 31_557_600)} def age_on(_planet, _seconds), do: {:error, "not a planet"} end