[Elixir]withとelseとguardsと。

Elixir 1.3では、 with に対して elseguards を使えるということで、少し試してみました。1.3の時と、1.2.4の時で無理やり書いた時。

http://tuvistavie.com/tokyo.ex

簡単な、 %{width: 10, height: 20} から値を取得して、それに対して幾つかのエラーケースを実践するという内容です。

1.3

さっとまとまる。


defmodule S do
@opts %{width: 10, height: 20}
# iex> S.neko_success
# {10, 20}
def neko_success do
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} when height > 10 <- Map.fetch(@opts, :height) do
IO.inspect {width, height}
else
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error -> IO.inspect other_error
end
end
# Map.fetch(@opts, :h) が失敗してしまう。
# iex> S.neko_fail_map
# :error
def neko_fail_map do
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} when height > 10 <- Map.fetch(@opts, :h) do
IO.inspect {width, height}
else
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error -> IO.inspect other_error
end
end
# Map.fetchは全て正しいが、guardで失敗するので `with` では失敗する
# iex> S.neko_fail_guard
# "failed in {:ok, height}"
def neko_fail_guard do
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} when height < 10 <- Map.fetch(@opts, :height) do
IO.inspect {width, height}
else
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error -> IO.inspect other_error
end
end
end

1.2.4

読みにくい感じ。不具合増えそうだ。


defmodule S do
@opts %{width: 10, height: 20}
# iex> S.neko_success
# {10, 20}
def neko_success do
result =
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} <- Map.fetch(@opts, :height) do
case height do
x when x > 10 -> {width, height}
_ -> {:ok, height}
end
end
case result do
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error when not is_tuple(other_error) -> IO.inspect other_error
other -> IO.inspect result
end
end
# Map.fetch(@opts, :h) が失敗してしまう。
# iex> S.neko_fail_map
# :error
def neko_fail_map do
result =
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} <- Map.fetch(@opts, :h) do
case height do
x when x > 10 -> {width, height}
_ -> {:ok, height}
end
end
case result do
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error when not is_tuple(other_error) -> IO.inspect other_error
other -> IO.inspect result
end
end
# Map.fetchは全て正しいが、guardで失敗するので `with` では失敗する
# iex> S.neko_fail_guard
# "failed in {:ok, height}"
def neko_fail_guard do
result =
with {:ok, width} <- Map.fetch(@opts, :width),
{:ok, height} <- Map.fetch(@opts, :height) do
case height do
x when x < 10 -> {width, height}
_ -> {:ok, height}
end
end
case result do
{:ok, 20} -> IO.inspect "failed in {:ok, height}"
{:error, message} -> IO.inspect {:error, message}
other_error when not is_tuple(other_error) -> IO.inspect other_error
other -> IO.inspect result
end
end
end

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.