TreeExplorer: finish test coverage of expand+transform

This commit is contained in:
Fischlurch 2017-12-06 02:02:22 +01:00
parent 9e9c6c3ec6
commit 085b304a38
3 changed files with 63 additions and 30 deletions

View file

@ -22,11 +22,12 @@
/** @file iter-tree-explorer.hpp
** Building tree expanding and backtracking evaluations within hierarchical scopes.
** Based on the <b>Lumiera Forward Iterator</b> concept and using the basic IterAdaptor templates,
** these components allow to implement typical evaluation strategies, like e.g. depth-first or
** breadth-first exploration of a hierarchical structure. Since the access to this structure is
** Based on the *Lumiera Forward Iterator* concept and using the basic IterAdaptor templates,
** these components allow to implement typical evaluation strategies, like conditional expanding
** or depth-first exploration of a hierarchical structure. Since the access to this structure is
** abstracted through the underlying iterator, what we effectively get is a functional datastructure.
** The implementation is based on the IterStateWrapper, which is one of the basic helper templates
** The implementation is based on the idea of a "state core", which is wrapped right into the iterator
** itself (value semantics) -- similar to the IterStateWrapper, which is one of the basic helper templates
** provided by iter-adapter.hpp.
**
** @remark as of 2017, this template, as well as the initial IterExplorer (draft from 2012) can be
@ -38,13 +39,14 @@
** separate the _mechanics of evaluation_ from the actual logic of the target domain.
**
** # Iterators as Monad
** The fundamental idea behind the implementation technique used here is the \em Monad pattern
** known from functional programming. A Monad is a (abstract) container created by using some specific functions.
** This is an rather abstract concept with a wide variety of applications (things like IO state, parsers, combinators,
** The fundamental idea behind the implementation technique used here is the _Monad pattern_
** known from functional programming. A Monad is a container holding some arbitrarily typed base value; the monad can
** be seen as "amplifying" and enhancing the contained base value by attaching additional properties or capabilities
** This is a rather detached concept with a wide variety of applications (things like IO state, parsers, combinators,
** calculations with exception handling but also simple data structures like lists or trees). The key point with any
** monad is the ability to \em bind a function into the monad; this function will work on the \em internals of the
** monad and produce a modified new monad instance. In the simple case of a list, "binding" a function
** basically means to map the function onto the elements in the list.
** monad is the ability to _bind a function_ into the monad; this function will work on the _contained base values_
** and produce a modified new monad instance. In the simple case of a list, "binding" a function basically means
** to _map the function onto_ the elements in the list.
**
** ## Rationale
** The primary benefit of using the monad pattern is to separate the transforming operation completely from
@ -57,6 +59,22 @@
** - and this evaluation needs to be done asynchronously and in parallel (no locking, immutable data)
** - and a partial evaluation needs to be stored as continuation (not relying on the stack for partial results)
**
** # A Pipeline builder
** Based on such concepts, structures and evaluation patterns, the TreeExplorer serves the purpose to provide
** building blocks to assemble a _processing pipeline_, where processing will happen _on demand,_ while iterating.
** TreeExplorer itself is both a Lumiera Forward Iterator based on some wrapped data source, and at the same time
** it is a builder to chain up processing steps to work on the data pulled from that source. These processing steps
** are attached as _decorators_ wrapping the source, in the order the corresponding builder functions were invoked.
** - the _expand operation_ installs a function to consume one element and replace it by the sequence of elements
** (``children'') produced by that _»expansion functor«_. But this expansion does not happen automatically and
** on each element, rather it is triggered by issuing a dedicated `expandChildren()` call on the processing
** pipeline. Thus, binding the expansion functor has augmented the data source with the ability to explore
** some part in more detail _when required.
** - the _transform operation_ installs a function to be mapped onto each element retrieved from the underlying source
** - in a similar vein, the _filter operation_ binds a predicate to decide about using or discarding data
** - in concert, expand- and transform operation allow to build hierarchy evaluation algorithms without exposing
** any knowledge regarding the concrete hierarchy used and explored as data source.
**
** @todo WIP-WIP-WIP initial draft as of 11/2017
**
** @see IterTreeExplorer_test
@ -229,6 +247,8 @@ namespace lib {
}//(End) namespace iter_explorer : predefined policies and configurations
namespace { // TreeExplorer traits
using meta::enable_if;
@ -496,6 +516,8 @@ namespace lib {
iterNext(); // consume current head element
if (not isnil(expanded))
expansions_.push (move(expanded));
SRC::expandChildren();
}
/** diagnostics: current level of nested child expansion */

View file

