Lambda Expressions

In this code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Ex10_15.cpp Using lambda expressions
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std; // Just to avoid a lot of using directives in the example...
        
// Template function to return the average of the elements in a vector
template <class T> T average(const vector<T>& vec)
{
  static_assert(std::is_arithmetic<T>::value,
                            "Type parameter for average() must be aithmetic.");
  T sum(0);
  for_each(vec.begin(), vec.end(),
    [&sum](const T& value){ sum += value; });
  return sum/vec.size();
}
        
// Template function to set a vector to values beginning with start
// and incremented by increment
template <class T> void setValues(vector<T>& vec, T start, T increment)
{
  static_assert(std::is_arithmetic<T>::value,
                            "Type parameter for setValues() must be aithmetic.");
  T current(start);
  generate(begin(vec), end(vec),
    [increment, &current]()->T{T result(current);
                                current += increment;
                                return result;});
}
        
// Template function to set a vector to random values between min and max
template<class T> void randomValues(vector<T>& vec, T min, T max)
{
  static_assert(std::is_arithmetic<T>::value,
                            "Type parameter for randomValues() must be aithmetic.");
  srand(static_cast<unsigned int>(time(0)));   // Initialize random
                                              //  number generator
  generate(begin(vec), end(vec),
    [=](){ return static_cast<T>(static_cast<double>(rand())/
                                                     RAND_MAX*(max-min)+ min); });
}
        
// Template function to list the values in a vector
template<class T> void listVector(const vector<T>& vec)
{
  int count = 0;      // Used to control outputs per line
  const int valuesPerLine(5);
  for_each(begin(vec), end(vec),
    [&count, valuesPerLine](const T& n)->void{
                                 cout << setw(10) << n << "  ";
                                 if(++count % valuesPerLine == 0)
                                   cout << endl;});
}
        
int main()

{
  vector<int> integerData(50);
  randomValues(integerData, 1, 10);    // Set random integer values
  cout << "Vector contains:" << endl;
  listVector(integerData);
  cout << "Average value is "<< average(integerData) << endl;
        
  vector<double> realData(20);
  setValues(realData, 5.0, 2.5);   // Set real values starting at 5.0
  cout << "Vector contains:" << endl;
  listVector(realData);
  cout << "Average value is "<< average(realData) << endl;
        
   return 0;
}



From my Book:

"
"line 29"

1
2
3
[increment, &current]()->T{T result(current);
current += increment;
return result;}


The lambda accepts no arguments, but it accesses increment by value and current by reference, the latter being used to store the next value to be set. This lambda has the side effect that current will be updated when generate is finished. The following lambda expression is similar, but without the side effect:

1
2
3
[=]()mutable->T{T result(current);
current += increment;
return result;}
"


I dont exactly understand what side affect it is talking about. Wouldn't you want generate to update current?

I understand how the second code fixes it though, just takes everything in the enclosing scope by value.

Thanks in advance!
In the first example, you are taking current by reference so the += inside the function affects 'current' outside of the function. The second case does not, and so does not. That is the side effect that is being referred to; modification of a variable other than the parameters.

You need not have generate update 'current' since all it is doing is populating the range with values; it can (as in the second example), just make a copy of current and use that to generate its values without modifying the one in the outer scope.
Alright thanks!
Topic archived. No new replies allowed.