Harald Achitz
Developer / Programmer
Forth Func Prog Sweden MeetUp 2020
Forth Func Prog Sweden MeetUp 2020


C++ for fun … ctional programmers … ???


History of C++
The language and the standard library
Functional ideas and concepts in C++
Some code
Most important C++ basics (imho)
Notable literature

1982 development starts
1985 first commercial implementation
1998 C++ iso standard, language and std library
… long break (minor update 03)
2011 C++11
2014 C++14
2017 C++17
2020 C++20
C++ is too complex. We need to make it smaller, simpler, and cleaner.
And please add these two features.
And whatever you do, don’t break my code!
Anybody who comes to you and says he has a perfect (programming) language is either naive or a salesman.
Clearly, I reject the view that there is one way that is right for everyone and for every problem.
A multi-paradigm programming language
A multi-paradigm programming language
Where imperative programming
meets object oriented programming
meets generic programming
meets functional programming
(… style)
A multi-paradigm programming language
It’s huge, where to start?
A multi-paradigm programming language
Within C++, there is a much smaller and clearer language struggling to get out
The Standard Template Library
(HP Software Technology Lab)
Alexander Stepanov
Silicon Graphics Inc.
2011 N. Shoreline Blvd.
Mt. View, CA 94043
stepanov@mti.sgi.com
Meng Lee
Hewlett-Packard Laboratories
1501 Page Mill Road
Palo Alto, CA 94304
lee@hpl.hp.com

It is the result of over 15 years of research in generic programming that I’ve done in different places, with different collaborators, and in different programming languages.
algorithm
container
iterator
function object
adaptor
algorithm
container
iterator
function object
adaptor
io (stream)
utilities
memory allocation
allocator
design documents
algorithm (+ parallel)
container
iterator
function object
adaptor
.. everything plus
threading
filesystem
type traits (made public)
new vocabulary types
ranges
… plus plus plus
It’s huge, … and still growing
Where to start ?

Filter
Map
Reduce (fold)
std::vector<int> data = {1,2,3,4,5} ;
auto even = [](int v){ return (v & 1) == 0 ;};
std::vector<int> even_numbers ;
std::copy_if(data.begin(), data.end(),
std::back_insert_iterator(even_numbers),
even);
//even_numbers => {2,4}std::vector<int> data = {1,2,3,4,5} ;
auto scale = 1.4 ;
std::vector<double> scaled ;
std::transform(data.begin(), data.end(),
std::back_insert_iterator(scaled),
[scale](int i){return i * scale;});
//scaled => {1.4, 2.8, 4.2, 5.6, 7.0}std::vector<int> data = {1,2,3,4,5} ;
auto v1 = std::accumulate(data.begin(), data.end(),
0, std::plus<>());
auto v2 = std::reduce(data.begin(), data.end(),
0, std::plus<>());std::vector<std::string> values{
"Forth", "functional",
"programming", "meetup"
} ;
auto char_cout = std::transform_reduce(
std::execution::par,
values.begin(), values.end(),
0, std::plus<>{},
[](const std::string& s) {
return s.size();
});
// char_cout == 32We saw dynamic memory management
We saw no pointers
We saw no new and no delete (or malloc/free)
We saw no raw loops
Higher order function
Immutability
Recursion
Function purity
Referential transparency
How do they map to C++, if they do at all
Yes!
C++ has higher order functions
std::vector<int> v;
// ...
auto negatives_to_zero = lift::if_then_else(
lift::less_than(0),
[](const auto&) { return 0;},
[](const auto& x) { return x;});
std::vector<int> result;
std::transform(std::begin(v), std::end(v),
std::back_inserter(result),
negatives_to_zero);C++ has const
It is not exactly the same.
Value semantic
References are explicit and a type
Everything is mutable until declared const
std::vector<int> a {1,2,3} ;
auto b = a ; // copy
b.push_back(4);
assert(a.size() == 3) ;
assert(b.size() == 4) ;// takes by value, copy construction
void f(std::vector<int> v) {
// my personal,local mutable data
b.push_back(4);
}
std::vector<int> a {1,2,3} ;
f(a);
assert(a.size() == 3) ;Value semantic
References are explicit and a type
Everything is mutable until declared const
std::vector<int> a {1,2,3} ;
auto& b = a ; // the '&' is important
b.push_back(4);
assert(a.size() == 4) ;
assert(b.size() == 4) ;Value semantic
References are explicit and a type
Everything is mutable until declared const
const variables and referencesconst int num = 42 ; // can not be changed
void f(const std::vector<int>& v) {
// v.push_back(4); Compile time error
// num = 32 ; Compile time error
}Yes, if you want, and you should
You can create immutable data structures
Yes, you can do recursion if you want
template<class FwdIt, class Comp = std::less<>>
void quick_sort(FwdIt first, FwdIt last,
Comp cmp = Comp{}){
const auto N = std::distance(first, last);
if (N <= 1) return;
const auto pivot = *std::next(first, N / 2);
const auto m1 = std::partition(
first, last, [=](const auto& elem){
return cmp(elem, pivot);
});
auto const m2 = std::partition(
m1, last, [=](const auto& elem){
return !cmp(pivot, elem);
});
quick_sort(first, m1, cmp);
quick_sort(m2, last, cmp);
}Yes, you can do recursion if you want.
Tail call optimization not part of the standard
There are loops (for, while, do/while)
Use algorithm!
Function purity
Referential transparency
Function purity
Referential transparency
Yes!
Even some C compilers (gcc) taking advantage via function attributes.
int hash (const char *) __attribute__ ((pure));
int square (int) __attribute__ ((const));This is C, it is up to the user to make guarantees!
C++ hast constexpr.
constexpr int hash (const char *) ;
constexpr int square (int) ;This is C++, the compiler make the guarantees!
Higher order function
Immutability
Recursion
Function purity
Referential transparency