@ -572,10 +572,14 @@ namespace test{
* in that case it might even happen that the downstream consumer does not even see the
* items resulting from child expansion, because they are evaluated and then filtered
* away by a transformer and filter placed in between.
* @note a corollary of the aforementioned is the observation that having several expand
* layers is rather not useful in practice. Due to the nested inheritance structure
* of the assembled TreeExplorer, it is the expansion layer most on top in the chain
* who will receive the `expandChildren()` call.
* @note as a consequence of the flexible automatic adapting of bound functors, it is
* possible for bound functors within different "layers" to collaborate, based on
* additional knowledge regarding the embedded data source internals. This test
* demonstrates a transform functor, which takes the _source iterator_ as argument
* and invokes `it.expandChildren()` to manipulate the underlying evaluation.
* However, since the overall evaluation is demand driven, there are inherent
* limitations to such a setup, which bends towards fragility when leaving
* the realm of pure functional evaluation.
*/
void
verify_combinedExpandTransform()
@ -590,13 +594,13 @@ namespace test{
++ii;
CHECK (8 == *ii);
ii.expandChildren();
cout << materialise(ii) <<endl;/////////////////////////////////TODO "8-4-2-6-4-2"
CHECK ("6-4-2-6-4-2" == materialise(ii) );
// the following contrived example demonstrates
// how intermediary processing steps may interact
cout << materialise (
CHECK (materialise (
treeExplore(CountDown{5})
.expand([](uint j){ return CountDown{j-1}; })
.transform([](int v){ return 2*v; })
@ -605,13 +609,14 @@ namespace test{
auto elm = *it;
if (elm == 6)
{
it.expandChildren();
elm *= 10;
it.expandChildren(); // NOTE at that point we're forced to decide if
elm = *it * 10; // we want to return the parent or the 1st child
}
return elm;
})
.transform([](float f){ return f/2; })
) <<endl;///////////////////////////////////////////TODO "5-4-30-1-2-1"
.transform([](float f){ return 0.055 + f/2; })
)
== "5.055-4.055-20.055-1.055-2.055-1.055" );
}

View file

@ -5710,7 +5710,7 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1512363286920" ID="ID_1420123769" MODIFIED="1512363305422" TEXT="Zusammenspiel">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1512363297486" ID="ID_531127457" MODIFIED="1512516890757" TEXT="re-evaluate">
<node COLOR="#338800" CREATED="1512363297486" FOLDED="true" ID="ID_531127457" MODIFIED="1512521973765" TEXT="re-evaluate">
<linktarget COLOR="#5a92a2" DESTINATION="ID_531127457" ENDARROW="Default" ENDINCLINATION="385;167;" ID="Arrow_ID_556443427" SOURCE="ID_579206895" STARTARROW="None" STARTINCLINATION="844;55;"/>
<icon BUILTIN="button_ok"/>
<icon BUILTIN="messagebox_warning"/>
@ -5719,10 +5719,11 @@
<node CREATED="1512363380411" ID="ID_1008917631" MODIFIED="1512363473668" TEXT="expandChildren &#xe4;ndert aktuellen Gehalt der Quelle">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1512363397897" ID="ID_1178182932" MODIFIED="1512363487789" TEXT="aber downstream reagiert (bisher) nur auf iterate()">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1512363397897" ID="ID_1178182932" MODIFIED="1512521936459" TEXT="aber downstream reagiert (bisher) nur auf iterate()">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1512363421797" ID="ID_1732504592" MODIFIED="1512363505534" TEXT="Folge: geCacheter Wert aus Transformer &#xfc;berdeckt">
<node CREATED="1512363421797" ID="ID_1732504592" MODIFIED="1512521966101" TEXT="Folge: geCacheter Wert aus Transformer &#xfc;berdeckt">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="broken-line"/>
</node>
</node>
@ -6247,9 +6248,10 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1510969031379" ID="ID_722056043" MODIFIED="1512358551383" TEXT="verify_combinedExpandTransform();">
<icon BUILTIN="pencil"/>
<node CREATED="1512363192308" ID="ID_1913090689" MODIFIED="1512363209302" TEXT="expand &#xfc;ber Transformer hinweg">
<node COLOR="#338800" CREATED="1510969031379" ID="ID_722056043" MODIFIED="1512521923184" TEXT="verify_combinedExpandTransform();">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1512363192308" FOLDED="true" ID="ID_1913090689" MODIFIED="1512522127007" TEXT="expand &#xfc;ber Transformer hinweg">
<icon BUILTIN="button_ok"/>
<node CREATED="1512363626338" ID="ID_1302720848" MODIFIED="1512363637547" TEXT="funktioniert out-of-the-Box">
<icon BUILTIN="ksmiletris"/>
</node>
@ -6257,12 +6259,16 @@
<icon BUILTIN="smiley-oh"/>
</node>
</node>
<node CREATED="1512363210130" ID="ID_480959271" MODIFIED="1512363224156" TEXT="expand aus manipulierendem Transformer">
<node COLOR="#338800" CREATED="1512363210130" FOLDED="true" ID="ID_480959271" MODIFIED="1512522130630" TEXT="expand aus manipulierendem Transformer">
<icon BUILTIN="button_ok"/>
<node CREATED="1512363649158" ID="ID_1152388495" MODIFIED="1512363655383" TEXT="ebenso">
<icon BUILTIN="ksmiletris"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1512363659085" ID="ID_1079241242" MODIFIED="1512363737038" TEXT="TODO output CHECK">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1512522106792" ID="ID_1499481842" MODIFIED="1512522120926" TEXT="naja fast noch fastiger">
<icon BUILTIN="smiley-neutral"/>
</node>
<node COLOR="#338800" CREATED="1512363659085" ID="ID_1079241242" MODIFIED="1512521919442" TEXT="TODO output CHECK">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1512363228751" ID="ID_579206895" MODIFIED="1512516921091" TEXT="Problem: re-evaluate nach expand">