Functional C++
@KevlinHenney
https://twitter.com/mfeathers/status/29581296216
functional
programming
higher-order functions
recursion
statelessness
first-class functions
immutability
pure functions
unification
declarative
pattern matching
non-strict evaluation
idempotence
lists
mathematics
lambdas
currying
monads
class heating_system
{
public:
void turn_on();
void turn_off();
...
};
class timer
{
public:
timer(time_of_day when, command & what);
void run();
void cancel();
...
};
class command
{
public:
virtual void execute() = 0;
...
};
class turn_on : public command
{
public:
explicit turn_on(heating_system & heating)
: heating(heating)
{
}
void execute() override
{
heating.turn_on();
}
private:
heating_system & heating;
};
class turn_off : public command
{
public:
explicit turn_off(heating_system & heating)
: heating(heating)
class turn_on : public command
{
public:
explicit turn_on(heating_system & heating)
: heating(heating)
{
}
void execute() override
{
heating.turn_on();
}
private:
heating_system & heating;
};
class turn_off : public command
{
public:
explicit turn_off(heating_system & heating)
: heating(heating)
{
}
void execute() override
{
heating.turn_off();
}
private:
heating_system & heating;
};
class timer
{
public:
timer(
time_of_day when,
void execute(void * context), void * context);
void run();
void cancel();
...
};
void turn_on(void * context)
{
static_cast<heating_system *>(context)->turn_on();
}
void turn_off(void * context)
{
static_cast<heating_system *>(context)->turn_off();
}
class timer
{
public:
timer(time_of_day when, function<void()> what);
void run();
void cancel();
...
};
timer on(
time_on,
std::bind(&heating_system::turn_on, &heating));
timer off(
time_off,
std::bind(&heating_system::turn_off, &heating));
timer on(time_on, [&] { heating.turn_on(); });
timer off(time_off, [&] { heating.turn_off(); });
William Cook, "On Understanding Data Abstraction, Revisited"
[](){}
[](){}()
paraskevidekatriaphobia, noun
 The superstitious fear of Friday 13th.
 Contrary to popular myth, this superstition is relatively recent
(19th century) and did not originate during or before the
medieval times.
 Paraskevidekatriaphobia (or friggatriskaidekaphobia) also
reflects a particularly egocentric attributional bias: the universe
is prepared to rearrange causality and probability around the
believer based on an arbitrary and changeable calendar system,
in a way that is sensitive to geography, culture and time zone.
WordFriday.com
struct tm next_friday_13th(const struct tm * after)
{
struct tm next = *after;
enum { daily_secs = 24 * 60 * 60 };
time_t seconds =
mktime(&next) +
(next.tm_mday == 13 ? daily_secs : 0);
do
{
seconds += daily_secs;
next = *localtime(&seconds);
}
while(next.tm_mday != 13 || next.tm_wday != 5);
return next;
}
std::find_if(
++begin, day_iterator(),
[](const std::tm & day)
{
return day.tm_mday == 13 && day.tm_wday == 5;
});
class day_iterator : public std::iterator<...>
{
public:
day_iterator() ...
explicit day_iterator(const std::tm & start) ...
const std::tm & operator*() const
{
return day;
}
const std::tm * operator->() const
{
return &day;
}
day_iterator & operator++()
{
std::time_t seconds = std::mktime(&day) + 24 * 60 * 60;
day = *std::localtime(&seconds);
return *this;
}
day_iterator operator++(int) ...
...
};
http://www.adampetersen.se/articles/fizzbuzz.htm
http://www.adampetersen.se/articles/fizzbuzz.htm
enum fizzbuzzed
{
fizz = -2,
buzz = -1,
fizzbuzz = 0,
first = 1,
last = 100
};
constexpr fizzbuzzed fizzbuzz_of(int n)
{
return
n % 3 == 0 && n % 5 == 0 ? fizzbuzz :
n % 3 == 0 ? fizz :
n % 5 == 0 ? buzz :
fizzbuzzed(n);
}
When it is not
necessary to
change, it is
necessary not to
change.
Lucius Cary
const
&
&&
Immutable Value
References to value objects are commonly distributed and
stored in fields. However, state changes to a value caused
by one object can have unexpected and unwanted side-
effects for any other object sharing the same value
instance. Copying the value can reduce the
synchronization overhead, but can also incur object
creation overhead.
Therefore:
Define a value object type whose instances are immutable.
The internal state of a value object is set at construction
and no subsequent modifications are allowed.
Copied Value
Value objects are commonly distributed and stored in
fields. If value objects are shared between threads,
however, state changes caused by one object to a value
can have unexpected and unwanted side effects for any
other object sharing the same value instance. In a multi-
threaded environment shared state must be synchronized
between threads, but this introduces costly overhead for
frequent access.
Therefore:
Define a value object type whose instances are copyable.
When a value is used in communication with another
thread, ensure that the value is copied.
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
void set_year(int);
void set_month(int);
void set_day_in_month(int);
...
};
Just because you
have a getter,
doesn't mean you
should have a
matching setter.
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
void set(int year, int month, int day_in_month);
...
};
today.set(2015, 9, 14);
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
};
today = date(2015, 9, 14);
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
};
today = date { 2015, 9, 14 };
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
};
today = { 2015, 9, 14 };
"Get something"
is an imperative
with an expected
side effect.
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int get_year() const;
int get_month() const;
int get_day_in_month() const;
...
};
class date
{
public:
date(int year, int month, int day_in_month);
date(const date &);
date & operator=(const date &);
...
int year() const;
int month() const;
int day_in_month() const;
...
};
Conversions
Overloading
Derivation
Genericity
Mutability
Referential transparency is a very
desirable property: it implies that
functions consistently yield the same
results given the same input,
irrespective of where and when they are
invoked. That is, function evaluation
depends less—ideally, not at all—on the
side effects of mutable state.
Edward Garson
"Apply Functional Programming Principles"
Asking a question
should not change
the answer.
Bertrand Meyer
Asking a question
should not change
the answer, and
nor should asking
it twice!
A book is simply the
container of an idea like
a bottle; what is inside
the book is what matters.
Angela Carter
// "FTL" (Functional Template Library :->)
// container style
template<typename ValueType>
class container
{
public:
typedef const ValueType value_type;
typedef ... iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
...
container & operator=(const container &);
...
};
template<typename ValueType>
class set
{
public:
typedef const ValueType * iterator;
...
set(std::initializer_list<ValueType> values);
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
iterator find(const ValueType &) const;
std::size_t count(const ValueType &) const;
iterator lower_bound(const ValueType &) const;
iterator upper_bound(const ValueType &) const;
pair<iterator, iterator> equal_range(const ValueType &) const;
...
private:
ValueType * members;
std::size_t cardinality;
};
set<int> c { 2, 9, 9, 7, 9, 2, 4, 5, 8 };
template<typename ValueType>
class array
{
public:
typedef const ValueType * iterator;
...
array(std::initializer_list<ValueType> values);
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
...
private:
ValueType * elements;
std::size_t length;
};
array<int> c { 2, 9, 9, 7, 9, 2, 4, 5, 8 };
In computing, a persistent data structure is a data structure
that always preserves the previous version of itself when it is
modified. Such data structures are effectively immutable, as
their operations do not (visibly) update the structure in-place,
but instead always yield a new updated structure.
http://en.wikipedia.org/wiki/Persistent_data_structure
(A persistent data structure is not a data structure committed
to persistent storage, such as a disk; this is a different and
unrelated sense of the word "persistent.")
template<typename ValueType>
class vector
{
public:
typedef const ValueType * iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
vector pop_front() const;
vector pop_back() const;
...
private:
ValueType * anchor;
iterator from, until;
};
template<typename ValueType>
class vector
{
public:
typedef const ValueType * iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
vector pop_front() const;
vector pop_back() const;
...
private:
ValueType * anchor;
iterator from, until;
};
template<typename ValueType>
class vector
{
public:
typedef const ValueType * iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
vector popped_front() const;
vector popped_back() const;
...
private:
ValueType * anchor;
iterator from, until;
};
template<typename ValueType>
class vector
{
public:
typedef const ValueType * iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
vector popped_front() const;
vector popped_back() const;
...
private:
ValueType * anchor;
iterator from, until;
};
I still have a deep fondness for the
Lisp model. It is simple, elegant, and
something with which all developers
should have an infatuation at least
once in their programming life.
Kevlin Henney
"A Fair Share (Part I)", CUJ C++ Experts Forum, October 2002
lispt
template<typename ValueType>
class list
{
public:
class iterator;
...
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & front() const;
list popped_front() const;
list pushed_front() const;
...
private:
struct link
{
link(const ValueType & value, link * next);
ValueType value;
link * next;
};
link * head;
std::size_t length;
};
Hamlet: Yea, from the table
of my memory I'll wipe away
all trivial fond records.
William Shakespeare
The Tragedy of Hamlet
[Act I, Scene 5]
Garbage collection [...] is optional
in C++; that is, a garbage collector
is not a compulsory part of an
implementation.
Bjarne Stroustrup
http://stroustrup.com/C++11FAQ.html
assert(
std::get_pointer_safety() ==
std::pointer_safety::strict);
Ophelia: 'Tis in my memory
locked, and you yourself shall
keep the key of it.
William Shakespeare
The Tragedy of Hamlet
[Act I, Scene 3]
A use-counted class is more
complicated than a non-use-
counted equivalent, and all of
this horsing around with use
counts takes a significant
amount of processing time.
Robert Murray
C++ Strategies and Tactics
template<typename ValueType>
class vector
{
public:
typedef const ValueType * iterator;
...
bool empty() const;
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & operator[](std::size_t) const;
const ValueType & front() const;
const ValueType & back() const;
const ValueType * data() const;
vector popped_front() const;
vector popped_back() const;
...
private:
std::shared_ptr<ValueType> anchor;
iterator from, until;
};
Uses std::default_delete<ValueType[]>, but
cannot be initialised from std::make_shared
template<typename ValueType>
class list
{
public:
class iterator;
...
std::size_t size() const;
iterator begin() const;
iterator end() const;
const ValueType & front() const;
list popped_front() const;
list pushed_front() const;
...
private:
struct link
{
link(const ValueType & value, std::shared_ptr<link> next);
ValueType value;
std::shared_ptr<link> next;
};
std::shared_ptr<link> head;
std::size_t length;
};
{
list<Anything> chain;
std::fill_n(
std::front_inserter(chain),
how_many,
something);
}
On destruction, deletion of links is recursive
through each link, causing the stack to blow up
for surprisingly small values of how_many.
Concurrency
Concurrency
Threads
Concurrency
Threads
Locks
All computers
wait at the
same speed.
Some people, when confronted with a
problem, think, "I know, I'll use threads,"
and then two they hav erpoblesms.
Ned Batchelder
https://twitter.com/#!/nedbat/status/194873829825327104
Shared memory is like a canvas where
threads collaborate in painting images,
except that they stand on the opposite
sides of the canvas and use guns rather
than brushes. The only way they can
avoid killing each other is if they shout
"duck!" before opening fire.
Bartosz Milewski
"Functional Data Structures and Concurrency in C++"
http://bartoszmilewski.com/2013/12/10/functional-data-structures-and-concurrency-in-c/
Mutable
Immutable
Unshared Shared
Unshared mutable
data needs no
synchronisation
Unshared immutable
data needs no
synchronisation
Shared mutable
data needs
synchronisation
Shared immutable
data needs no
synchronisation
Mutable
Immutable
Unshared Shared
Unshared mutable
data needs no
synchronisation
Unshared immutable
data needs no
synchronisation
Shared mutable
data needs
synchronisation
Shared immutable
data needs no
synchronisation
The Synchronisation Quadrant
std::string fizzbuzz(int n)
{
return
n % 3 == 0 && n % 5 == 0 ? "FizzBuzz" :
n % 3 == 0 ? "Fizz" :
n % 5 == 0 ? "Buzz" :
std::to_string(n);
}
void fizzbuzzer(
channel<int> & receive,
channel<std::string> & send)
{
for(int n; receive >> n;)
send << fizzbuzz(n);
}
int main()
{
channel<int> out;
channel<std::string> back;
std::thread fizzbuzzing(fizzbuzzer, out, back)
for(int n = 1; n <= 100; ++n)
{
out << n;
std::string result;
back >> result;
std::cout << result << "n";
}
...
}
Sender Receiver A
Message 1Message 3
Receiver B
In response to a message that it receives, an actor
can make local decisions, create more actors, send
more messages, and determine how to respond to
the next message received.
http://en.wikipedia.org/wiki/Actor_model
Multithreading is just one
damn thing after, before, or
simultaneous with another.
Andrei Alexandrescu
Actor-based concurrency is
just one damn message after
another.
Go with
the flow.
Queens of the Stone Age

