Как распечатать значения массива карт в Elixir?

Новое в Elixir от Ruby, и я пытаюсь распечатать значения массива карт, используя следующий код:

Карта-script.ex

list = [0, 1]
map = %{0 => [1, 2], 1 => [2, 3]}

Enum.each list, fn n ->
  IO.puts map[n]
end

Вывод:

^A^B
^B^C

Что я делаю не так? Эликсир похож на Ruby, но он ведет себя по-другому....

Ответ 1

Вы должны использовать IO.inspect вместо IO.puts для печати внутреннего представления значения:

iex> IO.puts [1, 2]
^A^B                          # prints "^A^B"
:ok                           # return value of IO.puts

iex> IO.inspect [1, 2]
[1, 2]                        # prints "[1, 2]"
[1, 2]                        # return value of IO.inspect

Однако у вас могут возникнуть проблемы с некоторыми специальными значениями:

iex> IO.inspect [97, 98]
'ab'                          # prints "'ab'"
'ab'                          # return value of IO.inspect

Чтобы объяснить это поведение, нам нужно понять, как струны работают в Elixir. Существует два типа строк. Двоичные строки (двойные кавычки) и списки символов (одинарные кавычки). Внутри они построены из простых примитивов. Двоичные строки построены из двоичных файлов, а списки символов создаются из списков:

iex> "ab"                    # a binary string
"ab"

iex> <<97, 98>>              # the same string in binary syntax
"ab"

iex> 'ab'                    # a character list
'ab'

iex> [97, 98]                # the same character list in list syntax
'ab'

Сначала это может показаться запутанным, но это происходит из-за двух вещей. Во-первых, нет встроенного строкового типа, поскольку мы видели, что строки построены из других примитивных типов. Во-вторых, в Elixir нет определенных пользователем типов. Поэтому, когда Elixir видит список только с целыми числами, он пытается распечатать его как строку для удобства. Однако под капотом это еще только список целых чисел.

В приведенных выше примерах 97 и 98 представляют собой коды кода юникода для символов a и b поэтому они будут показаны в виде строки, даже если используется IO.inspect.

Теперь вы можете понять, почему это напечатало ^A^B в ваших примерах - это только контрольные символы из ASCII-кодировки, которые, как представляется, представлены кодовыми точками 1 и 2.

Однако вы можете передать параметр char_lists: :as_lists, чтобы печатать исходные списки без попытки сделать такое преобразование:

iex> IO.inspect [97, 98], char_lists: :as_lists
[97, 98]                                         # prints '[97, 98]'
'ab'                                             # Iex still shows the return value as 'ab'

Если вы откроете iex и введите h Inspect.Opts, вы увидите, что Elixir делает подобные вещи с другими значениями, а именно с структурами и двоичными файлами.