/var/log/messages

Mar 2, 2019 - 2 minute read - Comments - programming

プログラミング Elixir (23)

13.10 変換: テーブルに整形、の節。直前エントリで確認した通りでまんま出力すれば良いだけ感がありますが違うのかな。

以下が、な模様。

  def process({user, project, count}) do
    Issues.GithubIssues.fetch(user, project)
    |> decode_response
    |> convert_to_list_of_maps
    |> sort_into_ascending_order
    |> Enum.take(count)
    |> print_table_for_columns(["number", "created_at", "title"])
  end

直前エントリにて列挙したカラムですね。そのまんまでしょ、ってことでテキストでは実装がそのまんま列挙されています。

ありゃ?

** (CompileError) lib/issues/cli.ex:55: undefined function print_table_for_columns/2

て言われます。おかしいな、定義してるのに。

とりあえず

テストにはパスしています。

  • simple_test_data の定義誤り
  • Output is correct なテストについて、末端の空白

いくつか確認

Enum で以下とか

  • each/2
  • map/2
  • map_join/3
  • max/1

確認してみます。Enum.each/2 が Invokes the given fun for each item in the enumerable. とのこと。これはチェック済みなのかどうか。あるいは Enum.map/2 は Returns a list where each item is the result of invoking fun on each corresponding item of enumerable. とあります。each と map って微妙スね。

あるいは map_join/3 が以下。

Maps and joins the given enumerable in one pass.

joiner can be either a binary or a list and the result will be of the same type as joiner. If joiner is not passed at all, it defaults to an empty binary.

All items returned from invoking the mapper must be convertible to a binary, otherwise an error is raised.

以下な用例が引用されています。

iex> Enum.map_join([1, 2, 3], " = ", &(&1 * 2))
"2 = 4 = 6"

map_join/3 てどこで使われているのかな。

  def format_for(column_width) do
    map_join(column_width, " | ", fn width -> "~-#{width}s" end) <> "~n"
  end

  def separator(column_widths) do
    map_join(column_widths, "-+-", fn width -> List.duplicate("-", width) end)
  end

こいつら、どこで使われているのかと。ええと format_for は以下。

  def print_table_for_columns(rows, headers) do
    with data_by_columns = split_into_columns(rows, headers),
         columns_width   = width_of(data_by_columns),
         format          = format_for(columns_width)

あるいは separator は以下?

    do
         puts_one_line_in_columns(headers, format)
         IO.puts(separator(columns_width))
         puts_in_columns(data_by_columns, format)
    end

とりあえず

https://hexdocs.pm/elixir/Enum.html#map_join/3 によれば

Enum.map_join([1, 2, 3], " = ", &(&1 * 2))
"2 = 4 = 6"

とのこと。あとは max/1 ですね。て max/1 が無いぞ。とりあえず https://hexdocs.pm/elixir/Enum.html#max/2 が以下な説明。

Returns the maximal element in the enumerable according to Erlang's term ordering.

If multiple elements are considered maximal, the first one that was found is returned.

Calls the provided empty_fallback function and returns its value if enumerable is empty. The default empty_fallback raises Enum.EmptyError.

こんな例が示されています。

iex> Enum.max([1, 2, 3])
3

使われているのは以下な手続きですね。

  def width_of(columns) do
    for column <- columns, do: column |> map(&String.length/1) |> max
  end

これ、どうなのか。と思ったら

  • for の結果が map に渡されて
  • その結果が max に渡される

のか。