Boost.Hana: boost::hana::lazy< implementation_defined > Struct Template Reference

| Boost.Hana 1.0.0 Your standard library for metaprogramming |

Synopsis of associated functions | Friends | List of all members
boost::hana::lazy< implementation_defined > Struct Template Reference
Data types

## Description

### template<typename implementation_defined>
struct boost::hana::lazy< implementation_defined >

`hana::lazy` implements superficial laziness via a monadic interface.

It is important to understand that the laziness implemented by `lazy` is only superficial; only function applications made inside the `lazy` monad can be made lazy, not all their subexpressions.

Note
  The actual representation of `hana::lazy` is completely implementation-defined. Lazy values may only be created through `hana::make_lazy`, and they can be stored in variables using `auto`, but any other assumption about the representation of `hana::lazy<...>` should be avoided. In particular, one should not rely on the fact that `hana::lazy<...>` can be pattern-matched on, because it may be a dependent type.

## Modeled concepts

1. `Functor`
   Applying a function over a lazy value with `transform` returns the result of applying the function, as a lazy value.
   // Copyright Louis Dionne 2013-2016
   // Distributed under the Boost Software License, Version 1.0.
   // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
   #include <boost/hana/eval.hpp>
   #include <boost/hana/functional/placeholder.hpp>
   #include <boost/hana/lazy.hpp>
   #include <boost/hana/transform.hpp>
   namespace hana = boost::hana;
   using hana::_;
   int main() {
   static_assert(hana::eval(hana::transform(hana::make_lazy(4 / _)(1), _ * 3)) == (4 / 1) * 3, "");
   hana::transform(hana::make_lazy(4 / _)(0), _ * 3); // never evaluated
   }
2. `Applicative`
   A normal value can be lifted into a lazy value by using `lift<lazy_tag>`. A lazy function can be lazily applied to a lazy value by using `ap`.
3. `Monad`
   The `lazy` monad allows combining lazy computations into larger lazy computations. Note that the `|` operator can be used in place of the `chain` function.
   // Copyright Louis Dionne 2013-2016
   // Distributed under the Boost Software License, Version 1.0.
   // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
   #include <boost/hana/assert.hpp>
   #include <boost/hana/chain.hpp>
   #include <boost/hana/eval.hpp>
   #include <boost/hana/lazy.hpp>
   #include <functional>
   #include <iostream>
   #include <sstream>
   namespace hana = boost::hana;
   template <typename T>
   T read_(std::istream& stream) {
   T x;
   stream >> x;
   std::cout << "read " << x << " from the stream\n";
   return x;
   }
   int main() {
   std::stringstream ss;
   int in = 123;
   std::cout << "creating the monadic chain...\n";
   auto out = hana::make_lazy(read_<int>)(std::ref(ss))
   | [](auto x) {
   std::cout << "performing x + 1...\n";
   return hana::make_lazy(x + 1);
   }
   | [](auto x) {
   std::cout << "performing x / 2...\n";
   return hana::make_lazy(x / 2);
   };
   std::cout << "putting " << in << " in the stream...\n";
   ss << in; // nothing is evaluated yet
   std::cout << "evaluating the monadic chain...\n";
   auto eout = hana::eval(out);
   std::cout << "the result of the monadic chain is " << eout << "\n";
   BOOST_HANA_RUNTIME_CHECK(eout == (in + 1) / 2);
   }
4. `Comonad`
   The `lazy` comonad allows evaluating a lazy computation to get its result and lazily applying functions taking lazy inputs to lazy values. This blog post goes into more details about lazy evaluation and comonads.
   // Copyright Louis Dionne 2013-2016
   // Distributed under the Boost Software License, Version 1.0.
   // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
   #include <boost/hana/assert.hpp>
   #include <boost/hana/eval.hpp>
   #include <boost/hana/extend.hpp>
   #include <boost/hana/extract.hpp>
   #include <boost/hana/lazy.hpp>
   #include <sstream>
   namespace hana = boost::hana;
   int main() {
   std::stringstream s("1 2 3");
   auto i = hana::make_lazy([&] {
   int i;
   s >> i;
   return i;
   })();
   auto i_plus_one = hana::extend(i, [](auto lazy_int) {
   return hana::eval(lazy_int) + 1;
   });
   BOOST_HANA_RUNTIME_CHECK(hana::extract(i_plus_one) == 2);
   BOOST_HANA_RUNTIME_CHECK(hana::extract(i_plus_one) == 3);
   BOOST_HANA_RUNTIME_CHECK(hana::extract(i_plus_one) == 4);
   }

