Pourquoi les plages ne peuvent-elles pas être utilisées pour la fonctionnalité de bibliothèque de tuyaux?

10

Jonathan Boccara (auteur de Fluent C ++ ) a écrit une bibliothèque appelée pipes .

Ce "piping", dit la page principale du référentiel, ne ressemble pas à l'utilisation de plages, même s'il a la même apparence: il n'est pas basé sur un tir paresseux, mais plutôt sur une poussée désireuse. Mais il est indiqué que l'on ne peut pas utiliser la bibliothèque de plages pour effectuer diverses opérations de «pipe». Par exemple:

  • dézipper - Prenez une entrée zippée - une gamme de k-tuples essentiellement - et produisez k sorties indépendantes distinctes.
  • fork - Produisez plusieurs copies (indépendantes) d'un conteneur / d'une plage.

Je ne comprends pas très bien pourquoi, en principe, c'est le cas. (Bien sûr, à l'exception des plages où vous ne pouvez pas obtenir l'itérateur / sentinelle final.)

einpoklum
la source

Réponses:

7

Ce qui est discuté est essentiellement la différence entre une méthodologie de traitement basée sur la poussée et une méthodologie basée sur l'extraction. Dans un système push comme cette bibliothèque de tuyaux, vous établissez une chaîne de traitement, et chaque étape de traitement pousse ses données directement dans la suivante. Dans un système de type pull, vous établissez une représentation des données, à laquelle vous pouvez accéder et modifier si nécessaire. Le traitement ne se fait pas tout seul; cela ne se produit que lorsque quelqu'un tente de consommer la gamme.

Les opérations unzipet forksont toutes deux des opérations un à plusieurs: elles prennent une seule entrée et la mappent à de nombreuses opérations de traitement.

En tant que système push, la bibliothèque de canaux peut gérer des opérations un-à-plusieurs en raison de la structure de son API. Une opération est représentée par un appel de fonction; l'entrée est impliquée par le point d'utilisation (en l'utilisant >>=ou en la passant à un processeur). Les paramètres de la fonction définissent sa sortie (en ignorant les paramètres destinés au processeur lui-même). Et comme les fonctions C ++ peuvent avoir des nombres arbitraires de paramètres, une opération de mappage un à plusieurs tombe naturellement. Vous fournissez simplement des processeurs appropriés pour les différentes sorties.

En tant que système d'extraction, les plages sont basées sur les valeurs de retour. C ++ n'a pas de mécanisme de langage pour renvoyer plusieurs valeurs, donc le mieux que nous puissions faire est de renvoyer une "valeur" qui représente plusieurs valeurs.

Cependant, le chaînage de l'adaptateur de plage est finalement basé sur les entrées qui sont des plages . Et une "'valeur' ​​qui représente plusieurs valeurs" n'est pas en soi une plage. Il peut contenir des plages, mais cela n'en fait pas une plage.

Alors maintenant, vous devez prendre ce type très certainement "pas une gamme" et faire fonctionner tous vos adaptateurs de gamme avec lui. L'application d'un adaptateur de plage doit diffuser cette opération sur le type, créant ainsi une opération plusieurs-à-plusieurs. Ce n'est pas facile.

Mais plus important encore ... ce n'est probablement pas ce que vous voulez . Si vous avez forkune plage, vous voudrez certainement effectuer un traitement différent sur les plages répliquées. Et cela ferme complètement toute chance d'utiliser l' |opération pour le faire. Vous devrez créer des moyens d'appliquer des adaptateurs à des parties spécifiques de ces tuples de plage. Et ces moyens vont de plus en plus ressembler à un processeur push.

À la fin de la journée, un système de type pull n'a qu'une sortie à chaque niveau. Cela fait partie du concept de base d'une telle API: chaque étape de traitement génère une plage. Cela a ses avantages (traitement paresseux) mais représenter des opérations un-à-plusieurs est l'un de ses points faibles.

Les plages peuvent certainement avoir une unzipfonction (il forks'agit simplement de copier la plage). Mais ce ne serait pas un |adaptateur de style; ce serait une fonction qui prend une plage sur un type décomposable et renvoie un tuple de plages. Si vous souhaitez effectuer plus de traitement avec eux, vous devez alors stocker le tuple dans une valeur, accéder aux éléments individuels et les utiliser comme bon vous semble.

Nicol Bolas
la source