From 86856390e184a02fbef43ccac12260608e5b8841 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 27 Nov 2017 03:22:34 +0100 Subject: [PATCH] TreeExplorer: cover expansion using a different result type here using a lambda with side-effect and returning a reference to a STL collection with the children, which is managed elsewhere. --- src/lib/iter-tree-explorer.hpp | 4 +-- tests/library/iter-tree-explorer-test.cpp | 44 ++++++++++++++++++++++- wiki/thinkPad.ichthyo.mm | 4 ++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 665b291e5..073f0a8a4 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -431,8 +431,8 @@ namespace lib { { REQUIRE (checkPoint(*this), "attempt to expand an empty explorer"); - ResIter expanded = 0 < depth()? expandChildren_(*expansions_) - : expandChildren_(*this); + ResIter expanded{ 0 < depth()? expandChildren_(*expansions_) + : expandChildren_(*this)}; iterNext (*this); // consume current head element if (not isnil(expanded)) expansions_.push (move(expanded)); diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 6a4574225..92f8900ca 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -288,7 +288,7 @@ namespace test{ - /** @test use a preconfigured "expand" functor to recurse into children + /** @test use a preconfigured "expand" functor to recurse into children. * The `expand()` builder function predefines a way how to _expand_ the current * head element of the iteration. However, expansion does not happen automatically, * rather, it needs to be invoked by the client, similar to increment of the iterator. @@ -298,6 +298,29 @@ namespace test{ * Conceptually, the evaluation _forks into the children of the expanded element_, before * continuing with the successor of the expansion point. Obviously, expansion can be applied * again on the result of the expansion, possibly leading to a tree of side evaluations. + * + * The expansion functor may be defined in various ways and will be adapted appropriately + * - it may follow the classical "monadic pattern", i.e. take individual _values_ and return + * a _"child monad"_, which is then "flat mapped" (integrated) into the resulting iteration + * - the resulting child collection may be returned as yet another iterator, which is then + * moved by the implementation into the stack of child sequences currently in evaluation + * - or alternatively the resulting child collection may be returned just as a "state core", + * which can be adapted into a _iterable state_ (see lib::IterStateWrapper). + * - or it may even return the reference to a STL collection existing elsewhere, + * which will then be iterated to yield the child elements + * - and, quite distinct to the aforementioned "monadic" usage, the expansion functor + * may alternatively be written in a way as to collaborate with the "state core" used + * when building the TreeExplorer. In this case, the functor typically takes a _reference_ + * to this underlying state core or iterator. The purpose for this definition variant is + * to allow exploring a tree-like evaluation, without the need to disclose anything about + * the backing implementation; the expansion functor just happens to know the implementation + * type of the "state core" and manipulate it through its API to create a "derived core" + * representing a _child evaluation state_. + * - and finally, there is limited support for _generic lambdas._ In this case, the implementation + * will try to instantiate the passed lambda by using the concrete source iterator type as argument. + * + * @note expansion functor may use side-effects and indeed return something entirely different + * than the original sequence, as long as it is iterable and yields compatible values. */ void verify_expandOperation() @@ -312,6 +335,25 @@ namespace test{ .expand([](uint j){ return NumberSequence{j-1}; }) ); + // lambda with side-effect and a different return type + vector> childBuffer; + auto expandIntoChildBuffer = [&](uint j) -> vector& + { + childBuffer.emplace_back(); + vector& childNumbz = childBuffer.back(); + for (size_t i=0; i - + + +