RSS GitHub LinkedIn

Lazy Evaluation - Epilogue

Summary of lazy evaluation using bind expressions.

This series on lazy evaluation as unveiled an untapped potential of bind expressions. Lazy bind expressions provide a compact notation for their construction, which has many applications including symbolic differentiation. Lazy bind expressions are compliant with the standard.

Prologue

The prologue explains bind expressions and how to pass overloaded functions as function arguments by wrapping them as function objects.

Lazy Operators

Lazy operators provides a compact notation to create bind expressions. This is done by overloading operators for lazy arguments – bind expressions or placeholders.

A custom placeholder with an assignment operator is introduced. This placeholder is used as a user-defined literal, such as 1_p.

sort(first, last, 1_p < 2_p);

Lazy Functions

Lazy functions supplements the compact notation with overloaded functions for lazy arguments.

Reseat ramp
Extending at placeholder
sort(first, last, via::abs(1_p) < via::abs(2_p));

The lazy bind expressions uses customization point objects as the bound function. These are function objects that use argument-dependent lookup to find overloaded functions. As a consequence, lazy functions can be invoked with lazy arguments to produce new lazy bind expressions.

auto ramp      = via::max(0, 1_p); // Bind expression
auto ramp_diff = ramp(1_p - 2_p);  // Extended bind expression

Lazy Algorithms

Lazy algorithms demonstrates lazy bind expressions working seamlessly with standard algorithms.

// Counts positive elements
auto r = std::count_if(first, last, 1_p > 0);

Multivariate for-each and fold algorithms are provided.

// int sum = std::inner_product(first, last, second, 0);

auto r = fold(1_p + 2_p * 3_p, 0, first, last, second);
// where
//   r = 0
//   r = r + first[0] * second[0]
//   r = r + first[1] * second[1]
//   ...

Lazy References

Lazy references are reference wrappers with member operators, such as assignment or subscripting.

// a = std::accumulate(first, last, a);

each(bind_ref(a) += 1_p, first, last);

Expression Templates

Expression templates are syntactic sugar for element-wise vector operations. Lazy references and bind expressions are used as building-blocks.

Automatic Differentiation

Automatic differentiation is possible by combining lazy bind expressions with dual numbers. Symbolic differentiation materializes when using lazy dual numbers.

Consider the derivative of a composed function

$$\begin{eqnarray*} \frac{d}{dx} \sin(x^2) &=& 2\ x \cos(x^2) \end{eqnarray*}$$

Invoking the function with a lazy dual number yields its derivative as a bind expression.

auto x = dual::make_number(1_p, 1);

auto f = via::sin(x * x);
// where
//   f.tangent() == (1_p * 1 + 1 * 1_p) * via::cos(1_p * 1_p);




© 2026 Bjørn Reese.