Кортеж

Кортеж — тип данных в Эрланге, предназначенный для группировки нескольких (часто разнородных) термов в новый, единый терм. То же: tuple.

Кортеж выглядит как фигурные скобки, внутри которых через запятые перечислены его элементы. Элементы могут быть разнотипными. При этом элементы в свою очередь тоже могут быть сложными термами. В следующем примере кортеж состоит из элементов: атом, строка, атом, целое число, список.

1> { my_name, "Vasya", age, 18, [151, 229, 388] }. 
{my_name,"Vasya",age,18,[151,229,388]}

Наглядный пример использования кортежа — хранение цвета в формате RGB. Каждый из трёх цветов может иметь числовое представление в диапазоне 0..255. Как это сделать. Тут у нас есть несколько вариантов. Во-первых, мы можем хранить всё в одной целочисленной переменной: 16#dc143c (например). Здесь dc отвечает за красный, 14 — за зелёный, 3c — за синий. Во-вторых, мы можем завести три переменные:

1> R = 16#dc. 
220
2> G = 16#14.
20
3> B = 16#3c. 
60

Этот вариант часто удобнее первого, потому что мы без лишних телодвижений можем получить значение каждой из трёх составляющих цвета. Минус этого подхода — придётся завести три переменные, которые никак между собой не связаны. Если дело происходит в какой-нибудь небольшой функции, это не проблема. Но если код довольно сложный и запутанный, мы можем ошибиться и, например, подумать, что G это не зелёный цвет, а, скажем, год рождения или вес в граммах.

В-третьих, мы можем хранить наши цвета в кортеже.

4> Cvet = {220, 20, 60}. 
{220,20,60}

Кортеж удобен для хранения и передачи связанных между собой данных. RGB — типичный пример связанных между собой переменных. Другой пример — координаты точки XY или XYZ.

Эти данные группируются, а потом их можно в любой момент разгруппировать. Допустим, нас интересует только зелёный цвет.

6> {_, Grn, _} = Cvet. 
{220,20,60}
7> Grn. 
20

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

Кортежи сами по себе не содержат именованных полей. Если надо как-то уточнить содержание, можно добавить просто дополнительный атом: { age, 18 }. Также для удобства программиста можно использовать записи, которые, оставаясь кортежем, обретают при этом именованные поля.

Кортеж, как и другие термы, сразу конкретен, он сразу конструируется из значений и становится значением. При создании кортежа нельзя использовать переменные, к которым пока ещё не привязаны значения.

1> X = 10.
10
2> XY = {X, Y}. 
* 1:10: variable 'Y' is unbound

Чем кортеж отличается от списка?

Кортежи очень похожи на списки. И там и там можно сгруппировать любое количество термов в один. Использование кортежей похоже на использование списков. То же самое RGB можно сгруппировать в список:

1> Cvet = [220, 20, 60]. 
[220,20,60]
2> [_, Grn, _] = Cvet. 
[220,20,60]
3> Grn. 
20

Как показали мои опыты, разница в скорости работы списков и кортежей несущественная.

Отличие, во-первых, чисто стилистическое. В списки принято группировать такие элементы, количество которых нам заранее не известно. Допустим, мы анализируем текстовые файлы и каждую строку берём как отдельный элемент. Количество таких элементов может быть разным, поэтому мы их и сохраняем в список. И конечно, за редким исключением, список содержит элементы одного типа. Было бы странным, если в нашем списке вперемешку были строки и, допустим, номера страниц книги, на которых эти строки располагаются. Впрочем, если надо, так тоже можно сделать, но обработка таких гетерогенных списков заметно усложнится.

В кортежах напротив — количество элементов заранее известно. Например, на стадии проектирования программы нами определено, что цвет будет определяться в формате RGB или RGBA, поэтому мы и создадим кортеж, включающий три или четыре элемента. Аналогично и с координатами точки. Если нам нужны координаты XY, это будет ясно уже на стадии проектирования программы, поэтому мы создаём кортеж из двух элементов. Если надо XYZ, то будет из трёх элементов. Раз количество элементов заранее известно, значит, элементы кортежа могут быть разных типов. Например, строка для ФИО нашего юзера, целое число для его возраста и атом пола.

Поэтому обычно списки применяют для группировки однородных элементов в неопределённом количестве, а кортежи для группировки неоднородных элементов в определённом количестве.

Во-вторых, частью языка является обработчик списка, обладающий богатыми возможностями, и он предназначен именно для списков, а не кортежей. Ну и наличие таких модулей как lists заставляет нас использовать именно списки для группировки однородных элементов в неопределённом количестве.

Как узнать размер кортежа?

Иногда хочется знать, сколько элементов в том или ином кортеже. Для этого есть биф size.

1> Cvet = {128, 64, 0}. 
{128,64,0}
2> size(Cvet). 
3

© Алексей Карманов, 2024.