feat(util/list): add map_filter template

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-11-21 14:47:50 -08:00
parent f6bfd11aed
commit 8515821d56
2 changed files with 44 additions and 0 deletions

View file

@ -161,6 +161,23 @@ static void tst12() {
lean_assert(sum == 30); lean_assert(sum == 30);
} }
static void tst13() {
list<int> l({1, 2, 3, 4, 5, 6, 7});
list<int> l2 = map_filter(l, [](int in, int & out) {
if (in % 2 == 0) {
out = in + 10;
return true;
} else {
return false;
}
});
std::cout << l2 << "\n";
list<int> l3({12, 14, 16});
lean_assert_eq(l2, l3);
lean_assert(empty(map_filter(l, [](int, int &) { return false; })));
lean_assert(empty(map_filter(list<int>(), [](int in, int & out) { out = in; return true; })));
}
int main() { int main() {
tst1(); tst1();
tst2(); tst2();
@ -174,5 +191,6 @@ int main() {
tst10(1000, 5); tst10(1000, 5);
tst11(1000, 5); tst11(1000, 5);
tst12(); tst12();
tst13();
return has_violations() ? 1 : 0; return has_violations() ? 1 : 0;
} }

View file

@ -156,6 +156,32 @@ list<T> map(list<T> const & l, F && f) {
} }
} }
/**
\brief Similar to \c map but \c f has signature
<tt>bool f(T const & in, T & out)</tt>
If \c out becomes part of the result iff \c f returns true.
*/
template<typename T, typename F>
list<T> map_filter(list<T> const & l, F && f) {
if (is_nil(l)) {
return l;
} else {
buffer<typename list<T>::cell*> tmp;
to_buffer(l, tmp);
unsigned i = tmp.size();
list<T> r;
while (i > 0) {
--i;
T out;
if (f(tmp[i]->head(), out))
r = cons(out, r);
}
return r;
}
}
/** /**
\brief Semantically equivalent to \c map, but it tries to reuse \brief Semantically equivalent to \c map, but it tries to reuse
list cells. The elements are compared using the predicate \c eq. list cells. The elements are compared using the predicate \c eq.