Những gì đang được thảo luận về cơ bản là sự khác biệt giữa phương pháp xử lý dựa trên đẩy và phương pháp xử lý dựa trên kéo. Trong một hệ thống đẩy như thư viện ống này, bạn thiết lập một chuỗi xử lý và mỗi bước xử lý sẽ đẩy dữ liệu của nó trực tiếp vào kế tiếp. Trong một hệ thống kéo như các phạm vi, bạn thiết lập một biểu diễn dữ liệu mà bạn có thể truy cập và sửa đổi khi cần. Việc xử lý không tự xảy ra; nó chỉ xảy ra khi ai đó cố gắng tiêu thụ phạm vi.
Các hoạt động unzip
và fork
cả hai hoạt động một-nhiều: chúng lấy một đầu vào duy nhất và ánh xạ nó tới nhiều hoạt động xử lý.
Là một hệ thống đẩy, thư viện ống có thể xử lý các hoạt động một-nhiều do cấu trúc API của nó. Một hoạt động được đại diện bởi một cuộc gọi chức năng; đầu vào được ngụ ý bởi điểm sử dụng (sử dụng >>=
hoặc chuyển nó tới bộ xử lý). Các tham số của hàm xác định đầu ra của nó (bỏ qua các tham số có nghĩa là cho chính bộ xử lý). Và vì các hàm C ++ có thể có số lượng tham số tùy ý, nên một hoạt động ánh xạ một-nhiều tự nhiên rơi ra. Bạn chỉ cần cung cấp bộ xử lý thích hợp cho các đầu ra khác nhau.
Là một hệ thống kéo, phạm vi dựa trên các giá trị trả về. C ++ không có cơ chế ngôn ngữ để trả về nhiều giá trị, vì vậy điều tốt nhất chúng ta có thể làm là trả về một "giá trị" đại diện cho nhiều giá trị.
Tuy nhiên, chuỗi bộ điều hợp phạm vi cuối cùng dựa trên các đầu vào là phạm vi . Và một "giá trị" đại diện cho nhiều giá trị " tự nó không phải là một phạm vi. Nó có thể chứa phạm vi, nhưng điều đó không làm cho nó một phạm vi.
Vì vậy, bây giờ bạn phải thực hiện loại "không phải là một phạm vi" rất chắc chắn này và làm cho tất cả các bộ điều hợp phạm vi của bạn hoạt động với nó. Áp dụng bộ điều hợp phạm vi phải phát hoạt động đó qua các loại, tạo ra một hoạt động nhiều-nhiều. Làm điều đó không dễ dàng.
Nhưng quan trọng hơn ... đó có lẽ không phải là điều bạn muốn . Nếu bạn fork
là một phạm vi, thì bạn gần như chắc chắn muốn thực hiện xử lý khác nhau trên các phạm vi được nhân rộng. Và điều đó hoàn toàn tắt bất kỳ cơ hội sử dụng các |
hoạt động để làm điều đó. Bạn sẽ phải xây dựng các cách để áp dụng bộ điều hợp cho các phần cụ thể của các bộ dữ liệu này. Và những cách đó đang ngày càng giống như một bộ xử lý dựa trên đẩy.
Vào cuối ngày, một hệ thống kiểu kéo chỉ có một đầu ra ở mỗi cấp. Đó chỉ là một phần của khái niệm cốt lõi của một API như vậy: mỗi bước xử lý tạo ra một phạm vi. Điều này có lợi thế của nó (lười xử lý) nhưng đại diện cho các hoạt động một-nhiều là một trong những lĩnh vực yếu của nó.
Phạm vi chắc chắn có thể có một unzip
chức năng ( fork
thực sự chỉ là sao chép phạm vi). Nhưng nó sẽ không phải là một |
bộ chuyển đổi phong cách; nó sẽ là một hàm lấy một phạm vi trên một số loại có thể phân tách và trả về một bộ phạm vi. Nếu bạn muốn xử lý nhiều hơn với chúng, thì bạn sẽ cần lưu trữ bộ dữ liệu trong một giá trị, truy cập các phần tử riêng lẻ và sử dụng chúng khi bạn thấy phù hợp.