Почему нельзя использовать диапазоны для функциональности библиотеки каналов? - PullRequest
10 голосов
/ 05 марта 2020

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

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

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

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

1 Ответ

7 голосов
/ 06 марта 2020

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

Операции unzip и fork являются операциями «один ко многим»: они принимают один вход и сопоставляют его со многими операциями обработки.

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

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

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

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

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

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

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

...