On Thu, Jan 6, 2011 at 11:57 PM, Neil Groves
Ignoring the implementation issues for a moment I would like to explain my rationale for the current syntax. I consider the range adaptors to be orthogonal to algorithms. I therefore perceive a syntactic difference between the application of algorithms and adaptors to be an advantage. With your example above I find the first version of the code more instantly understandable since the most-significant operation (copy) is at the start of the line. Therefore my personal opinion is that it is undesirable to extend the pipe syntax to the application of algorithms.
I'm not entirely convinced by the 'orthogonality' view - it is certainly one way of looking at adaptors vs algorithms, and is not without merit, but I do find the fully piped syntax a very natural expression of design intent. If the implementation difficulties were not prohibitive it is a syntax I'd like supported.
Now considering implementation details I believe there are other reasons to not extend the pipe syntax. When designing Boost.Range the extension of the central idioms to user types and algorithms has been made simple. The range adaptors are less simple to implement but are far less numerous than user supplied algorithms. The current arrangement provides an extremely low barrier for users wishing to implement range based algorithms.
It may be that this is not possible to do in a watertight way. I've looked at the current implementation, and at how the templated pipe operator is protected from consideration by ADL unless one operand is an adaptor. Using the fully piped notation the last element of the piped expression might be * an adaptor - implying a first class lazily evaluated range * a function accepting instances/references of value_type of the range * a function accepting a whole range * something else I haven't thought of each of which would require to processed quite differently by the pipe operator, so the templating would have to be quite clever. Assuming all that can be done, and I think it can, there's also the case where no adaptors are involved, eg. std::vector<int> v; void f(int); v | f; which doesn't go anywhere near the boost::range_detail namespace! I'm not sure that's fixable, unless you supply some help, eg. boost::range(v)| f; where boost::range() accesses the appropriate namespace. So, all in all maybe it's best left as is! I am very interested to hear the thoughts of yourself and the rest of the
boost community now that I have expanded upon some of the rationale. I am open to being convinced.
- Rob.