Слово о iota и enumerate

Может быть Вы помните о том, с чего наш блог начинался…

Вначале был уникальный язык программирования под названием Icon, которым мы увлекались некоторое время назад. Он пленил нас своей простотой и продуманностью, а также своей сверхвысокоуровневостью и необычной концепцией генераторов. Потом мы познакомились с D, который пошел гораздо дальше, воплотив в жизнь концепцию диапазонов.

Именно о некоторых интересных алгоритмах над диапазонами (в основном, над числовыми) сегодня и поговорим.

Представьте, вы оперируете непрерывным множеством чисел от какого-то минимального и какого-то максимального, и вам нужно что-то сделать с каждым из элементов такого множества…
Первая идея, которая приходит Вам в голову будет выглядеть примерно так:
for (int i = minimum; i < maximum; i++)
{
 // некоторое действие
}

где minimum — начало диапазона чисел, maximum — его конец (и строго говоря, необязательно, чтобы тип переменной был int, но надеюсь идею вы поймете).

Однако, в стандартной библиотеке D есть интересный алгоритм iota (в модуле std.range), который принимает в качестве аргументов от двух до трех параметров: начальный элемент, конечный элемент и необязательный параметр, который задает шаг:

auto r = iota(0.0, 0.5, 0.1);

Этот пример показывает создание числового диапазона от 0.0 до 0.5 (не включая) с шагом в 0.1, и в некоторых приложениях, в сочетании с таким интересными шаблонами как map и each из стандартной библиотеки может стать одной из любопытных замен для стандартных циклов.

Другим интересным алгоритмом является алгоритм enumerate, который использует такую классную идею D, как кортежи типов.

Что делает enumerate?

Все очень просто: enumerate принимает некоторый диапазон (необязательно, числовой, кстати) и некоторое число (необязательный параметр), начиная с которого алгоритма начнет нумеровать элементы входного диапазона:

auto r = [0, 2, 4, 6, 8];
auto t = r.enumerate(0);

foreach (pair; t)
{
   writeln(pair[0], " , ", pair[1]);
}

Данный пример выведет набор пар t в виде «номер , элемент_массива_r«, т.е. по сути дела, создаст список пар индекс-значения, и отсчет будет начат с нуля. Весь фокус тут заключается в том, что enumerate генерирует список пар, который является одним элементом, состоящим из разных типов (такая штука называется кортежем типов). Кортеж типов, в данном случае, состоит из двух элементов — номера и элемента входного диапазона, а к его содержимому можно обратиться по индексам 0 и 1.

Не поверите, насколько творчески можно использовать эти простые алгоритмы, если применить смекалку и изобретательность!

P.S.: Вот вам пример. Жаль только без кода…

Однажды в интерфейсе одной программы необходимо было задать значения для QComboBox, которые были статичны и имелись в простом массиве строк. Цикл для этого не был пригоден, так как кода было уже много и наличие даже небольшого цикла в интерфейсной части могло бы сбить с толку. После недолгих раздумий была сделана нумерация массива строк с помощью enumerate, а добавление в QComboBox реализовано через each.

В итоге, две строки кода, которые очень хорошо читаются.

Добавить комментарий