Dlaczego zakresów nie można używać do funkcji biblioteki rur?

10

Jonathan Boccara (autor Fluent C ++ ) napisał bibliotekę o nazwie pipe .

Ta „piping”, jak głosi strona główna repozytorium, nie przypomina używania zakresów, chociaż wygląda tak samo: nie opiera się na leniwym ciągnięciu, ale raczej chętnym pchaniu. Ale to stwierdził, że nie można korzystać z biblioteki zakresów do wykonywania różnych operacji „rury”. Na przykład:

  • rozpakuj - Pobierz skompresowane dane wejściowe - zasadniczo zakres k-krotek - i wygeneruj k osobnych, niezależnych wyników.
  • fork - Wyprodukuj wiele (niezależnych) kopii kontenera / zakresu.

Nie do końca rozumiem, dlaczego w zasadzie tak jest. (Oczywiście z wyjątkiem zakresów, w których nie można uzyskać iteratora końcowego / wartownika.)

einpoklum
źródło

Odpowiedzi:

7

Omawiana jest zasadniczo różnica między metodologią przetwarzania opartą na wypychaniu a metodologią opartą na pobieraniu. W systemie wypychania, takim jak ta biblioteka potoków, ustanawiasz łańcuch przetwarzania, a każdy krok przetwarzania wypycha swoje dane bezpośrednio do następnego. W systemach typu pull-system, tworzysz reprezentację danych, do której możesz uzyskać dostęp i modyfikować w razie potrzeby. Przetwarzanie nie odbywa się samo z siebie; zdarza się to tylko wtedy, gdy ktoś próbuje wykorzystać zasięg.

unzipI forkoperacje są obie operacje jeden-do-wielu: biorą jedno wejście i mapować go do wielu operacji przetwarzania.

Jako system wypychania biblioteka potoków może obsługiwać operacje jeden do wielu ze względu na strukturę interfejsu API. Operacja jest reprezentowana przez wywołanie funkcji; dane wejściowe są implikowane przez punkt użytkowania (użycie >>=lub przekazanie do procesora). Parametry funkcji określają jej wynik (ignorując parametry przeznaczone dla samego procesora). A ponieważ funkcje C ++ mogą mieć dowolną liczbę parametrów, naturalnie wypada operacja mapowania jeden do wielu. Po prostu dostarczasz odpowiednie procesory dla różnych wyjść.

Jako system ściągania zakresy oparte są na wartościach zwracanych. C ++ nie ma mechanizmu językowego do zwracania wielu wartości, więc najlepsze, co możemy zrobić, to zwrócić „wartość” reprezentującą wiele wartości.

Jednak łączenie adapterów zakresu jest ostatecznie oparte na wejściach będących zakresami . A „wartość” reprezentująca wiele wartości ” sama w sobie nie jest zakresem. Może zawierać zakresy, ale to nie oznacza, że ​​jest to zakres.

Więc teraz musisz wziąć ten zdecydowanie „nie będący zakresem” i sprawić, by wszystkie adaptery działały z nim. Zastosowanie adaptera zasięgu musi rozgłaszać tę operację dla danego typu, tworząc operację wiele do wielu. Nie jest to łatwe.

Ale co ważniejsze ... prawdopodobnie nie tego chcesz . Jeśli masz forkzakres, to prawie na pewno chcesz wykonać inne przetwarzanie w replikowanych zakresach. A to całkowicie ogranicza szansę wykorzystania |operacji do tego celu. Musisz opracować sposoby zastosowania adapterów do określonych części tych krotek zakresu. I te sposoby będą coraz bardziej przypominały procesor push.

Pod koniec dnia system w stylu pull ma tylko jedną moc wyjściową na każdym poziomie. To tylko część główną koncepcją takiego API: każdy etap przetwarzania generuje się zasięg. Ma to swoje zalety (leniwe przetwarzanie), ale reprezentowanie operacji jeden do wielu jest jednym z jego słabych obszarów.

Zakresy z pewnością mogą mieć jakąś unzipfunkcję ( forktak naprawdę po prostu kopiują zakres). Ale to nie byłby |adapter stylu; byłaby to funkcja, która przejmuje zakres w stosunku do pewnego rodzaju rozkładalnego i zwraca krotkę zakresów. Jeśli chcesz wykonać z nimi więcej przetwarzania, musisz przechowywać krotkę w wartości, uzyskać dostęp do poszczególnych elementów i używać ich, jak uważasz.

Nicol Bolas
źródło