Library: RandomDraw - dynamic configuration requires partial application

Investigation in test setup reveals that the intended solution
for dynamic configuration of the RandomDraw can not possibly work.
The reason is: the processing function binds back into the object instance.
This implies that RandomDraw must be *non-copyable*.

So we have to go full circle.
We need a way to pass the current instance to the configuration function.
And the most obvious and clear way would be to pass it as function argument.
Which however requires to *partially apply* this function.

So -- again -- we have to resort to one of the functor utilities
written several years ago; and while doing so, we must modernise
these tools further, to support perfect forwarding and binding
of reference arguments.
This commit is contained in:
Fischlurch 2023-11-22 22:11:59 +01:00
parent 75cbfa8991
commit 32b740cd40
10 changed files with 683 additions and 144 deletions

View file

@ -35,7 +35,13 @@
**
** @todo the implementation is able to handle partial application with N arguments,
** but currently we need just one argument, thus only this case was wrapped
** up into a convenient functions func::applyFirst and func::applyLast
** up into a convenient functions func::applyFirst and func::applyLast
** @todo 11/23 these functor-utils were written at a time when support for handling
** generic functions in C++ was woefully inadequate; at that time, we neither
** had Lambda-support in the language, nor the ability to use variadic arguments.
** Providing a one-shot function-style interface for this kind of manipulations
** is still considered beneficial, and thus we should gradually modernise
** the tools we want to retain...
**
** @see control::CommandDef usage example
** @see function.hpp
@ -50,6 +56,7 @@
#include "lib/meta/tuple-helper.hpp"
#include <functional>
#include <utility>
#include <tuple>
@ -58,8 +65,10 @@ namespace lib {
namespace meta{
namespace func{
using std::function;
using std::tuple;
using std::function;
using std::forward;
using std::move;
@ -607,8 +616,8 @@ namespace func{
public:
typedef function<typename FunctionTypedef<Ret,ArgsL>::Sig> LeftReducedFunc;
typedef function<typename FunctionTypedef<Ret,ArgsR>::Sig> RightReducedFunc;
typedef function<typename BuildFunType<Ret,ArgsL>::Sig> LeftReducedFunc;
typedef function<typename BuildFunType<Ret,ArgsR>::Sig> RightReducedFunc;
/** do a partial function application, closing the first arguments<br/>
@ -670,7 +679,7 @@ namespace func{
using PreparedArgTypes = typename Types<PreparedArgs>::Seq;
using RemainingArgs = typename Types<ReducedArgs>::Seq;
using ReducedSig = typename FunctionTypedef<Ret,RemainingArgs>::Sig;
using ReducedSig = typename BuildFunType<Ret,RemainingArgs>::Sig;
template<class SRC, class TAR, size_t i>
using IdxSelector = typename PartiallyInitTuple<SRC, TAR, pos>::template IndexMapper<i>;
@ -694,10 +703,12 @@ namespace func{
namespace { // ...helpers for specifying types in function declarations....
using std::get;
template<typename RET, typename ARG>
struct _Sig
{
typedef typename FunctionTypedef<RET, ARG>::Sig Type;
typedef typename BuildFunType<RET, ARG>::Sig Type;
typedef TupleApplicator<Type> Applicator;
};
@ -712,32 +723,92 @@ namespace func{
template<typename FUN1, typename FUN2>
struct _Chain
{
typedef typename _Fun<FUN1>::Args Args;
typedef typename _Fun<FUN2>::Ret Ret;
typedef typename FunctionTypedef<Ret, Args>::Sig ChainedSig;
typedef function<ChainedSig> Functor;
using Ret = typename _Fun<FUN2>::Ret;
using Args = typename _Fun<FUN1>::Args;
using FunType = typename BuildFunType<Ret,Args>::Fun;
static auto adaptedFunType() { return FunType{}; }
template<typename F1, typename F2
,typename RET, typename... ARGS>
static auto
composedFunctions (F1&& f1, F2&& f2, _Fun<RET(ARGS...)>)
{
tuple<F1,F2> binding{forward<F1> (f1)
,forward<F2> (f2)
};
return [binding = move(binding)]
(ARGS ...args) mutable -> RET
{
auto& functor1 = get<0>(binding);
auto& functor2 = get<1>(binding);
//
return functor2 (functor1 (forward<ARGS> (args)...));
};
}
};
template<typename SIG>
template<typename FUN>
struct _PapS
{
typedef typename _Fun<SIG>::Ret Ret;
typedef typename _Fun<SIG>::Args Args;
typedef typename Split<Args>::Head Arg;
typedef typename Split<Args>::Tail Rest;
typedef typename _Sig<Ret,Rest>::Type Signature;
typedef function<Signature> Function;
using Ret = typename _Fun<FUN>::Ret;
using Args = typename _Fun<FUN>::Args;
using Arg = typename Split<Args>::Head;
using Rest = typename Split<Args>::Tail;
using FunType = typename BuildFunType<Ret,Rest>::Fun;
static auto adaptedFunType() { return FunType{}; }
template<typename F, typename A
,typename RET, typename... ARGS>
static auto
bindFrontArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
{
tuple<F,A> binding{forward<F> (fun)
,forward<A> (arg)
};
return [binding = move(binding)]
(ARGS ...args) mutable -> RET
{
auto& functor = get<0>(binding);
//
return functor ( forward<A> (get<1>(binding))
, forward<ARGS> (args)...);
};
}
};
template<typename SIG>
template<typename FUN>
struct _PapE
{
typedef typename _Fun<SIG>::Ret Ret;
typedef typename _Fun<SIG>::Args Args;
typedef typename Split<Args>::End Arg;
typedef typename Split<Args>::Prefix Rest;
typedef typename _Sig<Ret,Rest>::Type Signature;
typedef function<Signature> Function;
using Ret = typename _Fun<FUN>::Ret;
using Args = typename _Fun<FUN>::Args;
using Arg = typename Split<Args>::End;
using Rest = typename Split<Args>::Prefix;
using FunType = typename BuildFunType<Ret,Rest>::Fun;
static auto adaptedFunType() { return FunType{}; }
template<typename F, typename A
,typename RET, typename... ARGS>
static auto
bindBackArg (F&& fun, A&& arg, _Fun<RET(ARGS...)>)
{
tuple<F,A> binding{forward<F> (fun)
,forward<A> (arg)
};
return [binding = move(binding)]
(ARGS ...args) mutable -> RET
{
auto& functor = get<0>(binding);
//
return functor ( forward<ARGS> (args)...
, forward<A> (get<1>(binding)));
};
}
};
} // (End) argument type shortcuts
@ -761,7 +832,8 @@ namespace func{
}
/** apply the given function to the argument tuple */
/** apply the given function to the argument tuple
* @deprecated 11/23 meanwhile provided by the standard lib! */
template<typename SIG, typename...ARG>
inline
typename _Fun<SIG>::Ret
@ -774,7 +846,7 @@ namespace func{
/** close the given function over all arguments,
* using the values from the argument tuple.
* @return a closure object, which can be
* @return a closure object, which can be
* invoked later to yield the
* function result. */
template<typename SIG, typename...ARG>
@ -788,29 +860,25 @@ namespace func{
/** close the given function over the first argument */
template<typename SIG, typename ARG>
inline
typename _PapS<SIG>::Function
applyFirst (SIG& f, ARG arg)
template<typename FUN, typename ARG>
inline auto
applyFirst (FUN&& fun, ARG&& arg)
{
typedef typename _PapS<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindFront (f, val);
static_assert (_Fun<FUN>(), "expect something function-like");
return _PapS<FUN>::bindFrontArg (forward<FUN> (fun)
,forward<ARG> (arg)
,_PapS<FUN>::adaptedFunType());
}
/** close the given function over the last argument */
template<typename SIG, typename ARG>
inline
typename _PapE<SIG>::Function
applyLast (SIG& f, ARG arg)
template<typename FUN, typename ARG>
inline auto
applyLast (FUN&& fun, ARG&& arg)
{
typedef typename _PapE<SIG>::Arg ArgType;
typedef Types<ArgType> ArgTypeSeq;
typedef Tuple<ArgTypeSeq> ArgTuple;
ArgTuple val(arg);
return PApply<SIG,ArgTypeSeq>::bindBack (f, val);
static_assert (_Fun<FUN>(), "expect something function-like");
return _PapE<FUN>::bindBackArg (forward<FUN> (fun)
,forward<ARG> (arg)
,_PapE<FUN>::adaptedFunType());
}
@ -818,7 +886,7 @@ namespace func{
* which especially might be a (nested) binder... */
template<typename SIG, typename TERM>
inline
typename _PapE<SIG>::Function
typename _PapE<SIG>::FunType::Functor
bindLast (SIG& f, TERM const& arg)
{
typedef Types<TERM> ArgTypeSeq;
@ -836,14 +904,12 @@ namespace func{
inline auto
chained (FUN1&& f1, FUN2&& f2)
{
using Ret = typename _Chain<FUN1,FUN2>::Ret;
return [functor1 = std::forward<FUN1> (f1)
,functor2 = std::forward<FUN2> (f2)]
(auto&& ...args) -> Ret
{
return functor2 (functor1 (std::forward<decltype(args)> (args)...));
};
static_assert (_Fun<FUN1>(), "expect something function-like for function-1");
static_assert (_Fun<FUN2>(), "expect something function-like for function-2");
using Chain = _Chain<FUN1,FUN2>;
return Chain::composedFunctions (forward<FUN1> (f1)
,forward<FUN2> (f2)
,Chain::adaptedFunType());
}

View file

@ -185,6 +185,29 @@ namespace meta{
/** abbreviation for referring to a function's return type */
template<typename FUN>
using _FunRet = typename _Fun<FUN>::Ret;
namespace {
template<typename FUN>
struct _DetectSingleArgFunction
{
static_assert(_Fun<FUN>() , "something funktion-like required");
static_assert(_Fun<FUN>::ARITY == 1 , "function with exactly one argument required");
using Sig = typename _Fun<FUN>::Sig;
using Arg = typename _Fun<Sig>::Args::List::Head;
};
}
/** abbreviation for referring to a function's single Argument type */
template<typename FUN>
using _FunArg = typename _DetectSingleArgFunction<FUN>::Arg;
/**
* Meta-function to check that some _function like_ entity
* offers the expected signature
@ -303,24 +326,28 @@ namespace meta{
* @param ARGS a type sequence describing the arguments
*/ //////////////////////////////////////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic, then replace this by a single variadic template
template<typename RET, typename ARGS>
struct FunctionTypedef;
struct BuildFunType;
template< typename RET>
struct FunctionTypedef<RET, Types<> >
struct BuildFunType<RET, Types<> >
{
typedef function<RET(void)> Func;
typedef RET Sig();
using Sig = RET(void);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
template< typename RET
, typename A1
>
struct FunctionTypedef<RET, Types<A1>>
struct BuildFunType<RET, Types<A1>>
{
typedef function<RET(A1)> Func;
typedef RET Sig(A1);
using Sig = RET(A1);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -328,10 +355,12 @@ namespace meta{
, typename A1
, typename A2
>
struct FunctionTypedef<RET, Types<A1,A2>>
struct BuildFunType<RET, Types<A1,A2>>
{
typedef function<RET(A1,A2)> Func;
typedef RET Sig(A1,A2);
using Sig = RET(A1,A2);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -340,10 +369,12 @@ namespace meta{
, typename A2
, typename A3
>
struct FunctionTypedef<RET, Types<A1,A2,A3>>
struct BuildFunType<RET, Types<A1,A2,A3>>
{
typedef function<RET(A1,A2,A3)> Func;
typedef RET Sig(A1,A2,A3);
using Sig = RET(A1,A2,A3);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -353,10 +384,12 @@ namespace meta{
, typename A3
, typename A4
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4>>
struct BuildFunType<RET, Types<A1,A2,A3,A4>>
{
typedef function<RET(A1,A2,A3,A4)> Func;
typedef RET Sig(A1,A2,A3,A4);
using Sig = RET(A1,A2,A3,A4);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -367,10 +400,12 @@ namespace meta{
, typename A4
, typename A5
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5>>
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5>>
{
typedef function<RET(A1,A2,A3,A4,A5)> Func;
typedef RET Sig(A1,A2,A3,A4,A5);
using Sig = RET(A1,A2,A3,A4,A5);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -382,10 +417,12 @@ namespace meta{
, typename A5
, typename A6
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6>>
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6>>
{
typedef function<RET(A1,A2,A3,A4,A5,A6)> Func;
typedef RET Sig(A1,A2,A3,A4,A5,A6);
using Sig = RET(A1,A2,A3,A4,A5,A6);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -398,10 +435,12 @@ namespace meta{
, typename A6
, typename A7
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7>>
{
typedef function<RET(A1,A2,A3,A4,A5,A6,A7)> Func;
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7);
using Sig = RET(A1,A2,A3,A4,A5,A6,A7);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -415,10 +454,12 @@ namespace meta{
, typename A7
, typename A8
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8>>
{
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8)> Func;
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8);
using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};
@ -433,10 +474,12 @@ namespace meta{
, typename A8
, typename A9
>
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
struct BuildFunType<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9>>
{
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8,A9)> Func;
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8,A9);
using Sig = RET(A1,A2,A3,A4,A5,A6,A7,A8,A9);
using Fun = _Fun<Sig>;
using Func = function<Sig>;
using Functor = Func;
};

View file

@ -341,6 +341,7 @@ namespace lib {
using Res = typename lib::meta::_Fun<FUN>::Ret;
using lib::meta::func::chained;
using lib::meta::_FunRet;
if constexpr (std::is_same_v<Res, Tar>)// ◁──────────────────────────┨ function produces result directly
return std::forward<FUN>(fun);
@ -355,13 +356,13 @@ namespace lib {
,[this](double rand){ return limited(rand); }
);
else
if constexpr (std::is_same_v<Res, RandomDraw const&>)// ◁─────────────┨ function yields parametrised RandomDraw to invoke
if constexpr (std::is_same_v<Res, RandomDraw>)// ◁────────────────────┨ function yields parametrised RandomDraw to invoke
return [functor=std::forward<FUN>(fun), this]
(auto&& ...inArgs)
{ // invoke with copy
RandomDraw const& parametricDraw = functor(inArgs...);
(auto&& ...inArgs) -> _FunRet<RandomDraw>
{ // invoke with copy
RandomDraw parametricDraw = functor(inArgs...);
return parametricDraw (forward<decltype(inArgs)> (inArgs)...);
}; // forward arguments
}; // forward arguments
else
static_assert (not sizeof(Res), "unable to adapt / handle result type");
NOTREACHED("Handle based on return type");

View file

@ -506,7 +506,7 @@ namespace control {
{
using Args = typename Types<TYPES...>::Seq;
using Ret = void;
using Sig = typename FunctionTypedef<void, Args>::Sig;
using Sig = typename BuildFunType<void, Args>::Sig;
using ArgTuple = std::tuple<TYPES...>;
};

View file

@ -61,7 +61,7 @@ namespace control {
using std::function;
using lib::meta::FunctionTypedef;
using lib::meta::BuildFunType;
using lib::meta::_Fun;
using lib::meta::Types;
using lib::meta::Append;
@ -84,9 +84,9 @@ namespace control {
using ExtendedArgs = typename Types<ExtendedArglist>::Seq;
public:
using OperateSig = typename FunctionTypedef<void, Args>::Sig;
using CaptureSig = typename FunctionTypedef<MEM, Args>::Sig;
using UndoOp_Sig = typename FunctionTypedef<void, ExtendedArgs>::Sig;
using OperateSig = typename BuildFunType<void, Args>::Sig;
using CaptureSig = typename BuildFunType<MEM, Args>::Sig;
using UndoOp_Sig = typename BuildFunType<void, ExtendedArgs>::Sig;
using CmdArgs = Args;
using Memento = MEM;
};
@ -124,9 +124,9 @@ namespace control {
using ExtendedArglist = typename Append<ARG, Memento>::List;
using ExtendedArgs = typename Types<ExtendedArglist>::Seq;
using OperateSig = typename FunctionTypedef<void, ARG>::Sig;
using CaptureSig = typename FunctionTypedef<Ret,ARG>::Sig;
using UndoOp_Sig = typename FunctionTypedef<void, ExtendedArgs>::Sig;
using OperateSig = typename BuildFunType<void, ARG>::Sig;
using CaptureSig = typename BuildFunType<Ret,ARG>::Sig;
using UndoOp_Sig = typename BuildFunType<void, ExtendedArgs>::Sig;
};
/** Case2: defining the actual Undo function */
template<typename ARG>
@ -138,9 +138,9 @@ namespace control {
using OperationArglist = typename SplitLast<Args>::List;
using OperationArgs = typename Types<OperationArglist>::Seq;
using OperateSig = typename FunctionTypedef<void, OperationArgs>::Sig;
using CaptureSig = typename FunctionTypedef<Ret,OperationArgs>::Sig;
using UndoOp_Sig = typename FunctionTypedef<void, ARG>::Sig;
using OperateSig = typename BuildFunType<void, OperationArgs>::Sig;
using CaptureSig = typename BuildFunType<Ret,OperationArgs>::Sig;
using UndoOp_Sig = typename BuildFunType<void, ARG>::Sig;
};
public:

View file

@ -72,7 +72,7 @@ namespace control {
* the undo and capture function, setting up the necessary bindings and closures for
* allowing them to cooperate behind the scenes to carry out the UNDO functionality.
* On construction, the UndoMutation functor retrieves the wired up functions,
* storing them into generic containers (type erasure) for later invocation.
* storing them into generic containers (type erasure) for later invocation.
*
* More specifically, the \c captureFunction, which is expected to run immediately prior
* to the actual command operation, returns a \b memento value object (of unspecific type),
@ -143,29 +143,27 @@ namespace control {
* @note similar to #getState(), the returned functor will throw
* when the state capturing wasn't yet invoked
*/
function<SIG>
function<SIG>
tieUndoFunc()
{
using std::bind;
return bindLast( undo_ // getState() bound to last argument of undo(...)
, bind (&MementoTie::getState, this)
);
);
}
/** bind the capturing function to the internal memento store within this object.
* @return a functor, which on invocation will automatically store the return value
* of the capturing function (= the current memento value) into the field
* #memento_ within this object
* #memento_ within this object
*/
function<SIG>
tieCaptureFunc()
{
using std::placeholders::_1;
function<void(MEM)> doCaptureMemento = bind (&MementoTie::capture, this, _1 );
return chained(capture_, doCaptureMemento);
return chained(capture_
,[this](MEM const& mementoVal){ capture (mementoVal); }
);
}
@ -183,7 +181,7 @@ namespace control {
/** conversion to bool() yields true
* if all functions are usable and
* if all functions are usable and
* memento state has been captured
*/
explicit
@ -203,7 +201,7 @@ namespace control {
};
template<typename SIG, typename MEM>
MementoTie<SIG,MEM>::operator std::string() const
{

View file

@ -149,7 +149,7 @@ namespace test {
typedef Prepend<Num<1>, Args>::Seq NewArgs; // manipulate the argument type(s)
DISPLAY (NewArgs);
typedef FunctionTypedef<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
typedef BuildFunType<RetType,NewArgs>::Sig NewSig; // re-build a new function signature
NewSig& fun = getNumberz<1,5,9>; //...which is compatible to an existing real function signature!
@ -337,7 +337,7 @@ namespace test {
// finally combine all techniques....
using NumberzArg = Types<List2>::Seq;
using NumberzSig = FunctionTypedef<int,NumberzArg>::Sig;
using NumberzSig = BuildFunType<int,NumberzArg>::Sig;
Tuple<NumberzArg> numberzTup (Num<5>(22), Num<6>(33), Num<7>(44));

View file

@ -39,6 +39,8 @@ namespace meta {
namespace test {
using ::test::Test;
using lib::test::showType;
using lib::meta::_Fun;
using func::applyFirst;
using func::applyLast;
using func::bindLast;
@ -142,10 +144,12 @@ namespace test {
virtual void
run (Arg)
{
check_diagnostics ();
check_partialApplication ();
check_functionalComposition ();
check_bindToArbitraryParameter ();
check_diagnostics();
check_partialApplication();
check_functionalComposition();
check_bindToArbitraryParameter();
verify_referenceHandling();
}
@ -383,6 +387,52 @@ namespace test {
CHECK (1+2+3+4+88 == f_bound_5 (_1_,_2_,_3_,_4_ ) );
}
/** @internal static function to pass as reference for test */
static long floorIt (float it) { return long(floor (it)); }
/** @test ensure reference types and arguments are handled properly */
void
verify_referenceHandling()
{
int ii = 99;
float ff = 88;
auto fun = std::function{[](float& f, int& i, long l) -> double { return f + i + l; }};
auto& f1 = fun;
// build chained and a partially applied functors
auto chain = func::chained(f1,floorIt);
auto pappl = func::applyFirst (f1, ff);
using Sig1 = _Fun<decltype(f1)>::Sig;
using SigC = _Fun<decltype(chain)>::Sig;
using SigP = _Fun<decltype(pappl)>::Sig;
CHECK (showType<Sig1>() == "double (float&, int&, long)"_expect);
CHECK (showType<SigC>() == "long (float&, int&, long)"_expect);
CHECK (showType<SigP>() == "double (int&, long)"_expect);
CHECK (220 == f1 (ff,ii,33));
CHECK (220 == chain(ff,ii,33));
CHECK (220 == pappl( ii,33));
// change original values to prove that references were
// passed and stored properly in the adapted functors
ii = 22;
ff = 42;
CHECK ( 97 == f1 (ff,ii,33));
CHECK ( 97 == chain(ff,ii,33));
CHECK ( 97 == pappl( ii,33));
// can even exchange the actual function, since f1 was passed as reference
fun = [](float& f, int& i, size_t s) -> double { return f - i - s; };
CHECK (-13 == f1 (ff,ii,33));
CHECK (-13 == chain(ff,ii,33));
CHECK (-13 == pappl( ii,33));
}
};

View file

@ -42,6 +42,7 @@ namespace test{
using util::_Fmt;
using lib::time::FSecs;
using lib::time::TimeVar;
using lib::meta::_FunRet;
@ -78,7 +79,7 @@ namespace test{
build (FUN&& fun)
{
return [functor=std::forward<FUN>(fun)]
(size_t hash)
(size_t hash) -> _FunRet<FUN>
{
return functor(uint(hash/64), uint(hash%64));
};
@ -94,7 +95,7 @@ namespace test{
build (FUN&& fun)
{
return [functor=std::forward<FUN>(fun)]
(size_t hash)
(size_t hash) -> _FunRet<FUN>
{
return functor(hash, ctxParameter);
};
@ -693,37 +694,90 @@ namespace test{
template<typename FUN, typename ARG, typename RET, typename... ARGS>
auto
_applyFirst (FUN&& fun, ARG&& arg, _Fun<RET(ARGS...)>)
{
std::tuple<FUN,ARG> binding{std::forward<FUN> (fun)
,std::forward<ARG>(arg)
};
return [binding = std::move(binding)]
(ARGS ...args) mutable -> RET
{
auto& functor = std::get<0> (binding);
//
return functor ( std::forward<ARG> (std::get<1> (binding))
, std::forward<ARGS> (args)...);
};
}
template<typename FUN, typename ARG>
auto
applyFirst (FUN&& fun, ARG&& arg)
{
using Ret = typename lib::meta::_Fun<FUN>::Ret;
using AllArgs = typename lib::meta::_Fun<FUN>::Args;
using RestArgs = typename lib::meta::Split<AllArgs>::Tail;
using AdaptedFun = typename lib::meta::BuildFunType<Ret,RestArgs>::Fun;
return _applyFirst( std::forward<FUN> (fun)
, std::forward<ARG> (arg)
, AdaptedFun{});
}
/** @test TODO change the generation profile dynamically
* @todo WIP 11/23 🔁 define implement
*/
void
verify_dynamicChange()
{
UNIMPLEMENTED ("change the generation profile dynamically");
SHOW_EXPR(int(d2( 0)));
SHOW_EXPR(int(d2( 1)));
SHOW_EXPR(int(d2( 2)));
SHOW_EXPR(int(d2( 3)));
SHOW_EXPR(int(d2( 4)));
SHOW_EXPR(int(d2( 5)));
SHOW_EXPR(int(d2( 6)));
SHOW_EXPR(int(d2( 7)));
SHOW_EXPR(int(d2( 8)));
SHOW_EXPR(int(d2( 9)));
SHOW_EXPR(int(d2(10)));
SHOW_EXPR(int(d2(63)));
SHOW_EXPR(int(d2(64)));
SHOW_EXPR(int(d2(65)));
SHOW_EXPR(int(d2(66)));
SHOW_EXPR(int(d2(67)));
SHOW_EXPR(int(d2(68)));
SHOW_EXPR(int(d2(69)));
SHOW_EXPR(int(d2(70)));
SHOW_EXPR(int(d2(71)));
SHOW_EXPR(int(d2(72)));
SHOW_EXPR(int(d2(73)));
SHOW_EXPR(int(d2(74)));
SHOW_EXPR(int(d2(75)));
// auto d1 = Draw([](Draw& draw, uint cycle, uint){
// draw.probability(cycle*0.2);
// });
//
//SHOW_EXPR(int(d1( 0)));
//SHOW_EXPR(int(d1( 1)));
//SHOW_EXPR(int(d1( 2)));
//SHOW_EXPR(int(d1( 16)));
//SHOW_EXPR(int(d1( 32)));
//SHOW_EXPR(int(d1( 48)));
//SHOW_EXPR(int(d1( 63)));
//SHOW_EXPR(int(d1( 64)));
//SHOW_EXPR(int(d1( 64 +1)));
//SHOW_EXPR(int(d1( 64 +2)));
//SHOW_EXPR(int(d1( 64+16)));
//SHOW_EXPR(int(d1( 64+32)));
//SHOW_EXPR(int(d1( 64+48)));
//SHOW_EXPR(int(d1( 64+64)));
//SHOW_EXPR(int(d1(128 +16)));
//SHOW_EXPR(int(d1(128 +32)));
//SHOW_EXPR(int(d1(128 +48)));
//SHOW_EXPR(int(d1(128 +64)));
//SHOW_EXPR(int(d1(128+64+16)));
//SHOW_EXPR(int(d1(128+64+32)));
//SHOW_EXPR(int(d1(128+64+48)));
//SHOW_EXPR(int(d1(128+64+64)));
int yy = 99;
float ff = 88;
auto fuK = std::function{[](float& f, int& i, size_t s) -> double { return f + i + s; }};
auto& f1 = fuK;
auto f2 = lib::meta::func::applyFirst(f1, ff);
using lib::meta::_Fun;
using Sig1 = _Fun<decltype(f1)>::Sig;
using Sig2 = _Fun<decltype(f2)>::Sig;
yy = 22;
ff = 42;
SHOW_TYPE(Sig1)
SHOW_TYPE(Sig2)
SHOW_EXPR(f1 (ff,yy,33))
SHOW_EXPR(f2 ( yy,33))
SHOW_TYPE(decltype(f2 ( yy,33)))
SHOW_TYPE(decltype(f2))
fuK = [](float& f, int& i, size_t s) -> double { return f * i * s; };
SHOW_EXPR(f1 (ff,yy,33))
SHOW_EXPR(f2 ( yy,33))
}
};

View file

@ -57425,6 +57425,144 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669580665" FOLDED="true" ID="ID_1852128670" MODIFIED="1700686547102" TEXT="Funktor-Manipulationen">
<icon BUILTIN="hourglass"/>
<icon BUILTIN="pencil"/>
<node CREATED="1700669596447" ID="ID_1886923243" MODIFIED="1700669617888" TEXT="einige Werkzeuge hatte ich vor sehr langer Zeit schon gebaut....">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700669619116" ID="ID_1944223150" MODIFIED="1700669643528" TEXT="diese m&#xfc;&#xdf;ten schrittweise modernisiert werden">
<icon BUILTIN="bell"/>
</node>
<node CREATED="1700669672781" ID="ID_1958398990" MODIFIED="1700669703266" TEXT="Function-composition: lib::meta::func::chained">
<node CREATED="1700669726758" ID="ID_611933272" MODIFIED="1700669730829" TEXT="function-closure.hpp"/>
<node CREATED="1700669750587" ID="ID_1086294542" MODIFIED="1700669760357" TEXT="Type-Binding helper _Chain&lt;FUN1,FUN2&gt;"/>
<node COLOR="#338800" CREATED="1700669762041" ID="ID_1323418254" MODIFIED="1700670034955" TEXT="11/23 auf variadic-&#x3bb; umgestellt">
<linktarget COLOR="#20b763" DESTINATION="ID_1323418254" ENDARROW="Default" ENDINCLINATION="1071;87;" ID="Arrow_ID_636352614" SOURCE="ID_80963960" STARTARROW="None" STARTINCLINATION="-916;62;"/>
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700669857972" HGAP="52" ID="ID_507646276" MODIFIED="1700670005919" TEXT="Vorsicht Falle" VSHIFT="4">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
der R&#252;ckgabetyp mu&#223; explizit deklariert werden &#8212; &#228;hnlich wie decltype(auto) &#8212; denn es kann sein, da&#223; die zusammengesetzte Funktion eine Referenz liefert
</p>
</body>
</html></richcontent>
<edge COLOR="#528497"/>
<font NAME="SansSerif" SIZE="10"/>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
</node>
<node CREATED="1700670186153" ID="ID_753645097" MODIFIED="1700670190204" TEXT="partial-Application">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700670130760" ID="ID_1114511607" MODIFIED="1700686530654" TEXT="partielle Funktions-Anwendung modernisieren">
<linktarget COLOR="#994a7b" DESTINATION="ID_1114511607" ENDARROW="Default" ENDINCLINATION="1203;76;" ID="Arrow_ID_448010949" SOURCE="ID_67786691" STARTARROW="None" STARTINCLINATION="615;22;"/>
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700672135424" ID="ID_1984801808" MODIFIED="1700672141808" TEXT="was ist daran erhaltenswert?">
<icon BUILTIN="help"/>
<node CREATED="1700672144271" ID="ID_1090292620" MODIFIED="1700672187951" TEXT="das Funktions-Manipulations-API">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...also eine Funktion, der man andere Funktoren gibt, und diese baut einen manipulierten Funktor. Sowas ist <i>extrem n&#252;tzlich...</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1700672199664" ID="ID_912990030" MODIFIED="1700672350154" TEXT="das generische bindFirst/bindLast &#x2014; wenn dann aber verallgemeinert">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
also die M&#246;glichkeit, Argumente durch Funktions-artige &#187;Binder&#171; zu schlie&#223;en, die dann aber erst zum Aufruf-Zeitpunkt aktiviert werden. In verallgemeinterter Form k&#246;nnten das beliebige passende Funktoren sein, die auch weiterhin Argumente ben&#246;tigen &#8212; und es m&#252;&#223;te ein neuer Funktionstyp synthetisiert werden (klingt schlimmer als es tats&#228;chlich umzusetzen ist, da wir so viele Tuple-Manipulationsfunktionen haben)
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700672372605" ID="ID_980669454" MODIFIED="1700672383347" TEXT="was weg mu&#xdf;...">
<icon BUILTIN="yes"/>
<node CREATED="1700672384495" ID="ID_1640467092" MODIFIED="1700672393458" TEXT="die HIlfs-Konstrukte"/>
<node CREATED="1700672393926" ID="ID_1776633246" MODIFIED="1700672401537" TEXT="die Argument-Tupel, die gespeichert werden"/>
<node CREATED="1700672402029" ID="ID_566925298" MODIFIED="1700672412031" TEXT="jedwede Kopie mu&#xdf; durch perfect-Forwarding ersetzt werden"/>
<node CREATED="1700672479034" ID="ID_1530548191" MODIFIED="1700672699321" TEXT="nach M&#xf6;glichkeit nur noch Lambdas liefern (keine std::function mehr)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
warum? weil das leichtgewichtiger und inline-freundlicher ist. Ein &#955; ist ja erst mal eine anonyme Klasse mit jedweder Storage direkt inline; es l&#228;&#223;t sich per Kopie und Verschiebung handhaben. Wer damit Probleme hat, kann sich das resultierende Lambda immer in eine Funktion packen, und den daf&#252;r passenden Funktor-Typ sollten wir auch als Metafunktion anbieten. Der Nachteil (oder auch Vorteil) von std::function ist, da&#223; das ein Objekt fester (relativ begrenzter) Gr&#246;&#223;e ist, und notfalls automatisch ein Erweiterungsspeicher auf dem Heap mitgef&#252;hrt wird.
</p>
</body>
</html></richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1700672430249" HGAP="136" ID="ID_975422639" MODIFIED="1700686519692" TEXT="schrittweise vorgehen...." VSHIFT="-7">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700672449602" ID="ID_1457801203" MODIFIED="1700680981796" TEXT="erst mal applyFirst neu implementieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1700680821756" ID="ID_1820837495" MODIFIED="1700680834943" TEXT="mit einem generic &#x3bb; ist es einfach..."/>
<node CREATED="1700680835467" ID="ID_1512849078" MODIFIED="1700680849404" TEXT="aber das Resultat ist keine Funktion (sondern ein Template)"/>
<node CREATED="1700680854471" ID="ID_908786228" MODIFIED="1700680868809" TEXT="besser: die neue Argument-Liste explizit umbauen und verwenden"/>
<node CREATED="1700680871677" ID="ID_290742590" MODIFIED="1700680955304" TEXT="Prototyp lokal im Test verifiziert: geht auch mit Referenzen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
und zwar
</p>
<ul>
<li>
Referenz irgendwo in den <i>sonstigen Argumenten</i>
</li>
<li>
Referenz als das Argument, das gebunden wird (&#10230; bleibt eine Referenz)
</li>
<li>
den Funktor selber als Referenz &#252;bergeben (&#10230; bleibt eine Referenz, man kann die konkrete Funktion austauschen)
</li>
</ul>
</body>
</html>
</richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700680640125" ID="ID_1600167237" MODIFIED="1700680810430" TEXT="neuer Trick: _Fun&lt;Sig&gt; als Transporter f&#xfc;r variadische Argument-Typen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...das bekannte leidige Problem: <i>argument packs</i>&#160;sind keine Typen; man kann sie daher nicht verarbeiten und weitergeben; stattdessen m&#252;sen wir einen Typ <i>mit varidadic parameters</i>&#160;verwenden, um am Zielort in der Argumentliste dagegen zu matchen. Da lib::meta::_Fun mehr und mehr zum Analyse-Tool f&#252;r Funktions-artige Entit&#228;ten wird, bietet es sich an, diese Metafunktion selber auch als Transporter f&#252;r Funktionssignaturen zu verwenden
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1700680962986" ID="ID_417878820" MODIFIED="1700686489900" TEXT="applyFirst / applyLast gegen neue Implementierung austauschen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1700686490730" ID="ID_270581080" MODIFIED="1700686505300" TEXT="zus&#xe4;tzlicher Test: auch Referenzen werden korrekt gehandhabt">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
@ -96688,6 +96826,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
<node COLOR="#338800" CREATED="1700535940171" ID="ID_80963960" MODIFIED="1700535962800" TEXT="lib::meta::func::chained() modernisiert">
<arrowlink COLOR="#20b763" DESTINATION="ID_1323418254" ENDARROW="Default" ENDINCLINATION="1071;87;" ID="Arrow_ID_636352614" STARTARROW="None" STARTINCLINATION="-916;62;"/>
<linktarget COLOR="#1de11c" DESTINATION="ID_80963960" ENDARROW="Default" ENDINCLINATION="1061;74;" ID="Arrow_ID_868943709" SOURCE="ID_146361421" STARTARROW="None" STARTINCLINATION="-252;-591;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
@ -96960,6 +97100,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node COLOR="#338800" CREATED="1700491985219" ID="ID_460437503" MODIFIED="1700623393034" TEXT="Adaptierung restrukturieren">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700667013700" ID="ID_1737653728" MODIFIED="1700667059509" TEXT="RandomDraw &#x25c1; NonCopyable">
<linktarget COLOR="#b1054b" DESTINATION="ID_1737653728" ENDARROW="Default" ENDINCLINATION="512;-31;" ID="Arrow_ID_685625009" SOURCE="ID_1118038273" STARTARROW="None" STARTINCLINATION="-660;37;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node COLOR="#338800" CREATED="1700577811739" ID="ID_1356052727" MODIFIED="1700623391805" TEXT="Konfigurations-DSL aufbauen">
<icon BUILTIN="button_ok"/>
@ -96968,6 +97112,189 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#435e98" CREATED="1700615809354" ID="ID_664060947" MODIFIED="1700615816506" TEXT="minVal"/>
<node COLOR="#435e98" CREATED="1700615812738" ID="ID_1089110674" MODIFIED="1700623389853" TEXT="mapping"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700666517058" ID="ID_1164549835" MODIFIED="1700666527223" TEXT="dynamische Parametrisierung erm&#xf6;glichen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700666528821" ID="ID_1733767299" MODIFIED="1700666725778">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<i>das </i>ist f&#252;r den <i>aktuellen </i>Use-case unabdingbar
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...im Gegensatz zu dem ganzen weiteren Schlonz, den ich die letzten Tage eingebaut habe, &#8222;weils grad gang&#8220;; ich brauche irgende einen Mechanismus, &#252;ber den ein sp&#228;ter hinzukonfigurierter Funktor <i>in Abh&#228;ngigkeit von aktuellen Parameter-Daten</i>&#160;an der Parametrisierung des RandomDraw &quot;drehen&quot; kann...
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700666732810" ID="ID_275616933" MODIFIED="1700666762334" TEXT="Konstruktions-Problem: wie kommt der Funktor an die aktuelle Instanz?">
<icon BUILTIN="messagebox_warning"/>
<node COLOR="#5b280f" CREATED="1700666796282" ID="ID_400868539" MODIFIED="1700666899207" TEXT="L&#xf6;sung-1: gar nicht. Er baut eine neue Instanz">
<icon BUILTIN="button_cancel"/>
<node CREATED="1700666822918" ID="ID_1578832431" MODIFIED="1700666830593" TEXT="auf die L&#xf6;sung bin ich zun&#xe4;chst verfallen"/>
<node CREATED="1700666831243" ID="ID_273291815" MODIFIED="1700666840360" TEXT="sie ist zwar etwas komisch zu verdrahten"/>
<node CREATED="1700666841204" ID="ID_1310803138" MODIFIED="1700666848911" TEXT="aber geht schon mal durch den Compiler"/>
<node CREATED="1700666849995" ID="ID_252787073" MODIFIED="1700666893728">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<i><font color="#f22e6c">dangling Reference</font></i>&#160;&#10233; CRASH
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="stop-sign"/>
<node CREATED="1700666909779" ID="ID_1903074332" MODIFIED="1700666917400" TEXT="wa-rum?">
<icon BUILTIN="smily_bad"/>
</node>
<node CREATED="1700666919681" ID="ID_1841792558" MODIFIED="1700666945613" TEXT="weil die huckepack-Funktion in RandomDraw auf *this bindet">
<icon BUILTIN="clanbomber"/>
</node>
<node CREATED="1700666957387" ID="ID_1118038273" MODIFIED="1700667065677" TEXT="Konsequenz: RandomDraw mu&#xdf; NonCopyable sein">
<arrowlink COLOR="#b1054b" DESTINATION="ID_1737653728" ENDARROW="Default" ENDINCLINATION="512;-31;" ID="Arrow_ID_685625009" STARTARROW="None" STARTINCLINATION="-660;37;"/>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node CREATED="1700667123763" ID="ID_360972195" MODIFIED="1700667721958">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
L&#246;sung-2: er bindet <i>irgendwie </i>eine Referenz darauf
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="hourglass"/>
<node CREATED="1700667152325" ID="ID_291951431" MODIFIED="1700667161608" TEXT="ja ... m&#xe4;hh">
<icon BUILTIN="smiley-neutral"/>
</node>
<node CREATED="1700667168921" ID="ID_277893933" MODIFIED="1700667204912" TEXT="...also entweder der User mu&#xdf; das beim Setup machen (&#x27f9; setzt bestehende Instanz voraus)"/>
<node CREATED="1700667209643" ID="ID_497670078" MODIFIED="1700667262488" TEXT="...oder man bietet ein spezielles Builder-Setup &#x27f6; Funktor 2.Ordnung">
<node CREATED="1700667287164" ID="ID_9300229" MODIFIED="1700667301028" TEXT="w&#xe4;re durchaus machbar &#x2014; aber nicht leicht zu vestehen">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1700667564352" ID="ID_662111218" MODIFIED="1700667663542" TEXT="in drei Schritten">
<node CREATED="1700667568604" ID="ID_1050199497" MODIFIED="1700667666028" TEXT="Builder-&#x3bb; : bekommt RandomDraw&amp; &#x27fc; liefert Manipulator-&#x3bb;">
<icon BUILTIN="full-1"/>
</node>
<node CREATED="1700667618957" ID="ID_162376172" MODIFIED="1700667668131" TEXT="Manipulator-&#x3bb;: bekommt Input, manipuliert RandomDraw&amp;">
<icon BUILTIN="full-2"/>
</node>
<node CREATED="1700667642374" ID="ID_629040008" MODIFIED="1700667670894" TEXT="Invocation: RandomDraw selber auf die Argumente anwenden">
<icon BUILTIN="full-3"/>
</node>
</node>
<node CREATED="1700667685604" ID="ID_462101752" MODIFIED="1700667704470" TEXT="Muuuh!">
<icon BUILTIN="smiley-angry"/>
</node>
</node>
<node CREATED="1700667315966" ID="ID_336303173" MODIFIED="1700667341006" TEXT="&#x27f9; der letztlich operierende Funktor h&#xe4;tte Res-type void (Seiteneffekt)"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700667728894" ID="ID_1647643633" MODIFIED="1700667762597" TEXT="Plan-B">
<font BOLD="true" NAME="SansSerif" SIZE="13"/>
<icon BUILTIN="yes"/>
<icon BUILTIN="hourglass"/>
</node>
</node>
<node CREATED="1700667358039" ID="ID_1159388516" MODIFIED="1700667382024" TEXT="L&#xf6;sung:3 er nimmt diese als Ref-Argument">
<node CREATED="1700667395811" ID="ID_1168097310" MODIFIED="1700667512459">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
das w&#228;re sch&#246;n sauber &#8212; <font size="6">ABER</font>&#160;...
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="smiley-oh"/>
<node CREATED="1700667426327" ID="ID_1988791757" MODIFIED="1700667443550" TEXT="woher bekommt er dann den Input f&#xfc;r die Parametrisierung?"/>
<node CREATED="1700667444188" ID="ID_495817814" MODIFIED="1700667455851" TEXT="weitere Argumente? welche?"/>
<node CREATED="1700667456602" ID="ID_1963198981" MODIFIED="1700667463789" TEXT="und wie bindet man das??"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700667812723" ID="ID_1483170838" MODIFIED="1700667830059" TEXT="Variadic-Args + rekursiver Aufruf">
<icon BUILTIN="idea"/>
<node CREATED="1700668497744" ID="ID_1487967876" MODIFIED="1700668593578" TEXT="das mu&#xdf; der adaptIn(fun)-Schritt aufl&#xf6;sen">
<node CREATED="1700668538836" ID="ID_1747416563" MODIFIED="1700668552053" TEXT="er mu&#xdf; dazu aber irgendwie die restlichen Argumente zu Greifen bekommen"/>
<node CREATED="1700668553545" ID="ID_1272264893" MODIFIED="1700668561180" TEXT="...und diese rekursiv an sich selber &#xfc;bergeben"/>
</node>
<node CREATED="1700669255396" ID="ID_1754735258" MODIFIED="1700669300783">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
l&#228;uft auf eine <b>partielle Anwendung</b>&#160;der Funktion hinaus
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1700669349834" ID="ID_1795148710" MODIFIED="1700669452457" TEXT="auch daf&#xfc;r gabs bereits eine LIbrary-L&#xf6;sung">
<node CREATED="1700669462313" ID="ID_146361421" MODIFIED="1700669512820" TEXT="genau die Geliche, die ich vor ein paar Tagen schon modernisiert habe...">
<arrowlink COLOR="#1de11c" DESTINATION="ID_80963960" ENDARROW="Default" ENDINCLINATION="1061;74;" ID="Arrow_ID_868943709" STARTARROW="None" STARTINCLINATION="-252;-591;"/>
</node>
<node CREATED="1700670079863" ID="ID_931371524" MODIFIED="1700670102061" TEXT="im Grunde ist auch das heutzutage leicht als generisches Lambda zu schreiben"/>
<node COLOR="#435e98" CREATED="1700670049963" ID="ID_67786691" MODIFIED="1700686592758" TEXT="kann man die partielle-Anwendung auch modernisieren? (und dann verwenden)">
<arrowlink COLOR="#994a7b" DESTINATION="ID_1114511607" ENDARROW="Default" ENDINCLINATION="1203;76;" ID="Arrow_ID_448010949" STARTARROW="None" STARTINCLINATION="615;22;"/>
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700672717763" HGAP="32" ID="ID_1710135688" MODIFIED="1700672756403" TEXT="nicht ganz so einfach wie bei der Funktions-Komposition" VSHIFT="9">
<icon BUILTIN="messagebox_warning"/>
</node>
<node COLOR="#435e98" CREATED="1700672739896" HGAP="26" ID="ID_1441194651" MODIFIED="1700686571025" TEXT="ein Teilschritt w&#xe4;re denkbar" VSHIFT="1">
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1700686572329" HGAP="43" ID="ID_1067874422" MODIFIED="1700686591140" TEXT="(ges&#xe4;gt, getan)" VSHIFT="1">
<font NAME="SansSerif" SIZE="11"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686650589" ID="ID_1320986357" MODIFIED="1700686659027" TEXT="adaptIn">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686611506" ID="ID_1055056344" MODIFIED="1700686621481" TEXT="partielle Anwendung anwenden">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686662293" ID="ID_473080725" MODIFIED="1700686674078" TEXT="sich selbst damit rekursiv aufrufen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686675275" ID="ID_1836010727" MODIFIED="1700686690830" TEXT="adaptOut">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686680324" ID="ID_1784901789" MODIFIED="1700686688050" TEXT="neuer Zweig f&#xfc;r void-Funktionen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686695792" ID="ID_1003013120" MODIFIED="1700686699584" TEXT="beide integriert">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700686712454" ID="ID_194082456" MODIFIED="1700686717365" TEXT="im Test verifizieren">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491877926" ID="ID_1958310493" MODIFIED="1700502021655" TEXT="Test zur Dokumentation">
<icon BUILTIN="pencil"/>