13.8 変換: データを並び替える、の節。
Enum.sort/2
パイプでどんどん繋いでいくさまがとても気持ち良いですね。ベルトコンベアな「デザイン」というのも分かりやすくて良いです。また、今回については試験も作っています。
def process([user, project, _count]) do
Issues.GithubIssues.fetch(user, project)
|> decode_response
|> convert_to_list_of_maps
|> sort_into_ascending_order
end
def decode_response({:ok, body}), do: body
def docode_response({:error, error}) do
{_, message} = List.keyfind(error, "message", 0)
IO.puts "Error fetching from Github: #{message}"
System.halt(2)
end
def convert_to_list_of_maps(list) do
list
|> Enum.map(&Enum.into(&1, Map.new))
end
def sort_into_ascending_order(list_of_issues) do
Enum.sort list_of_issues
fn l1, l2 -> l1["created_at"] <= l2["created_at"] end
end
今回は sort に渡してる手続きな比較が大丈夫なのかどうかが心配なので試験を書くとのこと。issues/test
配下に試験があるのは良いのですがいくつかの試験が既に欠いてある状態 (後天性記憶不全?)。以下を追加しています。
issues/test/cli_test.exs
test "sort ascending orders the correct way" do
result = sort_into_ascending_order(fake_created_at_list(["c", "b", "a"]))
issues = for issue <- result, do: issue["created_at"]
assert issues == ~2{a, b, c}
end
defp fake_created_at_list(values) do
data = for value <- values, do: [{"created_at", value}, {"other_data", "xxx"}]
convert_to_list_of_maps data
end
で、試験実行してみるに
== Compilation error in file lib/issues/github_issues.ex ==
ええと、github_issues.exs が以下になってました。
@github_url Application.get_env(:issues, github_url:)
以下に修正。
@github_url Application.get_env(:issues, :github_url)
で再度試験実行。
$ mix test
....
1) test sort ascending orders the correct way (CliTest)
test/cli_test.exs:22
** (FunctionClauseError) no function clause matching in Access.get/3
The following arguments were given to Access.get/3:
# 1
{:cont, []}
# 2
"created_at"
# 3
nil
Attempted function clauses (showing 5 out of 5):
def get(%module{} = container, key, default)
def get(map, key, default) when is_map(map)
def get(list, key, default) when is_list(list) and is_atom(key)
def get(list, key, _default) when is_list(list)
def get(nil, _key, default)
code: issues = for issue <- result, do: issue["created_at"]
stacktrace:
(elixir) lib/access.ex:316: Access.get/3
(issues) lib/issues/cli.ex:71: anonymous fn/2 in Issues.CLI.sort_into_ascending_order/1
(elixir) lib/enum.ex:2979: Enum.reduce/3
test/cli_test.exs:24: (test)
..
Finished in 0.1 seconds
2 doctests, 5 tests, 1 failure
Randomized with seed 801121
ありゃ、色々駄目じゃないスか。そもそも試験の記述もきちんと理解できていないのでそこから確認します。
むむむ
~w
は sigil でした。iex にて確認。
iex(1)> ~w{a b c}
["a", "b", "c"]
あ、comma で区切ってましたorz
assert issues == ~w{a, b, c}
ただしくは以下。
assert issues == ~w{a b c}
で、試験実行してみたのですがまだ駄目ですね。メセジてきにも変化なし。
発見orz
こうなっておりました。
def sort_into_ascending_order(list_of_issues) do
Enum.sort list_of_issues
fn l1, l2 -> l1["created_at"] <= l2["created_at"] end
end
これで sort_into_ascending_order から手続きオブジェクトが戻されてた模様。以下に修正して
def sort_into_ascending_order(list_of_issues) do
Enum.sort list_of_issues,
fn l1, l2 -> l1["created_at"] <= l2["created_at"] end
end
テスツ合格。
$ mix test
.......
Finished in 0.2 seconds
2 doctests, 5 tests, 0 failures
Randomized with seed 363252
IO.inspect
を使って云々しました。
test "sort ascending orders the correct way" do
result = sort_into_ascending_order(fake_created_at_list(["c", "b", "a"]))
IO.inspect(result)
issues = for issue <- result, do: issue["created_at"]
IO.inspect(issues)
assert issues == ~w{a b c}
end
出力が以下。
$ mix test
.[
%{"created_at" => "a", "other_data" => "xxx"},
%{"created_at" => "b", "other_data" => "xxx"},
%{"created_at" => "c", "other_data" => "xxx"}
]
["a", "b", "c"]
......
Finished in 0.1 seconds
2 doctests, 5 tests, 0 failures
Randomized with seed 711905
以下を試そうとしたのですが
require IEx; IEx.pry
これは iex
使ってないとダウトらしいです。
この節
さくっと流せると思ってたら微妙なハマり方をしてしまいましたorz