Browse DevX
Sign up for e-mail newsletters from DevX


Creating Unnamed Functions with the Lambda Library-3 : Page 3




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Creating a Lambda Expression
The lambda library enables you to rewrite the previous for_each() call like this:

for_each(s.begin(), s.end(), _1 = '*');

The interesting part is the third argument:

_1 = '*'

This expression creates a lambda functor which writes * to every character in s. The syntax seems unusual, so let's see how it works under the hood.

The identifier _1 (an underscore followed by the number one, not a lowercase "L") is called a placeholder. It's the crux of the lambda functor. Within each iteration of for_each(), the functor is called with a different element of s as its actual argument. This actual argument is substituted for the placeholder _1, and the body of the lambda functor is evaluated. Thus, within the first iteration _1 is translated to s[0], then s[1] and so on.

Delaying the Evaluation of Constants and Variables
The following line outputs the elements of a vector. Each element is followed by a space:

vector <int> vi; vi.push_back(10); vi.push_back(20); vi.push_back(30); for_each(vi.begin(), vi.end(), cout << _1 << ' ');

Remember to understand what a lambda functor such as:

std::cout << _1 << ' '

does on each iteration, simply replace the placeholder with an actual argument e.g., vi[0]. As expected, this for_each() call outputs:

10 20 30

Now suppose you want to insert a space before each element. You modify the for_each() call slightly:

for_each(vi.begin(), vi.end(), cout << ' ' <<_1);

This however doesn't work as expected. It outputs a single space followed by the elements of vi with no separators. The problem is that none of the operands of:

cout << ' '

is a lambda expression. Therefore, this expression is evaluated immediately, causing a single space to be displayed. In such cases, you need to use the constant() function for delaying the evaluation of constants:

for_each(vi.begin(), vi.end(), cout << constant(' ') << _1);

This time, you get the desired output:

10 20 30

The expression constant(' ') produces a nullary lambda functor that stores the character constant ' ' and returns a reference to it when called.

A similar problem arises when you use variables in a lambda expression:

int idx = 0; for_each(vi.begin(), vi.end(), cout << ++idx << ':' << _1 << '\n');

Here, idx is incremented and displayed only once while the rest of the elements are displayed sequentially. To get the desired results, wrap idx with the function var():

for_each(vi.begin(), vi.end(), cout << ++var(index) << ':' << _1 << '\n');

Now you get the desired output:

1:10 2:20 3:30

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date