次のプログラムどう思いますか?
defmodule Extract do
def get_value(string, desired_key) do
parts = String.split(string, "&")
Enum.find_value(parts, fn pair ->
key_value = String.split(pair, "=")
Enum.at(key_value, 0) == desired_key && Enum.at(key_value, 1)
end)
end
end
&で分割して、key=valueの組をつくって、desired_keyをキーとする値を求めるプログラムですね。
これで問題なく動きます。
達人プログラマーに確か、エラーは早い段階で検出する。エラーを隠して後の段階で問題が起きるような構造にしない。みたいなのがあったと思います。
このプログラムは、想定外のURL形式でもエラーになりません。
iex> Elixir101.get_value("name=Lucas&university=UFMG&lab=ASERG", "lab")
"ASERG"
iex> Elixir101.get_value("name=Lucas&university=institution=UFMG&lab=ASERG", "university")
"institution"
パターンマッチングを使って記述すると、key=value1=value2の場合、マッチングできないのでエラーになります。
defmodule Extract do
def get_value(string, desired_key) do
parts = String.split(string, "&")
Enum.find_value(parts, fn pair ->
[key, value] = String.split(pair, "=") # <= pattern matching
key == desired_key && value
end)
end
end
記述も簡素になっていい感じです。
doctestで実行してみました。エラーになりました。
1) doctest Elixir101.sample1/1 (1) (Elixir101Test)
test/elixir101_test.exs:3
** (MatchError) no match of right hand side value: ["university", "institution", "UFMG"]
stacktrace:
(elixir101 0.1.0) lib/elixir101.ex:38: anonymous fn/2 in Elixir101.get_value2/2
(elixir 1.14.4) lib/enum.ex:4239: Enum.find_value_list/3
(for doctest at) lib/elixir101.ex:6: (test)
参照にしたElixirドキュメント
https://hexdocs.pm/elixir/1.16.0-rc.0/code-anti-patterns.html#non-assertive-pattern-matching