Почему нельзя использовать диапазоны для функциональности библиотеки каналов?

10

Джонатан Боккара (автор Fluent C ++ ) написал библиотеку под названием pipe .

Эта «труба», как гласит главная страница репозитория, не похожа на использование диапазонов, даже если она выглядит одинаково: она не основана на ленивом вытягивании, а скорее на энергичном толчке. Но заявлено, что нельзя использовать библиотеку диапазонов для выполнения различных «конвейерных» операций. Например:

  • Распакуйте - Возьмите сжатый вход - по сути, диапазон k-кортежей - и создайте k отдельных независимых выходов.
  • fork - создает несколько (независимых) копий контейнера / диапазона.

Я не совсем понимаю, почему, в принципе, это так. (Конечно, за исключением диапазонов, где вы не можете получить конечный итератор / страж.)

einpoklum
источник

Ответы:

7

То, что обсуждается, по сути, является различием между методологией обработки, основанной на push, и методологией, основанной на pull. В push-системе, подобной этой библиотеке каналов, вы создаете цепочку обработки, и каждый шаг обработки направляет свои данные непосредственно на следующий. В вытянутой системе, подобной диапазонам, вы устанавливаете представление данных, к которому вы можете обращаться и изменять по мере необходимости. Обработка не происходит сама по себе; это происходит только тогда, когда кто-то пытается использовать диапазон.

unzipИ forkоперации как один-к-многим операции: они занимают один вход и отобразить его на многих технологических операций.

Как система push, библиотека pipe может обрабатывать операции «один ко многим» из-за структуры своего API. Операция представлена ​​вызовом функции; вход подразумевается точкой использования (использование >>=или передача его процессору). Параметры функции определяют ее вывод (игнорируя параметры, предназначенные для самого процессора). А поскольку функции C ++ могут иметь произвольное количество параметров, операция отображения «один ко многим» естественным образом выпадает. Вы просто поставляете соответствующие процессоры для различных выходов.

Как и в случае вытягивающей системы, диапазоны основаны на возвращаемых значениях. В C ++ нет языкового механизма для возврата нескольких значений, поэтому лучшее, что мы можем сделать, это вернуть «значение», которое представляет несколько значений.

Тем не менее, цепочка адаптера диапазона в конечном итоге основывается на входах, являющихся диапазонами . И «значение», представляющее несколько значений » само по себе не является диапазоном. Он может содержать диапазоны, но это не делает его диапазоном.

Так что теперь вы должны использовать этот тип «не диапазона» и заставить все ваши адаптеры диапазона работать с ним. Применение адаптера диапазона должно передавать эту операцию по типу, создавая операцию «многие ко многим». Делать это не легко.

Но что еще более важно ... это, вероятно, не то, что вы хотите . Если вы forkдиапазон, то вы почти наверняка захотите выполнить другую обработку на реплицированных диапазонах. И это полностью исключает любую возможность использования |операции для этого. Вам нужно будет создать способы применения адаптеров к определенным частям этих кортежей. И эти способы все больше будут выглядеть как процессоры на основе push.

В конце концов, у системы стиля тяги есть только один выход на каждом уровне. Это только часть основной концепции такого API: каждый шаг обработки генерирует в диапазон. Это имеет свои преимущества (ленивая обработка), но представление операций «один ко многим» является одной из его слабых сторон.

Диапазоны, безусловно, могут иметь unzipфункцию ( forkна самом деле это просто копирование диапазона). Но это не был бы |адаптер стиля; это была бы функция, которая принимает диапазон для некоторого разложимого типа и возвращает кортеж диапазонов. Если вы хотите выполнить дополнительную обработку с ними, вам нужно будет сохранить кортеж в значении, получить доступ к отдельным элементам и использовать их по своему усмотрению.

Николь Болас
источник