You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -135,6 +165,93 @@ const auto total_age = employees_below_40.reduce(0, [](const int& partial_sum, c
135
165
return partial_sum + p.age;
136
166
});
137
167
```
168
+
169
+
### lazy operations
170
+
Lazy vectors are useful when chaining multiple operations over a large vector. A regular `map().filter().reduce()` style chain creates intermediate vectors and iterates once per algorithm. Calling `.lazy()` stores the following operations and executes them only when a terminal operation is called, such as `get()` or `reduce()`. This can avoid unnecessary intermediate allocations and lets map/filter/reduce-style pipelines process elements in one pass. Sorting is an important exception: it cannot be streamed element by element, so lazy `sort`, `sort_ascending`, and `sort_descending` first collect the current lazy pipeline's values, sort that collected vector, and then continue feeding the rest of the lazy chain.
171
+
172
+
```c++
173
+
#include"vector.h"// instead of <vector>
174
+
175
+
const fcpp::vector<int> numbers({5, 1, 4, 2, 3});
176
+
177
+
const auto processed_numbers = numbers
178
+
// start a lazy pipeline from this point on
179
+
.lazy()
180
+
181
+
// this predicate is not evaluated yet
182
+
.filter([](const int& number) {
183
+
return number > 2;
184
+
})
185
+
186
+
// sorting is also deferred, but it needs to materialize the filtered
187
+
// values internally when the terminal operation is called
188
+
.sort_ascending()
189
+
190
+
// this transform is not evaluated yet
191
+
.map<std::string>([](const int& number) {
192
+
return std::to_string(number);
193
+
})
194
+
195
+
// terminal operation: all stored operations are executed here
Lazy zip can combine a lazy vector with an `fcpp::vector`, a `std::vector`, or another `fcpp::lazy_vector` and also waits until a terminal operation is called, and only then checks that both sides have equal sizes. When zipping with another lazy vector, the right-hand lazy vector is materialized internally at that point, so its values can be paired by index.
// terminal operation: zip size validation and all stored operations run here
246
+
.get();
247
+
248
+
// employees -> fcpp::vector<person>({
249
+
// person(32, "Jake"),
250
+
// person(45, "Anna"),
251
+
// person(37, "Kate"),
252
+
// })
253
+
```
254
+
138
255
### index search
139
256
```c++
140
257
#include "vector.h" // instead of <vector>
@@ -367,6 +484,93 @@ const auto total_age = employees_below_40.reduce(0, [](const int& partial_sum, c
367
484
});
368
485
```
369
486
487
+
### lazy operations
488
+
Lazy sets are useful when chaining operations over a large set and only needing the final materialized set or a reduced value. A regular `map().filter().reduce()` chain creates intermediate sets and iterates once per algorithm. Calling `.lazy()` stores the following operations and executes them only when a terminal operation is called, such as `get()` or `reduce()`. This can avoid unnecessary intermediate allocations and lets map/filter/reduce-style pipelines process keys in one pass. Unlike vectors, sets are already ordered by their comparator, so lazy sets focus on the operations that make sense for set data: `map`, `filter`, `difference_with`, `union_with`, `intersect_with`, `zip`, and `reduce`.
489
+
490
+
```c++
491
+
#include"set.h"// instead of <set>
492
+
493
+
const fcpp::set<int> numbers({1, 2, 3, 4, 5});
494
+
495
+
const auto total = numbers
496
+
// start a lazy pipeline from this point on
497
+
.lazy()
498
+
499
+
// this transform is not evaluated yet
500
+
.map<int>([](const int& number) {
501
+
return number * 3;
502
+
})
503
+
504
+
// this predicate is not evaluated yet
505
+
.filter([](const int& number) {
506
+
return number > 5;
507
+
})
508
+
509
+
// terminal operation: all stored operations are executed here
Lazy set algebra can combine a lazy set with an `fcpp::set`, a `std::set`, or another `fcpp::lazy_set`. The operation is still deferred, but set algebra needs set membership and sorted set semantics, so the current lazy pipeline is materialized internally when the terminal operation is called. When the right-hand side is also lazy, it is materialized internally at the same point.
// terminal operation: the lazy filter and set algebra run here
540
+
.get();
541
+
542
+
// guests -> fcpp::set<int>({18, 25, 51, 81})
543
+
```
544
+
545
+
Lazy set zip can combine a lazy set with an `fcpp::set`, a `std::set`, an `fcpp::vector`, a `std::vector`, an `fcpp::lazy_vector`, or another `fcpp::lazy_set`. Size validation is deferred until a terminal operation is called. When zipping with a vector, duplicate vector values are removed before zipping, just like the eager set zip operation. When zipping with a lazy vector, the right-hand lazy vector is materialized internally at that point and then deduplicated. When zipping with another lazy set, the right-hand lazy set is materialized internally at that point, so its keys can be paired in set order.
Lazy maps are useful when chaining `map_to`, `filter`, and `reduce` over a large map. A regular `filtered().map_to().reduce()` style chain creates intermediate maps and iterates once per algorithm. Calling `.lazy()` stores the following operations and executes them only when a terminal operation is called, such as `get()` or `reduce()`. This can avoid unnecessary intermediate allocations and lets map_to/filter/reduce-style pipelines process key/value pairs in one pass. When a lazy `map_to` creates equivalent output keys, the first key/value pair encountered in sorted map order is kept, following `std::map::insert` semantics.
0 commit comments