Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


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