Simplify element access in pipeline
Opened this issue · 0 comments
Description
Currently, flux::first
, flux::find_if
and some others return a cursor
. I will call these functions collectors
This makes sense with flux iteration model, but is unwieldy in practice:
// common part
struct IndexedData
{
int index;
int data; // assume this is important
};
IndexedData data[] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 5}};
auto cur = flux::find_if(data, [](auto&& d) { return d.data == 3; });
if (flux::is_last(data, cur)) {
return -1;
}
auto elem = flux::read_at(data, cur);
return process(elem);
What I would like instead is having an optional:
return flux::read_find_if(data, [](auto&& d) { return d.data == 3; })
.map(process)
.value_or(-1);
Proposed solution
I can see two ways to implement this. The tricky part is that flux::read_at
needs both the sequence and the cursor, so we cannot simply do .find_if(...).read()
. Adding a reference to the sequence in the cursor would be counter productive.
read_*
This solution is the most obvious. For each collector, we can provide a read_
version that will convert the cursor to an optional. We could also make the default collectors (find_if
, ...) return an optional, and create cursor_*
versions instead
read_self
(tap
?)
Another solution would be to provide a generic read_self
collector. It could be used like this:
return flux::read_self(data, [](auto &&seq) { return seq.find_if([](auto &&d) { return d.data == 3; }); })
.map(process)
.value_or(-1)
It would mean less implementation effort, but I'm not sure it would be really ergonomic. Also, this might have side effects I did not think about
Something else?
If there is a better way, I'd love to hear about it
Sidenote: while writing this, I've noticed find_if
doesn't seem tested?