Marjoram  0.01
Library for Functional Programming in C++
Lazy

Lazy Monad, supporting constants and functions. More...

Classes

class  ma::LazyIterator< A >
 Iterator over Lazy. More...
 
class  ma::Lazy< A >
 Lazy A; Either contains an A or a function that yields an A. More...
 

Functions

template<typename A >
Lazy< A > ma::Flatten (const Lazy< Lazy< A >> &LLa)
 Flattens a nested Lazy. More...
 
template<typename A >
Lazy< A > ma::Flatten (Lazy< Lazy< A >> &&LLa)
 Flattens a nested Lazy. More...
 

Detailed Description

Lazy Monad, supporting constants and functions.

Represents a lazy A that will be obtained via a delayed computation. The result will be stored for later re-use.

Allows const access to the stored value, even if not yet computed (through mutable internal storage).

Example

Suppose we would like to simplify the following class:

class Example {
public:
void examplify() const {
if (calcResult == -1) {
calcResult = expensiveCalculation();
}
// use calcResult somehow
}
void examplify2() const {
if (calcResult == -1) {
calcResult = expensiveCalculation();
}
// use calcResult in some other way
}
private:
double calcResult = -1; // -1 indicates not computed yet
double expensiveCalculation();
};

We can do so using a Lazy<Double> as follows:

class Example {
public:
Example() : calcResult([this](){ return expensiveCalculation(); }) {}
void examplify() const {
// use calcResult somehow with calcResult.get() -> double
}
void examplify2() const {
// use calcResult in some other way with calcResult.get() -> double
}
private:
Lazy<double> calcResult;
double expensiveCalculation();
};

Class Documentation

◆ ma::LazyIterator

class ma::LazyIterator

template<typename A>
class ma::LazyIterator< A >

Iterator over Lazy.

Allows mutable access to value contained. If the Lazy instance from which the iterator was created has not yet been evaluated, it is evaluated once the iterator is dereferenced.

Example:

Lazy<A> La;
[...]
for (const A& a: La) {
// use `a`
}

Public Types

using iterator_category = std::input_iterator_tag
 
using difference_type = size_t
 
using value_type = const A
 
using reference = const A &
 
using pointer = const A *
 

Public Member Functions

 LazyIterator (const Lazy< A > &La, bool start)
 
bool operator!= (const LazyIterator< A > &other)
 
reference operator* ()
 
pointer operator-> ()
 
LazyIteratoroperator++ ()
 
LazyIteratoroperator++ (int)
 

◆ ma::Lazy

class ma::Lazy

template<typename A>
class ma::Lazy< A >

Lazy A; Either contains an A or a function that yields an A.

Public Types

using value_type = A
 

Public Member Functions

 Lazy (std::function< A()> f)
 
 Lazy (const A &a)
 
 Lazy (const Lazy &)=default
 
Lazyoperator= (const Lazy &)=default
 
Lazyoperator= (const A &a)
 
Lazyoperator= (A &&a)
 
bool isEvaluated () const
 
A & get ()
 
const A & get () const
 
template<typename G >
auto map (G g) const -> Lazy< std::result_of_t< G(A)>>
 Composes self with g, that is, creates a new lazy value that yields the result of composing g with f, essentially Lazy<T>(g(f())). More...
 
template<typename G >
auto map (G g) -> Lazy< std::result_of_t< G(A)>>
 Composes self with g, that is, creates a new lazy value that yields the result of composing g with f, essentially Lazy<T>(g(f())). More...
 
template<typename G >
auto flatMap (G g) const -> std::result_of_t< G(A)>
 Composes self with g, that is, creates a new lazy value that yields the result of composing g with f and flattening, essentially Lazy<T>(g(f())). More...
 
template<typename G >
auto flatMap (G g) -> std::result_of_t< G(A)>
 Composes self with g, that is, creates a new lazy value that yields the result of composing g with f and flattening, essentially Lazy<T>(g(f())). More...
 
LazyIterator< A > begin () const
 
LazyIterator< A > end () const
 

Constructor & Destructor Documentation

◆ Lazy()

template<typename A>
ma::Lazy< A >::Lazy ( std::function< A()>  f)
inlineexplicit
Parameters
fFunction that will be called exactly once when get is called the first time.

Member Function Documentation

◆ flatMap() [1/2]

template<typename A>
template<typename G >
auto ma::Lazy< A >::flatMap ( g) const -> std::result_of_t<G(A)>
inline

Composes self with g, that is, creates a new lazy value that yields the result of composing g with f and flattening, essentially Lazy<T>(g(f())).

Parameters
gFunction object.

Type requirement:

  • G::operator() when called with argument of type A&& has return type Lazy<T> for some type T.

    Returns
    Lazy composition.
    Note
    The g object is captured inside the returned lazy object by reference and must persist until the first evaluation of the return value.

◆ flatMap() [2/2]

template<typename A>
template<typename G >
auto ma::Lazy< A >::flatMap ( g) -> std::result_of_t<G(A)>
inline

Composes self with g, that is, creates a new lazy value that yields the result of composing g with f and flattening, essentially Lazy<T>(g(f())).

Parameters
gFunction object.

Type requirement:

  • G::operator() when called with argument of type A&& has return type Lazy<T> for some type T.

    Returns
    Lazy composition.
    Note
    The g object is captured inside the returned lazy object by reference and must persist until the first evaluation of the return value.

◆ get() [1/2]

template<typename A>
A& ma::Lazy< A >::get ( )
inline
Returns
If the function has not yet been evaluated, evaluates it and stores its value. Then returns the stored value.

◆ get() [2/2]

template<typename A>
const A& ma::Lazy< A >::get ( ) const
inline
Returns
If the function has not yet been evaluated, evaluates it and stores its value. Then returns the stored value.

◆ isEvaluated()

template<typename A>
bool ma::Lazy< A >::isEvaluated ( ) const
inline
Returns
true iff has been evaluated.

◆ map() [1/2]

template<typename A>
template<typename G >
auto ma::Lazy< A >::map ( g) const -> Lazy<std::result_of_t<G(A)>>
inline

Composes self with g, that is, creates a new lazy value that yields the result of composing g with f, essentially Lazy<T>(g(f())).

Parameters
gFunction object.

Type requirement:

  • G::operator() when called with argument of type A&& has non-void return type.

    Returns
    Lazy composition.
    Note
    The g is captured inside the returned lazy object by reference and must persist until the first evaluation of the return value.

◆ map() [2/2]

template<typename A>
template<typename G >
auto ma::Lazy< A >::map ( g) -> Lazy<std::result_of_t<G(A)>>
inline

Composes self with g, that is, creates a new lazy value that yields the result of composing g with f, essentially Lazy<T>(g(f())).

Parameters
gFunction object.

Type requirement:

  • G::operator() when called with argument of type A&& has non-void return type.

    Returns
    Lazy composition.
    Note
    The g object is captured inside the returned lazy object by reference and must persist until the first evaluation of the return value.

Function Documentation

◆ Flatten() [1/2]

template<typename A >
Lazy<A> ma::Flatten ( const Lazy< Lazy< A >> &  LLa)

Flattens a nested Lazy.

Note that the none of the underlying computations is triggered and the returned lazy object is independent of the input.

◆ Flatten() [2/2]

template<typename A >
Lazy<A> ma::Flatten ( Lazy< Lazy< A >> &&  LLa)

Flattens a nested Lazy.

Note that the none of the underlying computations is triggered and on completion and the input is moved from.