Note
  `hana::lazy` only models a few concepts because providing more functionality would require evaluating the lazy values in most cases. Since this raises some issues such as side effects and memoization, the interface is kept minimal.

## Synopsis of associated functions

constexpr auto | eval
| Evaluate a lazy value and return it. More...
template<>
constexpr auto | make< lazy_tag >
| Lifts a normal value to a lazy one. More...
constexpr auto | make_lazy = make<lazy_tag>
| Alias to `make<lazy_tag>`; provided for convenience. More...

## Friends

template<typename... T, typename F >
constexpr auto | operator| (lazy< T... >, F)
| Equivalent to `hana::chain`.

## Associated functions

template<typename implementation_defined >

constexpr auto eval

related

Initial value:
= [](auto&& see_documentation) -> decltype(auto) {
return tag-dispatched;
}

Evaluate a lazy value and return it.

Given a lazy expression `expr`, `eval` evaluates `expr` and returns the result as a normal value. However, for convenience, `eval` can also be used with nullary and unary function objects. Specifically, if `expr` is not a `hana::lazy`, it is called with no arguments at all and the result of that call (`expr()`) is returned. Otherwise, if `expr()` is ill-formed, then `expr(hana::id)` is returned instead. If that expression is ill-formed, then a compile-time error is triggered.

The reason for allowing nullary callables in `eval` is because this allows using nullary lambdas as lazy branches to `eval_if`, which is convenient. The reason for allowing unary callables and calling them with `hana::id` is because this allows deferring the compile-time evaluation of selected expressions inside the callable. How this can be achieved is documented by `hana::eval_if`.

## Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/eval.hpp>
#include <boost/hana/functional/placeholder.hpp>
#include <boost/hana/lazy.hpp>
namespace hana = boost::hana;
static_assert(hana::eval(hana::make_lazy(hana::_ + 1)(3)) == 4, "");
int main() { }
template<typename implementation_defined >
template<>

constexpr auto make< lazy_tag >

related

Initial value:
= [](auto&& x) {
return lazy<implementation_defined>{forwarded(x)};
}

Lifts a normal value to a lazy one.

`make<lazy_tag>` can be used to lift a normal value or a function call into a lazy expression. Precisely, `make<lazy_tag>(x)` is a lazy value equal to `x`, and `make<lazy_tag>(f)(x1, ..., xN)` is a lazy function call that is equal to `f(x1, ..., xN)` when it is `eval`uated.

Note
  It is interesting to note that `make<lazy_tag>(f)(x1, ..., xN)` is equivalent to
  ap(make<lazy_tag>(f), lift<lazy_tag>(x1), ..., lift<lazy_tag>(xN))
  which in turn is equivalent to `make<lazy_tag>(f(x1, ..., xN))`, except for the fact that the inner call to `f` is evaluated lazily.

## Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/assert.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/eval.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/lazy.hpp>
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto f = hana::make<hana::lazy_tag>([](auto x) {
return 1 / x;
});
BOOST_HANA_CONSTEXPR_LAMBDA auto g = hana::make_lazy([](auto x) {
return x + 1;
});
BOOST_HANA_CONSTEXPR_CHECK(hana::eval(hana::if_(hana::false_c, f(0), g(0))) == 0 + 1);
}
template<typename implementation_defined >

constexpr auto make_lazy = make<lazy_tag>

related

Alias to `make<lazy_tag>`; provided for convenience.

## Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/assert.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/eval.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/lazy.hpp>
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto f = hana::make<hana::lazy_tag>([](auto x) {
return 1 / x;
});
BOOST_HANA_CONSTEXPR_LAMBDA auto g = hana::make_lazy([](auto x) {
return x + 1;
});
BOOST_HANA_CONSTEXPR_CHECK(hana::eval(hana::if_(hana::false_c, f(0), g(0))) == 0 + 1);
}