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

| Boost.Hana 1.7.1 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-2017
   // 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
   }
   eval.hpp
   Defines boost::hana::eval.
   boost::hana::_
   constexpr unspecified _
   Create simple functions representing C++ operators inline.
   Definition: placeholder.hpp:70
   lazy.hpp
   Defines boost::hana::lazy.
   boost::hana
   Namespace containing everything in the library.
   Definition: accessors.hpp:20
   placeholder.hpp
   Defines boost::hana::_.
   transform.hpp
   Defines boost::hana::transform.
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-2017
   // 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);
   }
   assert.hpp
   Defines macros to perform different kinds of assertions.
   chain.hpp
   Defines boost::hana::chain.
   boost::hana::in
   constexpr auto in
   Return whether the key occurs in the structure.
   Definition: contains.hpp:70
   BOOST_HANA_RUNTIME_CHECK
   #define BOOST_HANA_RUNTIME_CHECK(...)
   Equivalent to BOOST_HANA_RUNTIME_ASSERT, but not influenced by the BOOST_HANA_CONFIG_DISABLE_ASSERTIO...
   Definition: assert.hpp:209
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-2017
   // 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);
   }
   extend.hpp
   Defines boost::hana::extend.
   extract.hpp
   Defines boost::hana::extract.

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 friend auto | operator| (lazy< T... >, F)
| Equivalent to `hana::chain`.

## Associated functions

## ◆ eval

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-2017
// 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() { }

## ◆ make< lazy_tag >

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))
  boost::hana::lazy::make< lazy_tag >
  constexpr auto make< lazy_tag >
  Lifts a normal value to a lazy one.
  Definition: lazy.hpp:110
  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-2017
// 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);
}
bool.hpp
Defines the Logical and Comparable models of boost::hana::integral_constant.
config.hpp
Defines configuration macros used throughout the library.
boost::hana::if_
constexpr auto if_
Conditionally return one of two values based on a condition.
Definition: if.hpp:41
BOOST_HANA_CONSTEXPR_CHECK
#define BOOST_HANA_CONSTEXPR_CHECK(...)
Equivalent to BOOST_HANA_CONSTEXPR_ASSERT, but not influenced by the BOOST_HANA_CONFIG_DISABLE_ASSERT...
Definition: assert.hpp:300
if.hpp
Defines boost::hana::if_.

## ◆ make_lazy

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-2017
// 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);
}