Daniel Duffy
C++ author, trainer
Lecture videos are HERE
Lecture notes and HW pdf are at the bottom of this post
Please be sure you've read the HW Instructions prior to starting the exercises.
The objective of this exercise is to get you acquainted with lambda function syntax by examining some simple examples. Lambda functions are very important and useful and we shall be using them in other examples during the course.
In this exercise we concentrate on defining lambda functions that process arrays of double precision numbers (or integers) in various ways. In general, you need to think about a lambda’s signature, that is its return type and input arguments.
Answer the following questions:
a) Create a lambda function that multiplies each element of an array by a number. This number is a captured variable; test the function for the cases when it is copybyvalue and a reference. The original array is modified after having called the function.
b) Print the values of the modified array using auto to initialize the iterator variable instead of declaring it explicitly.
c) Write a lambda function to compute both the minimum and maximum of the elements in an array. The return type is an std::pair (or if you prefer, std::tuple with two elements) containing the computed minimum and maximum values in the array.
d) Compare the approach taken in part c) by calling std::minmax_element. For example, do you get the same output? How easy is to understand and reuse the code?
Exercise 2: Comparing Lambda Functions with Function Objects and Free Functions)
The objective of this exercise is to examine the application of lambda functions in C++ code. In this case we test some STL algorithms. In particular, we examine std::accumulate (by the way, it has two forms) that is a special fold function that iterates over the elements of an array and accumulates them in some way to produce scalar output. Consider the code to accumulate the elements of an array in some way. In other words it is a scalarvalued function that maps a vector to a scalar value.
The start code uses three functions, two of which are userdefined and the other is a predefined STL function object. The first two functions are:
and the algorithm is:
Answer the following questions:
a) Implement and test the algorithm using the generic lambda:
Can the algorithm also be used with complex numbers, for example? Can we use function objects to multiply the elements of an array of complex numbers?
Experiment with this kind of code in order to reach your conclusions.
b) Implement the accumulation algorithm using an embedded lambda function in combination with std::for_each() and captured variables.
c) Give an example of a stored lambda function that may be called from an STL algorithm (may be any relevant STL algorithm). Demonstrate using the STL algorithm with your stored lambda.
Review/Reflection for Yourself – no Submission required
Consider the code that you have written and consider the cases in which the use of lambda functions lead to more understandable, maintainable code than with function objects. For example, are lambda functions suitable for small chunks of code and system configuration? Some other tips:
_
Lecture notes and HW pdf are at the bottom of this post
Please be sure you've read the HW Instructions prior to starting the exercises.
1.1 Lambda Functions (video)
Exercise 1: First Encounters with Lambda Functions
The objective of this exercise is to get you acquainted with lambda function syntax by examining some simple examples. Lambda functions are very important and useful and we shall be using them in other examples during the course.
In this exercise we concentrate on defining lambda functions that process arrays of double precision numbers (or integers) in various ways. In general, you need to think about a lambda’s signature, that is its return type and input arguments.
Answer the following questions:
a) Create a lambda function that multiplies each element of an array by a number. This number is a captured variable; test the function for the cases when it is copybyvalue and a reference. The original array is modified after having called the function.
b) Print the values of the modified array using auto to initialize the iterator variable instead of declaring it explicitly.
c) Write a lambda function to compute both the minimum and maximum of the elements in an array. The return type is an std::pair (or if you prefer, std::tuple with two elements) containing the computed minimum and maximum values in the array.
d) Compare the approach taken in part c) by calling std::minmax_element. For example, do you get the same output? How easy is to understand and reuse the code?
Exercise 2: Comparing Lambda Functions with Function Objects and Free Functions)
The objective of this exercise is to examine the application of lambda functions in C++ code. In this case we test some STL algorithms. In particular, we examine std::accumulate (by the way, it has two forms) that is a special fold function that iterates over the elements of an array and accumulates them in some way to produce scalar output. Consider the code to accumulate the elements of an array in some way. In other words it is a scalarvalued function that maps a vector to a scalar value.
The start code uses three functions, two of which are userdefined and the other is a predefined STL function object. The first two functions are:
C++:
// N.B. Generic lambda
auto MyMultiply = [] (auto x, auto y) { return x*y ;};
struct FOMultiply
{
template <typename T>
T operator () (const T& x, const T& y)
{ return x * y; }
};
C++:
std::vector<int> vec { 1,2,3,4,5 };
int acc2 = std::accumulate(vec.begin(), vec.end(), initVal,
std::multiplies<int>());
int accA = accumulate(vec.begin(), vec.end(),
initVal, FOMultiply());
a) Implement and test the algorithm using the generic lambda:
C++:
auto MyMultiply = [] (auto x, auto y) { return x*y ;};
C++:
template <typename T>
T MyMultiply2(const T& x, const T& y) { return x*y; };
// Using complex numbers
using Complex = std::complex<double>;
std::vector<Complex>
complexArray{Complex(1.0, 1.0), Complex(2.0, 2.0) };
Complex initCVal(1.0, 1.0);
// auto acc6C = accumulate(complexArray.begin(),
// complexArray.end(), initCVal, FOMultiply());
Complex acc6C = accumulate(complexArray.begin(),
complexArray.end(), initCVal, MyMultiply2<Complex>);
std::cout << "Sum 6, complex numbers: " << acc6C << std::endl;
Experiment with this kind of code in order to reach your conclusions.
b) Implement the accumulation algorithm using an embedded lambda function in combination with std::for_each() and captured variables.
c) Give an example of a stored lambda function that may be called from an STL algorithm (may be any relevant STL algorithm). Demonstrate using the STL algorithm with your stored lambda.
Review/Reflection for Yourself – no Submission required
Consider the code that you have written and consider the cases in which the use of lambda functions lead to more understandable, maintainable code than with function objects. For example, are lambda functions suitable for small chunks of code and system configuration? Some other tips:
 More general function signatures.
 Other data types.
 Lambda versus free functions versus function object.
_
Attachments

4 MB Views: 363

302.1 KB Views: 66
Last edited by a moderator: