パイプライブラリ機能に範囲を使用できないのはなぜですか?


10

Jonathan Boccara(Fluent C ++の作者)がpipesというライブラリを作成しました。

リポジトリのメインページにあるこの「パイピング」は、見た目は同じですが、範囲の使用とは異なります。遅延プルではなく、積極的なプッシュに基づいています。しかし、範囲ライブラリを使用してさまざまな「パイプ」操作を実行することはできないと述べられています。例えば:

  • unzip-圧縮された入力(基本的に一連のkタプル)を取り、kの独立した独立した出力を生成します。
  • fork-コンテナー/範囲の複数の(独立した)コピーを生成します。

なぜそうなるのか、原理的にはよくわかりません。(もちろん、終了イテレータ/センチネルを取得できない範囲を除いて。)

回答:


7

議論されているのは、本質的にはプッシュベースの処理方法とプルベースの方法の違いです。このパイプライブラリのようなプッシュシステムでは、一連の処理を確立し、各処理ステップでデータを次のステップに直接プッシュします。範囲のようなプルシステムでは、データの表現を確立し、必要に応じてアクセスおよび変更できます。処理はそれ自体では発生しません。誰かが範囲を消費しようとしたときにのみ発生します。

unzipおよびfork操作は、両方の1対多の操作です:彼らは、単一の入力を取り、多くの処理操作にマップします。

プッシュシステムとして、APIの構造により、パイプライブラリは1対多の操作を処理できます。操作は関数呼び出しで表されます。入力は、使用ポイント(使用>>=またはプロセッサへの受け渡し)によって暗示されます。関数のパラメーターは、その出力を定義します(プロセッサー自体のパラメーターは無視します)。また、C ++関数は任意の数のパラメーターを持つことができるため、1対多のマッピング操作は自然に失敗します。さまざまな出力に適切なプロセッサを供給するだけです。

プルシステムとして、範囲は戻り値に基づいています。C ++には、複数の値を返すための言語メカニズムがないため、複数の値を表す「値」を返すことが最善の方法です。

ただし、範囲アダプターの連鎖は、最終的には範囲である入力に基づいています。また、「複数の値を表す「値」」自体は範囲ではありません。範囲を含めることはできますが、範囲にはなりません。

だから今、あなたはこれを非常に間違いなく「範囲ではない」タイプにして、すべての範囲アダプタをそれで動作させる必要があります。範囲アダプターを適用すると、その操作が型全体にブロードキャストされ、多対多の操作が作成されます。それを行うのは簡単ではありません。

しかし、もっと重要なことに...それはおそらくあなたが望むものではありませfork範囲の場合、ほぼ確実に、複製された範囲に対して異なる処理を実行する必要があります。そして、それは|操作を使用してそれを行う可能性を完全にシャットダウンします。これらの範囲タプルの特定の部分にアダプターを適用する方法を構築する必要があります。そして、これらの方法はますますプッシュベースのプロセッサのように見えるでしょう。

結局のところ、プルスタイルのシステムでは、各レベルに1つの出力しかありません。これは、このようなAPIのコアコンセプトの一部にすぎません。各処理ステップ範囲が生成されます。これには利点(遅延処理)がありますが、1対多の操作を表すことは、その弱点の1つです。

範囲は確かにunzip機能を持つことができます(fork本当に範囲をコピーするだけです)。しかし、それは|スタイルアダプタではありません。これは、分解可能な型の範囲を取り、範囲のタプルを返す関数です。それらを使用してさらに処理を行う場合は、タプルを値に格納し、個々の要素にアクセスして、必要に応じてそれらを使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.