Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do C++20 ranges not provide only pipe syntax?

I understand that question sounds weird, so here is a bit of context.

Recently I was disappointed to learn that map reduce in C++20 ranges does not work as one would expect i.e.

const double val = data | transform(...) | accumulate (...);

does not work, you must write it this unnatural way:

const double val = accumulate(data | transform(...));

Details can be found here and here, but it boils down to the fact that accumulate can not disambiguate between 2 different usecases.

So this got me thinking:

If C++20 required that you must use pipe for using ranges, aka you can not write

vector<int> v;
sort(v);

but you must write

vector<int> v
v|sort();

would that would solve problem of ambiguity?

And if so although unnatural to people using std::sort and other STL algorithms I wonder if in the long run that would be a better design choice.

Note: If this question is too vague feel free to vote to close, but I feel that this is a legitimate design question that can be answered in relatively unbiased way, especially if my understanding of the problem is wrong.

like image 534
NoSenseEtAl Avatar asked Dec 08 '19 22:12

NoSenseEtAl


People also ask

What are C ++ 20 ranges?

ranges::range. (C++20) specifies that a type is a range, that is, it provides a begin iterator and an end sentinel. (concept)

What is a view in C++?

The C/C++ views are panels that help you perform the tasks involved in creating C/C++ programs. The C/C++ perspective displays these panels in a single Eclipse window. Changing Views: You can add views to a perspective.

Is range v3 header only?

Disclaimers. The library used in the code examples is not really the C++20 ranges, it's the ranges-v3 open-source library from Eric Niebler, which is the basis of the proposal to add ranges to the C++. It's a header-only library compatible with C++11/14/17.


2 Answers

You need to differentiate between range algorithms and range adaptors. Algorithms are functions that perform a generic operation on a range of values. Adaptors are functions which create range views that modify the presentation of a range. Adaptors are chained by the | operator; algorithms are just regular functions.

Sometimes, the same conceptual thing can have an algorithm and adapter form. transform exists as both an algorithm and an adapter. The former stores the transformation into an output range; the latter creates a view range of the input that lazily computes the transformation as requested.

These are different tasks for different needs and uses.

Also, note that there is no sort adapter in C++20. A sort adapter would have to create a view range that somehow mixed around the elements in the source range. It would have to allocate storage for the new sequence of values (even if it's just sorting iterators/pointers/indices to the values). And the sorting would have to be done at construction time, so there would be no lazy operation taking place.

This is also why accumulate doesn't work that way. It's not a matter of "ambiguity"; it's a matter of the fundamental nature of the operation. Accumulation computes a value from a range; it does not compute a new range from an existing one. That's the work of an algorithm, not an adapter.

Some tasks are useful in algorithm form. Some tasks are useful in adapter form (you find very few zip-like algorithms). Some tasks are useful in both. But because these are two separate concepts for different purposes, they have different ways of invoking them.

like image 131
Nicol Bolas Avatar answered Sep 20 '22 16:09

Nicol Bolas


would that would solve problem of ambiguity?

Yes.

If there's only one way to write something, that one way must be the only possible interpretation. If an algorithm "call" can only ever be a partial call to the algorithm that must be completed with a | operation with a range on the left hand side, then you'd never even have the question of if the algorithm call is partial or total. It's just always partial.

No ambiguity in that sense.

But if you went that route though, you end up with things like:

auto sum = accumulate("hello"s);

Which doesn't actually sum the chars in that string and actually is placeholder that is waiting on a range to accumulate over with the initial value "hello"s.

like image 32
Barry Avatar answered Sep 19 '22 16:09

Barry