Implement QPromise<Sequence<T>>::reduce(reducer, initialValue)

Iterates over all the promise values (i.e. `Sequence<T>`) and reduces the sequence to a single value using the given `reducer` function and an optional `initialValue`. Also provide a static helper to directly reduce values (`QtPromise::reduce(values, reducer, initialValue)`).
This commit is contained in:
Simon Brunel
2019-02-25 10:07:06 +01:00
parent cbf4cc7867
commit e3f0f054af
15 changed files with 763 additions and 6 deletions

View File

@ -33,6 +33,7 @@ module.exports = {
'qtpromise/qpromise/ispending',
'qtpromise/qpromise/isrejected',
'qtpromise/qpromise/map',
'qtpromise/qpromise/reduce',
'qtpromise/qpromise/tap',
'qtpromise/qpromise/tapfail',
'qtpromise/qpromise/then',
@ -51,6 +52,7 @@ module.exports = {
'qtpromise/helpers/each',
'qtpromise/helpers/filter',
'qtpromise/helpers/map',
'qtpromise/helpers/reduce',
'qtpromise/helpers/resolve'
]
},

View File

@ -12,6 +12,7 @@
* [`QPromise<T>::isPending`](qpromise/ispending.md)
* [`QPromise<T>::isRejected`](qpromise/isrejected.md)
* [`QPromise<T>::map`](qpromise/map.md)
* [`QPromise<T>::reduce`](qpromise/reduce.md)
* [`QPromise<T>::tap`](qpromise/tap.md)
* [`QPromise<T>::tapFail`](qpromise/tapfail.md)
* [`QPromise<T>::then`](qpromise/then.md)
@ -31,6 +32,7 @@
* [`QtPromise::each`](helpers/each.md)
* [`QtPromise::filter`](helpers/filter.md)
* [`QtPromise::map`](helpers/map.md)
* [`QtPromise::reduce`](helpers/reduce.md)
* [`QtPromise::resolve`](helpers/resolve.md)
## Exceptions

View File

@ -0,0 +1,48 @@
---
title: reduce
---
# QtPromise::reduce
*Since: 0.5.0*
```cpp
QPromise::reduce(Sequence<T|QPromise<T>> values, Reducer reducer) -> QPromise<T>
QPromise::reduce(Sequence<T|QPromise<T>> values, Reducer reducer, R|QPromise<R> initialValue) -> QPromise<R>
// With:
// - Sequence: STL compatible container (e.g. QVector, etc.)
// - Reducer: Function(T|R accumulator, T item, int index) -> R|QPromise<R>
```
Iterates over `values` and [reduces the sequence to a single value](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29) using the given `reducer` function and an optional `initialValue`. The type returned by `reducer` determines the type of the `output` promise. If `reducer` throws, `output` is rejected with the new exception.
If `reducer` returns a promise (or `QFuture`), then the result of the promise is awaited, before continuing with next iteration. If any promise in the `values` sequence is rejected or a promise returned by the `reducer` function is rejected, `output` immediately rejects with the error of the promise that rejected.
```cpp
// Concatenate the content of the given files, read asynchronously
auto output = QtPromise::reduce(QList<QUrl>{
"file:f0.txt", // contains "foo"
"file:f1.txt", // contains "bar"
"file:f2.txt" // contains "42"
}, [](const QString& acc, const QString& cur, int idx) {
return readAsync(cur).then([=](const QString& res) {
return QString("%1;%2:%3").arg(acc).arg(idx).arg(res);
});
}, QString("index:text"));
// 'output' resolves as soon as all promises returned by
// 'reducer' are fulfilled or at least one is rejected.
// 'output' type: QPromise<QString>
output.then([](const QString& res) {
// res == "index:text;0:foo;1:bar;2:42"
// {...}
});
```
::: warning IMPORTANT
The first time `reducer` is called, if no `initialValue` is provided, `accumulator` will be equal to the first value in the sequence, and `currentValue` to the second one (thus index will be `1`).
:::
See also: [`QPromise<T>::reduce`](../qpromise/reduce.md)

View File

@ -0,0 +1,58 @@
---
title: .reduce
---
# QPromise::reduce
*Since: 0.5.0*
```cpp
QPromise<Sequence<T>>::reduce(Reducer reducer) -> QPromise<T>
QPromise<Sequence<T>>::reduce(Reducer reducer, R|QPromise<R> initialValue) -> QPromise<R>
// With:
// - Sequence: STL compatible container (e.g. QVector, etc.)
// - Reducer: Function(T|R accumulator, T item, int index) -> R|QPromise<R>
```
::: warning IMPORTANT
This method only applies to promise with sequence value.
:::
Iterates over all the promise values (i.e. `Sequence<T>`) and [reduces the sequence to a single value](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29) using the given `reducer` function and an optional `initialValue`. The type returned by `reducer` determines the type of the `output` promise.
See [`QtPromise::reduce`](../helpers/reduce.md) for details, this method is provided for convenience and is similar to:
```cpp
promise.then([](const T& values) {
return QtPromise::reduce(values, reducer, initialValue);
})
```
For example:
```cpp
auto input = QtPromise::resolve(QList<QUrl>{
"file:f0.txt", // contains "foo"
"file:f1.txt", // contains "bar"
"file:f2.txt" // contains "42"
});
// Concatenate the content of the given files, read asynchronously
auto output = input.reduce([](const QString& acc, const QString& cur, int idx) {
return readAsync(cur).then([=](const QString& res) {
return QString("%1;%2:%3").arg(acc).arg(idx).arg(res);
});
}, QString("index:text"));
// 'output' resolves as soon as all promises returned by
// 'reducer' are fulfilled or at least one is rejected.
// 'output' type: QPromise<QString>
output.then([](const QString& res) {
// res == "index:text;0:foo;1:bar;2:42"
// {...}
});
```
See also: [`QtPromise::reduce`](../helpers/reduce.md)

View File

@ -46,7 +46,7 @@ The `output` promise is resolved when the `QFuture` is [finished](https://doc.qt
## Error
Exceptions thrown from a QtConcurrent thread reject the associated promise with the exception as the reason. Note that if you throw an exception that is not a subclass of `QException`, the promise with be rejected with [`QUnhandledException`](https://doc.qt.io/qt-5/qunhandledexception.html#details) (this restriction only applies to exceptions thrown from a QtConcurrent thread, [read more](https://doc.qt.io/qt-5/qexception.html#details)).
Exceptions thrown from a QtConcurrent thread reject the associated promise with the exception as the reason. Note that if you throw an exception that is not a subclass of `QException`, the promise will be rejected with [`QUnhandledException`](https://doc.qt.io/qt-5/qunhandledexception.html#details) (this restriction only applies to exceptions thrown from a QtConcurrent thread, [read more](https://doc.qt.io/qt-5/qexception.html#details)).
```cpp
QPromise<int> promise = ...