Коллекцию выбирают по поведению, которое должна сохранять программа: важны ли порядок и повторы, нужен ли поиск по ключу или достаточно уникальности. Включение коллекции — компактная запись фильтрации и преобразования, которая не меняет правила порядка выбранной коллекции.
Сначала выберите коллекцию
| Коллекция | Когда выбирать | Наблюдаемое поведение |
|---|---|---|
Array<T> | Нужны порядок, доступ по позиции и повторяющиеся значения | Обход по возрастанию индекса, повторы сохраняются |
Map<K, V> | Значение выбирается по ключу | Ключи хранят порядок вставки; обновление существующего ключа сохраняет его место |
Set<T> | Важна уникальность значений | Первый из равных элементов сохраняет своё место |
Запустите пример
Сохраните код в файле collections-comprehensions.tpz:
let scores = [10, 25, 10]
let labels = map { "Ada": 10, "Lin": 25 }
let unique = set { 10, 25, 10 }
let focused = [ for score in scores if score >= 20 => score * 2 ]
let first = scores[0]
let missing = scores.get(9)
let hasAda = "Ada" in labels.keys
let missingLabel = match missing {
case Some(value) => "found {value}"
case None => "missing"
}
print("{scores}:{unique.toArray()}:{labels.keys}")
print("{focused}:{first}:{hasAda}")
print(missingLabel)topaz check collections-comprehensions.tpz
topaz run collections-comprehensions.tpz
Программа напечатает:
[10, 25, 10]:[10, 25]:[Ada, Lin]
[50]:10:true
missingМассив сохраняет оба значения 10. Множество объединяет повтор и оставляет место первого 10. labels.keys возвращает массив ключей в порядке вставки, поэтому проверка принадлежности записана как "Ada" in labels.keys.
Выбирайте чтение и изменение осознанно
scores[0] читает элемент непосредственно по индексу. Отрицательный или выходящий за границы индекс останавливает программу с ошибкой выполнения. scores.get(9) — безопасное чтение: оно возвращает Option, который пример разбирает с помощью match.
Для изменения коллекции на месте корневое связывание должно быть изменяемым. Перед операцией вроде values.push(...) объявите let mut values = [...]. Неизменяемое связывание всё равно можно использовать в выражении, которое создаёт новую коллекцию.
Повтор ключа в Map обрабатывается не так, как повтор элемента в Set. Повтор простого литерального ключа — статическая ошибка. Если равенство ключей выясняется только во время выполнения, сначала вычисляются операнды, затем создание завершается ошибкой без перезаписи. Для намеренного добавления или обновления ключа используйте Map.insert.
Литерал, цикл или включение?
- Если элементы перечислены прямо в коде, используйте
[a, b],set { a, b }илиmap { key: value }. - Если тело удобнее читать как последовательность шагов, используйте
for item in source { ... }. В позиции инструкции он выполняет действия, а в позиции выражения собирает результаты тела вArray. - Если фильтр и преобразование образуют одно ясное выражение, используйте
[ for item in source if condition => result ]. Для уникальных результатов замените внешние скобки наset { ... }, а для пар ключ–значение — наmap { ... }.
Список условий включения начинается с for, продолжается операторами for или if без запятых и завершается =>. Условия вкладываются слева направо. Итоговая коллекция становится доступна только после успешного выполнения всех достигнутых условий и тел.
Частые ошибки
Типы коллекций записываются как Array<T>, Map<K, V> и Set<T>; форма [T] типом коллекции не является. Литералам множества и отображения нужны слова set и map: #{...} и голая форма {key: value} не обозначают эти коллекции.
Форма key in map недопустима — используйте key in map.keys. Несовпадение допускающего отказ шаблона во включении вызывает ошибку, а не автоматически отбрасывает элемент. Для пропуска элементов добавьте явное условие if.
Точные границы
- Раскрытие внутри массива принимает только другой
Array. Для литералов и включенийSetиMapраскрытия нет. - Пустым
set {}иmap {}нужен ожидаемый типSet<T>илиMap<K, V>. - Ключи отображения и элементы множества должны рекурсивно допускать использование в качестве ключа.
- Удаление освобождает место в порядке; повторная вставка добавляет новое место в конец. Обновление значения существующего ключа его место не меняет.
forобходитArray, целочисленные диапазоны,Setиmap.keys. Для строки нужно явно получить последовательность скаляров.
Пользовательские итераторы, генераторы, ленивые и параллельные включения, раскрытие произвольных итерируемых значений и коллекции без определённого порядка в текущий язык не входят.
Начните с урока Данные и управление. Связывания во включениях разобраны в разделе Шаблоны и управление потоком, а точные повседневные методы — в разделе Операции с коллекциями.