JMU
Lambda Expressions
An Introduction with Examples in C++


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Motivation
Syntax
The Type of a Lambda Expression
The Type of a Lambda Expression (cont.)
An Example
An Example (cont.)

The closest() Function

cppexamples/lambdas/VectorMathExample.cpp (Fragment: closest)
        /**
 * A function that finds the distance between an origin
 * and the closest destination.
 *
 * @param origin        The origin
 * @param destinations  The destinations
 * @param m             The number of destinations
 * @pram metric         The metric to use
 * @return              The distance to the closest destination
 */
double closest(double origin[2], double destinations[][2], int m,
               std::function<double (double[], double[])> metric) {
  
  double  min = INFINITY;

  for (int i=0; i<m; i++) {
    double temp = metric(origin, destinations[i]);
    if (temp < min) {
      min = temp;
    }
  }
  return min;
}
        

Note: This function is passed the origin, the destinations, the number of destinations, and the std::function to use to calculate the distance.

An Example (cont.)

One Invocation of closest()

cppexamples/lambdas/VectorMathExample.cpp (Fragment: Euclidean)
          distance = closest(origin, destinations, 3,
                     // A Lambda expression for the Euclidean distance
                     [](double p[2], double q[2]) -> double {
                       double sum = 0.0;
                       for (int i=0; i<2; i++) {
                         sum += (p[i] - q[i])*(p[i] - q[i]);
                       }
                       return sqrt(sum);
                     });
        
An Example (cont.)

Another Invocation of closest()

cppexamples/lambdas/VectorMathExample.cpp (Fragment: rectilinear)
          double distance;
  distance = closest(origin, destinations, 3,
                     // A Lambda expression for the rectilinear distance
                     [](double p[2], double q[2]) -> double {
                       double sum = 0.0;
                       for (int i=0; i<2; i++) {
                         sum += abs(p[i] - q[i]);
                       }
                       return sum;
                     });
        
Another Example
Another Example (cont.)

The assertThrows() Function

/**
 * Check to see if a lambda expression throws a particular exception.
 *
 * @tparam T       The class of the exception
 * @param  lambda  The lambda expression to execute
 * @throws         invalid_argument if the exception is not thrown
 */
template<class T>
void assertThrows(std::function<void ()> lambda) {
  bool doesThrow = false;
  
  try {
    lambda();
  } catch(const exception& e) {
    doesThrow = dynamic_cast<const T*>(&e) != nullptr;
  }
  
  if (!doesThrow) {
    throw(invalid_argument("Expected " + string(typeid(T).name()) + " to be thrown"));
  }
}
Another Example (cont.)

The Unit Test

    try {
      assertThrows<out_of_range>([](void) {
      
        Sequence seq = {3,4,6};
          
        seq.get(-1);
      });
    } catch (const invalid_argument& ia) { 
      printf("Failed test: %s\n", ia.what());
    }