Por que os intervalos não podem ser usados ​​para a funcionalidade da biblioteca de pipes?

10

Jonathan Boccara (autor do Fluent C ++ ) escreveu uma biblioteca chamada pipes .

Essa "canalização", diz a página principal do repositório, não é como o uso de intervalos, embora pareça o mesmo: não se baseia em puxões preguiçosos, mas sim em empurrões ansiosos. Mas afirma-se que não se pode usar a biblioteca de intervalos para executar várias operações de 'pipe'. Por exemplo:

  • descompacte - tire uma entrada compactada - uma gama de k-tuplas essencialmente - e produz k saídas independentes e separadas.
  • fork - Produza várias cópias (independentes) de um contêiner / intervalo.

Não entendo bem por que, em princípio, é esse o caso. (É claro que, com exceção dos intervalos em que você não pode obter o iterador / sentinela final.)

einpoklum
fonte

Respostas:

7

O que está sendo discutido é essencialmente a diferença entre uma metodologia de processamento por push e outra por pull. Em um sistema push como essa biblioteca de canais, você estabelece uma cadeia de processamento e cada etapa do processamento envia seus dados diretamente para a próxima. Em intervalos do tipo pull-system, você estabelece uma representação de dados, que pode acessar e modificar conforme necessário. O processamento não acontece por si só; isso acontece apenas quando alguém tenta consumir o intervalo.

As operações unzipe forksão operações um para muitos: elas pegam uma única entrada e mapeiam para muitas operações de processamento.

Como um sistema push, a biblioteca de pipes pode lidar com operações de um para muitos devido à estrutura de sua API. Uma operação é representada por uma chamada de função; a entrada está implícita no ponto de uso (usando >>=ou passando para um processador). Os parâmetros da função definem sua saída (ignorando os parâmetros destinados ao próprio processador). E como as funções C ++ podem ter números arbitrários de parâmetros, uma operação de mapeamento de um para muitos cai naturalmente. Você simplesmente fornece processadores apropriados para as várias saídas.

Como um sistema pull, os intervalos são baseados nos valores de retorno. O C ++ não possui mecanismo de linguagem para retornar vários valores; portanto, o melhor que podemos fazer é retornar um "valor" que represente vários valores.

No entanto, o encadeamento do adaptador de faixa é basicamente baseado nas entradas que são faixas . E um "'valor' que representa vários valores" não é, por si só, um intervalo. Pode conter intervalos, mas isso não faz dele um intervalo.

Portanto, agora você precisa usar esse tipo definitivamente "sem alcance" e fazer com que todos os seus adaptadores funcionem com ele. A aplicação de um adaptador de intervalo deve transmitir essa operação pelo tipo, criando uma operação muitos para muitos. Fazer isso não é fácil.

Mas o mais importante ... provavelmente não é isso que você deseja . Se você forkpossui um intervalo, quase certamente deseja fazer um processamento diferente nos intervalos replicados. E isso interrompe completamente qualquer chance de usar a |operação para fazer isso. Você precisará criar maneiras de aplicar adaptadores a partes específicas dessas tuplas de intervalo. E essas maneiras serão cada vez mais parecidas com um processador baseado em push.

No final do dia, um sistema pull-style possui apenas uma saída em cada nível. Isso é apenas parte do conceito principal de uma API: cada etapa do processamento gera um intervalo. Isso tem suas vantagens (processamento lento), mas representar operações um para muitos é uma de suas áreas fracas.

As faixas certamente podem ter uma unzipfunção ( forké realmente apenas copiar o intervalo). Mas não seria um |adaptador de estilo; seria uma função que assume um intervalo sobre algum tipo decomponível e retorna uma tupla de intervalos. Se você deseja fazer mais processamento com eles, será necessário armazenar a tupla em um valor, acessar os elementos individuais e usá-los como achar melhor.

Nicol Bolas
fonte