diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 6aa6ea8a4..870747646 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -574,7 +574,7 @@ namespace lib { * yielding a compatible value type). Now, this _sequence of children_ effectively * replaces the expanded source element in the overall resulting sequence; which * means, the nested sequence was _flattened_ into the results. Since this expand() - * operation can again invoked on the results, the implementation of such an evaluation + * operation can again be invoked on the results, the implementation of such an evaluation * requires a stack datastructure, so the nested iterator from each expand() invocation * can be pushed to become the new active source for iteration. Thus the primary purpose * of this Expander (decorator) is to integrate those "nested child iterators" seamlessly @@ -583,7 +583,7 @@ namespace lib { * the source iterator wrapped by this decorator. * @remark since we allow a lot of leeway regarding the actual form and definition of the * _expansion functor_, there is a lot of minute technical details, mostly confined - * within the _BoundFunctorTraits. + * within the _BoundFunctor traits. * @tparam SRC the wrapped source iterator, typically a TreeExplorer or nested decorator. * @tparam FUN the concrete type of the functor passed. Will be dissected to find the signature */ @@ -1108,7 +1108,7 @@ namespace lib { /* ==== Builder functions ==== */ /** preconfigure this TreeExplorer to allow for _"expansion of children"_. - * The resulting iterator exposes an `expand()` function, which consumes + * The resulting iterator exposes an `expandChildren()` function, which consumes * the current head element of this iterator and feeds it through the * _expansion functor_, which was provided to this builder function here. * The _expansion functor_ is expected to yield a sequence of "child" elements, diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 3425789c6..02c5d4021 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -218,42 +218,46 @@ namespace test{ /*******************************************************************//** * @test use a simple source iterator yielding numbers - * to build various functional evaluation structures, - * based on the \ref IterExplorer template. - * - the [state adapter](\ref verifyStateAdapter() ) - * iterator construction pattern - * - helper to [chain iterators](\ref verifyChainedIterators() ) - * - building [tree exploring structures](\ref verifyDepthFirstExploration()) - * - the [monadic nature](\ref verifyMonadOperator()) of IterExplorer - * - a [recursively self-integrating](\ref verifyRecrusiveSelfIntegration()) - * evaluation pattern + * to build various functional evaluation pipelines, + * based on the \ref TreeExplorer template. + * - the adapter to wrap the source, which can either + * [be a "state core"](\ref verify_wrappedState() ), or can + * [be a "Lumiera Forward Iterator"](\ref verify_wrappedIterator() ) + * - the defining use case for TreeExplorer is to build a + * [pipeline for depth-first exploration](\ref verify_expandOperation() ) + * of a (functional) tree structure. This "tree" is created by invoking + * a "expand functor", which can be defined in various ways. + * - the usual building blocks for functional evaluation pipelines, that is + * [filtering](\ref verify_FilterIterator() ) and + * [transforming](\ref verify_transformOperation() ) of + * the elements yielded by the wrapped source iterator. + * - building complex pipelines by combining the aforementioned building blocks + * - using an opaque source, hidden behind the IterSource interface, and + * an extension (sub interface) to allow for "tree exploration" without + * any knowledge regarding the concrete implementation of the data source. * * ## Explanation * - * Both this test and the IterExplorer template might be bewildering - * and cryptic, unless you know the *Monad design pattern*. »Monads« - * are heavily used in functional programming, actually they originate - * from Category Theory. Basically, Monad is a pattern where we combine - * several computation steps in a specific way; but instead of intermingling - * the individual computation steps and their combination, the goal is to - * isolate and separate the _mechanics of combination_, so we can focus on - * the actual _computation steps:_ The mechanics of combination are embedded - * into the Monad type, which acts as a kind of container, holding some entities - * to be processed. The actual processing steps are then attached to the monad as - * "function object" parameters. It is up to the monad to decide if, and when - * those processing steps are applied to the embedded values and how to combine - * the results into a new monad. + * These tests build a evaluation pipeline by _wrapping_ some kind of data source + * and then layering some evaluation stages on top. There are two motivations why + * one might want to build such a _filter pipeline:_ + * - on demand processing ("pull principle") + * - separation of source computation and "evaluation mechanics" + * when building complex search and backtracking algorithms. * - * Using the monad pattern is well suited when both the mechanics of - * combination and the individual computation steps tend to be complex. - * In such a situation, it is beneficial to develop and test both - * in isolation. The IterExplorer template applies this pattern - * to the task of processing a source sequence. Typically we use - * this in situations where we can't afford building elaborate - * data structures in (global) memory, but rather strive at - * doing everything on-the-fly. A typical example is the - * processing of a variably sized data set without - * using heap memory for intermediary results. + * This usage style is inspired from the *Monad design pattern*. In our case here, + * the Iterator pipeline would be the monad, and can be augmented and reshaped by + * attaching further processing steps. How those processing steps are to be applied + * remains an internal detail, defined by the processing pipeline. »Monads« are heavily + * used in functional programming, actually they originate from Category Theory. Basically, + * Monad is a pattern where we combine several computation steps in a specific way; but + * instead of intermingling the individual computation steps and their combination, + * the goal is to isolate and separate the _mechanics of combination_, so we can focus + * on the actual _computation steps:_ The mechanics of combination are embedded into the + * Monad type, which acts as a kind of container, holding some entities to be processed. + * The actual processing steps are then attached to the monad as "function object" parameters. + * It is up to the monad to decide if, and when those processing steps are applied to the + * embedded values and how to combine the results into a new monad. * * @see TreeExplorer * @see IterAdapter @@ -440,7 +444,7 @@ namespace test{ template void - verify_treeExpandingIterator(EXP ii) + verify_treeExpandingIterator (EXP ii) { CHECK (!isnil (ii)); CHECK (5 == *ii); @@ -620,7 +624,7 @@ namespace test{ * matching algorithms. Even more so, when other operations like filtering are intermingled; * 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. + * away by transformers and filters placed in between. * @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 @@ -779,6 +783,16 @@ namespace test{ + // contrived example to verify interplay of filtering and child expansion; + // especially note that the filter is re-evaluated after expansion happened. + cout << "VERIFY->" + < - + @@ -5509,7 +5509,7 @@ - + @@ -5921,7 +5921,7 @@ - + @@ -5943,7 +5943,7 @@ - + @@ -5979,15 +5979,12 @@ - - + + - - - - + @@ -6110,7 +6107,7 @@ - + @@ -6139,7 +6136,7 @@ - + @@ -6171,7 +6168,7 @@ - + @@ -6337,7 +6334,7 @@ - + @@ -6351,16 +6348,8 @@

+ - - - - - - - - - @@ -6582,10 +6571,10 @@ - + @@ -9056,9 +9045,10 @@ - + + @@ -9067,7 +9057,7 @@ - + @@ -9076,7 +9066,7 @@ - + @@ -9092,7 +9082,7 @@ - + @@ -9111,8 +9101,8 @@ - - + + @@ -9219,7 +9209,7 @@ - + @@ -9331,7 +9321,7 @@ - + @@ -9373,7 +9363,7 @@ - + @@ -9472,7 +9462,7 @@ - + @@ -9681,7 +9671,7 @@ - + @@ -10109,7 +10099,7 @@ - + @@ -15311,7 +15301,7 @@ - + @@ -17293,7 +17283,7 @@ - + @@ -25101,6 +25091,45 @@ + + + + + + +

+ Beispiel: +

+

+ a-b-c-a +

+

+ match("a").after("b") scheitert, weil sich die Suche am ersten "a" festbeißt. +

+ + +
+ +
+ + + + + + + + + + + + + + + + + + + @@ -30432,6 +30461,436 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Thema: Monaden +

+ +
+ + + + + + + + + +

+ sind Monaden +

+

+ wirklich hilfreich? +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...bindet die Betrachtung auf einen technischen Level, +

+

+ und führt dazu, daß die Abstraktion undicht wird +

+ +
+
+ + + + + + + + + + + + +

+ genau der Umstand, +

+

+ daß funktionale Sprachen von einer Zustands-Phobie getrieben sind, +

+

+ macht Monaden nützlich, um inhärenten Zustand wegzuabstrahieren. +

+

+ Das kann genutzt werden, um den Zustand einer Wechselwirkung +

+

+ nach einer Seite der Glieder auszukoppeln. +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ gehört zu dem Themenkomplex "itertools" +

+

+ Python hat das auch, Java neuerdings auch +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...will sagen, es ist klar, wie man sowas machen kann. +

+

+ Seinerzeit war mir das auch klar, aber ich wollte es nicht gleich ausprogrammieren. +

+

+ Inzwischen kam dann das Thema UI-Coordinaten, und dort habe ich es ausprogrammiert, +

+

+ und zwar direkt in die Low-Level-Schicht integriert, was nicht schlecht ist, +

+

+ da eine Abstraktion hier sehr technisch werden würde +

+ +
+
+
+
+ + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...von der entsprechenden Methode im Transformer +

+ + +
+ +
+ + + + + + +

+ ...hatte die Notwendigkeit hierfür seinerzeit während der Tests entdeckt, +

+

+ und im Unit-Test nur für die Kombination Transformer + Explorer abgedeckt.... +

+ + +
+ +
+ + + +
+
+ + + + + + + + +
    +
  • + Suche wird geleitet durch die ViewSpecDSL +
  • +
  • + hinter dem (opaquen) TreeExplorer steckt die konkrete UI-Topologie +
  • +
+ + +
+
+ + + + + + +

+ EventLog ist ein Test-Hilfsmittel, +

+

+ um Unit-Tests über UI-Bus-Interaktionen schreiben zu können. +

+

+ Es gibt hierzu Test-Varianten, die jeden Aufruf in ein internes Log notieren. +

+

+ Im Test verwendet man dann eine Pattern-Such-DSL, +

+

+ hinter der sich eine verkettete Suche mit Backtracking verbirgt +

+ + +
+ + + + + + + + + + + + + + + + + + + +

+ sofern längerfristig Itertools durch TreeExplorer abgelöst werden könnte +

+ + +
+
+
+
+ + + + + + + + + + + +

+ Invariante: pullMatch() +

+ + +
+ + + +
+ + + + + + + + + +
+
+
+
@@ -33154,7 +33613,7 @@
- + @@ -33529,7 +33988,7 @@ - + @@ -34090,166 +34549,14 @@ - - - - - - - - -

- Thema: Monaden -

- -
- - - - - - - - - - - - - - - - -

- gehört zu dem Themenkomplex "itertools" -

-

- Python hat das auch, Java neuerdings auch -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- ...will sagen, es ist klar, wie man sowas machen kann. -

-

- Seinerzeit war mir das auch klar, aber ich wollte es nicht gleich ausprogrammieren. -

-

- Inzwischen kam dann das Thema UI-Coordinaten, und dort habe ich es ausprogrammiert, -

-

- und zwar direkt in die Low-Level-Schicht integriert, was nicht schlecht ist, -

-

- da eine Abstraktion hier sehr technisch werden würde -

- -
-
-
-
- - - - - - - -
-
- - - - - - - - - - - - - - -

- ...bindet die Betrachtung auf einen technischen Level, -

-

- und führt dazu, daß die Abstraktion undicht wird -

- -
-
- - - - - - - - - - - - -

- genau der Umstand, -

-

- daß funktionale Sprachen von einer Zustands-Phobie getrieben sind, -

-

- macht Monaden nützlich, um inhärenten Zustand wegzuabstrahieren. -

-

- Das kann genutzt werden, um den Zustand einer Wechselwirkung -

-

- nach einer Seite der Glieder auszukoppeln. -

- -
-
- - - - - - - - - - - + + + + + + +