Unicode в Erlang

Введение

Реализации строк как отдельного типа в Erlang-е нет. Вместо этого используются списки с ASCII значениями. Двойные кавычки (") представляют собой синтаксический сахар для более удобной записи и в конечном счете значение заключенное в них преобразуется в список.

1> [104, 101, 108, 108, 111].
"hello"
2> [$h, $e, $l, $l, $o].
"hello"

Юникодные строки

Юникодные строки, представляются в виде набора юникодных точек, например строка "Привет, мир" будет выглядеть следующим образом:

1> "Привет, мир".
[1055,1088,1080,1074,1077,1090,44,32,1084,1080,1088]

До версии Erlang/OTP R16 все юникодные строки (в том числе и бинарные) компилировались в бинарное представление (по 2-а байта на каждую юникодную точку для кириллицы):

[208,159,209,128,208,184,208,178,208,181,209,130,44,32,208,188,208,184,209,128]
В результате вывод на экран можно осуществлять 'как есть', однако при работе с таким представлением будут сложности:
String = "Привет, мир",
io:format("~s~n", [String]),
io:format("length: ~w~n", [length(String)]).
После компиляции вывод будет следующим:
Привет, мир
length: 20
Замечание! При работе через Erlang Emulator представление будет в виде кодовых точек.
С версии Erlang/OTP R16 появилась возможность задать кодировку исходного файла посредством добавления комментария:
%% -*- coding: utf-8 -*-
В результате строка будет представлена как и положено посредством юникодных точек но для вывода необходимо указывать дополнительный модификатор t и выставлять кодировку:
String = "Привет, мир",
io:setopts([{encoding, utf8}]),
io:format("length: ~w~n", [length(String)]),
io:format("~ts~n", [String]).
Привет, мир
length: 11

Начиная с Erlang/OTP R17 кодировка по умолчанию для исходных файлов изменена на UTF-8, поэтому необходимости в задании специального комментария уже нет. С версии Erlang/OTP 18.0 также появится поддержка юникода для атомов что означает поддержку в том числе функций и имен модулей.

Юникод в бинарном представлении

В бинарном представленни для кириллицы данные кодируется по два байта на юникодную точку.

<<"Привет, мир">>.
<<208,159,209,128,208,184,208,178,208,181,209,130,44,32,
                      208,188,208,184,209,128>

<<"Привет, мир"/utf8>>.
<<195,144,194,159,195,145,194,128,195,144,194,184,195,
                      144,194,178,195,144,194,181,195,145,194,130,44,32,195,
                      144,194,188,195,144,194,184,195,145,194,128>>
Начиная с версии Erlang/OTP R17 (либо и в Erlang/OTP R16 если указана кодировка исходного файла как UTF-8), в качестве представления берется младший байт юникодной точки.
<<"Привет, мир">>.
<<31,64,56,50,53,66,44,32,60,56,64>>

<<"Привет, мир"/utf8>>.
<<208,159,209,128,208,184,208,178,208,181,209,130,44,32,
  208,188,208,184,209,128>>
Другими словами начиная с Erlang/OTP R17 юникодная строка для бинарного представления урезается, а в случае когда указан модификатор utf8 кодируется по два байта на кодовую точку (для кириллицы).

Для информации! Длина представления определяется по контрольным битам, поэтому зависит от номера кодовой точки. Диапазон 0x80 - 0x07FF (128 - 2047) куда входит кириллица кодируется по 2-а байта.

Ссылки

Архив