A pointer is like a Maybe type.
A pointer is just some resource, like a file handler
void doSomething(const Data* data) {
if (data == nullptr) {
// there is no data
} else {
// ... we have data
}
}transferer ownership without copy
data that does not fit on the stack
(size, or re-size)
OS resource, socket, file descriptor, ..
Scope
void doSomething(const Data* data) { // scope
Foo f;
if (what_ever) { //scope
Bar b ;
} // ~b
{ // scope
Baz b;
} // ~b
} // ~fConstructor and Destructor
Resource creation ⇒ Constructor
Resource destruction ⇒ Destructor
class Foo{
// private resources
public:
Foo(/* arguments* /) {
/* create*/
} ;
~Foo() { /*release*/} ;
};Resource Acquisition Is Initialization
Bind the life cycle of a resource to the lifetime of an object.
For objects on the stack the } is the garbage collector ;-)
std::unique_ptrA smart pointer that owns a pointer and calls and action when it goes out of scope. There is only one owner. =⇒ This is the right default
std::shared_ptrA smart pointer that owns a pointer and calls and action when it goes out of scope. Multiple copies can exist, when the last instance goes out of scope, the resource is freed.
std::unique_ptr<Resource> build(int a, int b){
auto r = std::make_unique<Resource>(a,b) ;
// whatever with r
return r ;
}
void fun() {
auto res = build(1,2);
res->do_job1() ;
res->do_job2() ;
}Today’s C++, no new and no delete
Pointers are nothing to fear
We have seen how to use templates
std::vector<int>
std::unique_ptr<Resource>
std::make_unique<Resource>(a,b)
That’s a good start
C++ has now a range library
Better composable, can be lazy, hide iterator
Very new, C++20
std::vector<int> ints{0,1,2,3,4,5};
auto even = [](int i){ return 0 == i % 2; };
auto square = [](int i) { return i * i; };
std::ranges::for_each( ints |
std::views::filter(even) |
std::views::drop(1) |
std::views::transform(square) ,
[](const auto& v) { std::cout << v; }) ;Visual Studio (Code)
XCode
JetBrains CLion

