Mengapa rentang tidak dapat digunakan untuk fungsi pustaka pipa?

10

Jonathan Boccara (penulis Fluent C ++ ) menulis perpustakaan yang disebut pipa .

"Perpipaan" ini, halaman utama repositori mengatakan, tidak seperti penggunaan rentang, meskipun terlihat sama: Ini tidak didasarkan pada tarikan yang malas, tetapi lebih mendorong dengan bersemangat. Tetapi dinyatakan bahwa seseorang tidak dapat menggunakan perpustakaan rentang untuk melakukan berbagai operasi 'pipa'. Sebagai contoh:

  • unzip - Ambil input zip - kisaran k-tuple dasarnya - dan menghasilkan k, output independen terpisah.
  • fork - Menghasilkan banyak (independen) salinan wadah / rentang.

Saya tidak begitu mengerti mengapa, pada prinsipnya, itulah masalahnya. (Tentu saja dengan pengecualian rentang di mana Anda tidak bisa mendapatkan iterator / sentinel akhir.)

einpoklum
sumber

Jawaban:

7

Apa yang dibahas pada dasarnya adalah perbedaan antara metodologi pemrosesan berbasis push dan yang berbasis pull. Dalam sistem push seperti pustaka pipa ini, Anda membuat rantai pemrosesan, dan setiap langkah pemrosesan mendorong datanya langsung ke yang berikutnya. Dalam rentang seperti sistem tarik, Anda membuat representasi data, yang dapat Anda akses dan modifikasi sesuai kebutuhan. Pemrosesan tidak terjadi dengan sendirinya; itu terjadi hanya ketika seseorang mencoba untuk mengkonsumsi rentang tersebut.

The unzipdan forkoperasi keduanya operasi satu-ke-banyak: mereka mengambil input tunggal dan peta ke banyak operasi pengolahan.

Sebagai sistem dorong, pustaka pipa dapat menangani operasi satu-ke-banyak karena struktur API-nya. Operasi diwakili oleh panggilan fungsi; input tersirat pada titik penggunaan (menggunakan >>=atau meneruskannya ke prosesor). Parameter fungsi menentukan outputnya (mengabaikan parameter yang dimaksudkan untuk prosesor itu sendiri). Dan karena fungsi C ++ dapat memiliki jumlah parameter yang berubah-ubah, operasi pemetaan satu-ke-banyak secara alami tidak berlaku. Anda cukup memasok prosesor yang sesuai untuk berbagai output.

Sebagai sistem penarik, rentang didasarkan pada nilai balik. C ++ tidak memiliki mekanisme bahasa untuk mengembalikan beberapa nilai, jadi yang terbaik yang bisa kita lakukan adalah mengembalikan "nilai" yang mewakili beberapa nilai.

Namun, rangkaian adaptor rangkaian pada akhirnya didasarkan pada input yang berada dalam rentang . Dan "'nilai' yang mewakili beberapa nilai" itu sendiri bukan rentang. Mungkin berisi rentang, tetapi itu tidak membuatnya menjadi rentang.

Jadi sekarang Anda harus mengambil tipe "bukan rentang" yang sangat pasti ini dan membuat semua adaptor rentang Anda bekerja dengannya. Menerapkan adaptor jangkauan harus menyiarkan operasi itu di seluruh tipe, menciptakan operasi banyak ke banyak. Melakukan itu tidak mudah.

Tetapi yang lebih penting ... itu mungkin bukan yang Anda inginkan . Jika Anda forksuatu rentang, maka Anda hampir pasti ingin melakukan pemrosesan yang berbeda pada rentang yang direplikasi. Dan itu sepenuhnya menutup kemungkinan menggunakan |operasi untuk melakukan itu. Anda harus membangun cara untuk menerapkan adaptor ke bagian spesifik rentang-tupel ini. Dan cara-cara itu semakin terlihat seperti prosesor berbasis push.

Pada akhirnya, sistem gaya tarik hanya memiliki satu output di setiap level. Itu hanya bagian dari konsep inti dari API semacam itu: setiap langkah pemrosesan menghasilkan a kisaran. Ini memiliki kelebihan (pemrosesan malas) tetapi mewakili operasi satu-ke-banyak adalah salah satu area yang lemah.

Rentang tentu saja dapat memiliki unzipfungsi ( forkbenar-benar hanya menyalin rentang). Tapi itu tidak akan menjadi |adaptor gaya; itu akan menjadi fungsi yang mengambil rentang beberapa jenis terurai dan mengembalikan tupel rentang. Jika Anda ingin melakukan lebih banyak pemrosesan dengan mereka, maka Anda perlu menyimpan tuple dalam suatu nilai, mengakses elemen-elemen individual, dan menggunakannya sesuai keinginan Anda.

Nicol Bolas
sumber