Show Lecture.LambdaFunctions as a slide show.
CS253 Lambda Functions
Lambda
λ
This is the Greek letter lambda.
In C++, it refers to an anonymous function, an unnamed function,
a function literal.
Functions
- Functions are not first-class objects in C++.
- You can’t have a variable of type “function”, or even of type
“function taking no arguments and returning
int
”.
- You can’t copy a function.
- However, you can have a pointer to a function.
A function
Here’s a boring ordinary function:
bool odd(int n) { return n & 0b1; }
int main() {
cout << odd(42) << ' ' << odd(43) << '\n';
}
0 1
0b
indicates a binary constant. Sure, I could have written 0b1
as 1
, 01
, or 0x01
, but 0b1
stresses that it’s a bitmask.
Boolean values are displayed as 0
and 1
by default,
unless you use cout << boolalpha
.
Pointer to a function
bool odd(int n) { return n & 0b1; }
int main() {
bool (*p)(int) = odd;
cout << (*p)(42) << ' ' << p(43) << '\n';
}
0 1
p
is a variable of type “pointer to function taking a int
and returning a bool
”.
- Or,
p
is a pointer to function taking a int
and returning a bool
.
- So,
*p
is a function that takes a int
and returns a bool
.
- Some people (not me!) find such declarations hard to understand.
- For convenience,
*
is optional when calling the function.
auto
is your friend
bool odd(int n) { return n & 0b1; }
int main() {
auto p = odd;
cout << (*p)(42) << ' ' << p(43) << '\n';
}
0 1
auto
sure made that declaration easier!
There must be a better way.
- It seems a shame to have to name the function
odd
.
- Imagine if numbers worked that way:
cout << 355/113.0 << '\n'; // easy
3.14159
int a=355;
float b=113.0;
cout << a/b << '\n'; // tedious
3.14159
- It’s convenient to have unnamed numeric constants.
- If only we could have unnamed functions …
Alternate Function Syntax
There are two ways to declare a function return type:
int alpha() { return 42; }
auto beta() -> int { return 66; }
int main() {
cout << alpha() << ' ' << beta();
}
42 66
The alternate syntax exists to make template programming simpler;
it allows us to deduce the return type using the arguments.
Patience—neither of these are lambda functions.
Alternate Function Syntax
If the return type is not given, it is deduced:
int alpha() { return 42; }
auto gamma() { return 88; }
int main() {
cout << alpha() << ' ' << gamma();
}
42 88
Alternate Function Syntax
However, the return type must be unambiguous:
auto delta(bool flag) {
if (flag)
return 5;
else
return 6.7;
}
int main() {
cout << delta(true);
}
c.cc:5: error: inconsistent deduction for auto return type: 'int' and then
'double'
λ-expressions
auto p = [](int n) -> bool { return n & 0b1; };
cout << p(42) << ' ' << p(43) << '\n';
0 1
[](int n) -> int { return n & 0b1; }
is a lambda-expression
[]
is the capture-specification
- Stuff can go inside
[]
, but we’ll ignore that.
- Think of it as “here comes a λ-function”.
(int n)
is the argument list
-> bool
specifies the return type
- optional, if the compiler can figure it out
{ return n & 0b1; }
is the body
- I often forget the
;
at the end of the first line.
It’s an assignment statement, and so ends with a semicolon.
λ-expressions
The return-type may be deduced, if omitted:
auto p = [](int n) { return n & 0b1; };
cout << p(42) << ' ' << p(43) << '\n';
0 1
What is the return-type of the lambda-expression
pointed to by p
?
n
is an int
, 0b1
is an int
, so n & 0b1
is an int
.
- Therefore, the return-type is
int
.
- An
int
works as well as a bool
in this context.
- Before C had
bool
, it used int
as a boolean type.
Generic λ-expressions
Even the arguments can be auto
:
auto twice = [](auto v) { return v + v; };
cout << twice(3) << '\n'
<< twice(2.34) << '\n'
<< twice("Jack"s) << '\n'
<< twice('!') << '\n';
6
4.68
JackJack
66
This is more like a templated function, in that it defines a
family of functions.
No arguments
If no arguments are needed, the ()
can be omitted:
auto unique_id = [] { return getpid(); };
cout << unique_id() << '\n';
1021000
Use
- Well, this is all very impressive, but what good is it?
- Surely, it’s easier just to use regular functions.
- Functors and λ-expressions are useful with algorithms.