Functional C++

  • 1.
  • 4.
  • 6.
    functional programming higher-order functions recursion statelessness first-class functions immutability purefunctions unification declarative pattern matching non-strict evaluation idempotence lists mathematics lambdas currying monads
  • 7.
  • 8.
    class timer { public: timer(time_of_day when,command & what); void run(); void cancel(); ... }; class command { public: virtual void execute() = 0; ... };
  • 9.
    class turn_on :public command { public: explicit turn_on(heating_system & heating) : heating(heating) { } void execute() override { heating.turn_on(); } private: heating_system & heating; }; class turn_off : public command { public: explicit turn_off(heating_system & heating) : heating(heating)
  • 10.
    class turn_on :public command { public: explicit turn_on(heating_system & heating) : heating(heating) { } void execute() override { heating.turn_on(); } private: heating_system & heating; }; class turn_off : public command { public: explicit turn_off(heating_system & heating) : heating(heating) { } void execute() override { heating.turn_off(); } private: heating_system & heating; };
  • 11.
    class timer { public: timer( time_of_day when, voidexecute(void * context), void * context); void run(); void cancel(); ... };
  • 12.
    void turn_on(void *context) { static_cast<heating_system *>(context)->turn_on(); } void turn_off(void * context) { static_cast<heating_system *>(context)->turn_off(); }
  • 13.
    class timer { public: timer(time_of_day when,function<void()> what); void run(); void cancel(); ... };
  • 14.
    timer on( time_on, std::bind(&heating_system::turn_on, &heating)); timeroff( time_off, std::bind(&heating_system::turn_off, &heating));
  • 15.
    timer on(time_on, [&]{ heating.turn_on(); }); timer off(time_off, [&] { heating.turn_off(); });
  • 16.
    William Cook, "OnUnderstanding Data Abstraction, Revisited"
  • 17.
  • 18.
  • 21.
    paraskevidekatriaphobia, noun  Thesuperstitious fear of Friday 13th.  Contrary to popular myth, this superstition is relatively recent (19th century) and did not originate during or before the medieval times.  Paraskevidekatriaphobia (or friggatriskaidekaphobia) also reflects a particularly egocentric attributional bias: the universe is prepared to rearrange causality and probability around the believer based on an arbitrary and changeable calendar system, in a way that is sensitive to geography, culture and time zone. WordFriday.com
  • 22.
    struct tm next_friday_13th(conststruct tm * after) { struct tm next = *after; enum { daily_secs = 24 * 60 * 60 }; time_t seconds = mktime(&next) + (next.tm_mday == 13 ? daily_secs : 0); do { seconds += daily_secs; next = *localtime(&seconds); } while(next.tm_mday != 13 || next.tm_wday != 5); return next; }
  • 23.
    std::find_if( ++begin, day_iterator(), [](const std::tm& day) { return day.tm_mday == 13 && day.tm_wday == 5; });
  • 24.
    class day_iterator :public std::iterator<...> { public: day_iterator() ... explicit day_iterator(const std::tm & start) ... const std::tm & operator*() const { return day; } const std::tm * operator->() const { return &day; } day_iterator & operator++() { std::time_t seconds = std::mktime(&day) + 24 * 60 * 60; day = *std::localtime(&seconds); return *this; } day_iterator operator++(int) ... ... };
  • 27.
  • 28.
  • 29.
    enum fizzbuzzed { fizz =-2, buzz = -1, fizzbuzz = 0, first = 1, last = 100 }; constexpr fizzbuzzed fizzbuzz_of(int n) { return n % 3 == 0 && n % 5 == 0 ? fizzbuzz : n % 3 == 0 ? fizz : n % 5 == 0 ? buzz : fizzbuzzed(n); }
  • 30.
    When it isnot necessary to change, it is necessary not to change. Lucius Cary
  • 31.
  • 32.
  • 33.
  • 35.
    Immutable Value References tovalue objects are commonly distributed and stored in fields. However, state changes to a value caused by one object can have unexpected and unwanted side- effects for any other object sharing the same value instance. Copying the value can reduce the synchronization overhead, but can also incur object creation overhead. Therefore: Define a value object type whose instances are immutable. The internal state of a value object is set at construction and no subsequent modifications are allowed.
  • 36.
    Copied Value Value objectsare commonly distributed and stored in fields. If value objects are shared between threads, however, state changes caused by one object to a value can have unexpected and unwanted side effects for any other object sharing the same value instance. In a multi- threaded environment shared state must be synchronized between threads, but this introduces costly overhead for frequent access. Therefore: Define a value object type whose instances are copyable. When a value is used in communication with another thread, ensure that the value is copied.
  • 37.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... void set_year(int); void set_month(int); void set_day_in_month(int); ... };
  • 38.
    Just because you havea getter, doesn't mean you should have a matching setter.
  • 39.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... void set(int year, int month, int day_in_month); ... }; today.set(2015, 9, 14);
  • 40.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... }; today = date(2015, 9, 14);
  • 41.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... }; today = date { 2015, 9, 14 };
  • 42.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... }; today = { 2015, 9, 14 };
  • 43.
    "Get something" is animperative with an expected side effect.
  • 44.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int get_year() const; int get_month() const; int get_day_in_month() const; ... };
  • 45.
    class date { public: date(int year,int month, int day_in_month); date(const date &); date & operator=(const date &); ... int year() const; int month() const; int day_in_month() const; ... };
  • 46.
  • 48.
    Referential transparency isa very desirable property: it implies that functions consistently yield the same results given the same input, irrespective of where and when they are invoked. That is, function evaluation depends less—ideally, not at all—on the side effects of mutable state. Edward Garson "Apply Functional Programming Principles"
  • 49.
    Asking a question shouldnot change the answer. Bertrand Meyer
  • 50.
    Asking a question shouldnot change the answer, and nor should asking it twice!
  • 51.
    A book issimply the container of an idea like a bottle; what is inside the book is what matters. Angela Carter
  • 52.
    // "FTL" (FunctionalTemplate Library :->) // container style template<typename ValueType> class container { public: typedef const ValueType value_type; typedef ... iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; ... container & operator=(const container &); ... };
  • 53.
    template<typename ValueType> class set { public: typedefconst ValueType * iterator; ... set(std::initializer_list<ValueType> values); ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; iterator find(const ValueType &) const; std::size_t count(const ValueType &) const; iterator lower_bound(const ValueType &) const; iterator upper_bound(const ValueType &) const; pair<iterator, iterator> equal_range(const ValueType &) const; ... private: ValueType * members; std::size_t cardinality; }; set<int> c { 2, 9, 9, 7, 9, 2, 4, 5, 8 };
  • 54.
    template<typename ValueType> class array { public: typedefconst ValueType * iterator; ... array(std::initializer_list<ValueType> values); ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; ... private: ValueType * elements; std::size_t length; }; array<int> c { 2, 9, 9, 7, 9, 2, 4, 5, 8 };
  • 55.
    In computing, apersistent data structure is a data structure that always preserves the previous version of itself when it is modified. Such data structures are effectively immutable, as their operations do not (visibly) update the structure in-place, but instead always yield a new updated structure. http://en.wikipedia.org/wiki/Persistent_data_structure (A persistent data structure is not a data structure committed to persistent storage, such as a disk; this is a different and unrelated sense of the word "persistent.")
  • 56.
    template<typename ValueType> class vector { public: typedefconst ValueType * iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; vector pop_front() const; vector pop_back() const; ... private: ValueType * anchor; iterator from, until; };
  • 57.
    template<typename ValueType> class vector { public: typedefconst ValueType * iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; vector pop_front() const; vector pop_back() const; ... private: ValueType * anchor; iterator from, until; };
  • 58.
    template<typename ValueType> class vector { public: typedefconst ValueType * iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; vector popped_front() const; vector popped_back() const; ... private: ValueType * anchor; iterator from, until; };
  • 59.
    template<typename ValueType> class vector { public: typedefconst ValueType * iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; vector popped_front() const; vector popped_back() const; ... private: ValueType * anchor; iterator from, until; };
  • 61.
    I still havea deep fondness for the Lisp model. It is simple, elegant, and something with which all developers should have an infatuation at least once in their programming life. Kevlin Henney "A Fair Share (Part I)", CUJ C++ Experts Forum, October 2002
  • 62.
  • 63.
    template<typename ValueType> class list { public: classiterator; ... std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & front() const; list popped_front() const; list pushed_front() const; ... private: struct link { link(const ValueType & value, link * next); ValueType value; link * next; }; link * head; std::size_t length; };
  • 64.
    Hamlet: Yea, fromthe table of my memory I'll wipe away all trivial fond records. William Shakespeare The Tragedy of Hamlet [Act I, Scene 5]
  • 65.
    Garbage collection [...]is optional in C++; that is, a garbage collector is not a compulsory part of an implementation. Bjarne Stroustrup http://stroustrup.com/C++11FAQ.html
  • 66.
  • 67.
    Ophelia: 'Tis inmy memory locked, and you yourself shall keep the key of it. William Shakespeare The Tragedy of Hamlet [Act I, Scene 3]
  • 68.
    A use-counted classis more complicated than a non-use- counted equivalent, and all of this horsing around with use counts takes a significant amount of processing time. Robert Murray C++ Strategies and Tactics
  • 69.
    template<typename ValueType> class vector { public: typedefconst ValueType * iterator; ... bool empty() const; std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & operator[](std::size_t) const; const ValueType & front() const; const ValueType & back() const; const ValueType * data() const; vector popped_front() const; vector popped_back() const; ... private: std::shared_ptr<ValueType> anchor; iterator from, until; }; Uses std::default_delete<ValueType[]>, but cannot be initialised from std::make_shared
  • 70.
    template<typename ValueType> class list { public: classiterator; ... std::size_t size() const; iterator begin() const; iterator end() const; const ValueType & front() const; list popped_front() const; list pushed_front() const; ... private: struct link { link(const ValueType & value, std::shared_ptr<link> next); ValueType value; std::shared_ptr<link> next; }; std::shared_ptr<link> head; std::size_t length; };
  • 71.
    { list<Anything> chain; std::fill_n( std::front_inserter(chain), how_many, something); } On destruction,deletion of links is recursive through each link, causing the stack to blow up for surprisingly small values of how_many.
  • 73.
  • 74.
  • 75.
  • 76.
    All computers wait atthe same speed.
  • 77.
    Some people, whenconfronted with a problem, think, "I know, I'll use threads," and then two they hav erpoblesms. Ned Batchelder https://twitter.com/#!/nedbat/status/194873829825327104
  • 78.
    Shared memory islike a canvas where threads collaborate in painting images, except that they stand on the opposite sides of the canvas and use guns rather than brushes. The only way they can avoid killing each other is if they shout "duck!" before opening fire. Bartosz Milewski "Functional Data Structures and Concurrency in C++" http://bartoszmilewski.com/2013/12/10/functional-data-structures-and-concurrency-in-c/
  • 79.
    Mutable Immutable Unshared Shared Unshared mutable dataneeds no synchronisation Unshared immutable data needs no synchronisation Shared mutable data needs synchronisation Shared immutable data needs no synchronisation
  • 80.
    Mutable Immutable Unshared Shared Unshared mutable dataneeds no synchronisation Unshared immutable data needs no synchronisation Shared mutable data needs synchronisation Shared immutable data needs no synchronisation The Synchronisation Quadrant
  • 82.
    std::string fizzbuzz(int n) { return n% 3 == 0 && n % 5 == 0 ? "FizzBuzz" : n % 3 == 0 ? "Fizz" : n % 5 == 0 ? "Buzz" : std::to_string(n); }
  • 83.
    void fizzbuzzer( channel<int> &receive, channel<std::string> & send) { for(int n; receive >> n;) send << fizzbuzz(n); }
  • 84.
    int main() { channel<int> out; channel<std::string>back; std::thread fizzbuzzing(fizzbuzzer, out, back) for(int n = 1; n <= 100; ++n) { out << n; std::string result; back >> result; std::cout << result << "n"; } ... }
  • 86.
    Sender Receiver A Message1Message 3 Receiver B In response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received. http://en.wikipedia.org/wiki/Actor_model
  • 87.
    Multithreading is justone damn thing after, before, or simultaneous with another. Andrei Alexandrescu
  • 88.
    Actor-based concurrency is justone damn message after another.
  • 89.
    Go with the flow. Queensof the Stone Age