Functional Reactive Programming in C++
Meeting C++ 2016
Ivan Čukić
[email protected]
http://cukic.co
Functional design Reactive programming CODE: meetingcpp
Disclaimer
Make your code readable. Pretend the next person
who looks at your code is a psychopath and they know
where you live.
Philip Wadler
2
Functional design Reactive programming CODE: meetingcpp
Disclaimer
The code snippets are optimized for presentation, it is not
production-ready code.
std namespace is omitted, value arguments used instead of const-refs or
forwarding refs, etc.
3
.
FUNCTIONAL DESIGN
Higher-order functions
Purity and referential transparency
Functional design Reactive programming CODE: meetingcpp
Elements of functional design
Higher-order functions
Purity
Immutable state
...
6
Functional design Reactive programming CODE: meetingcpp
Higher-order functions
We have had higher-order functions since C++98.
No lambdas, no std::function ... needed.
f i n d _ i f ( b e g i n ( cs ) , end ( cs ) , is_error ) ;
auto gt42 = b i n d ( greater<>() , _1 , 42);
/ / or old bind1st , . . .
7
Functional design Reactive programming CODE: meetingcpp
Higher-order functions
We have had higher-order functions for as long as we have had
the call operator.
class functional_object {
public :
r e s u l t operator() ( ... ) const
{
...
}
};
8
Functional design Reactive programming CODE: meetingcpp
Word frequency
1986: Donald Knuth was asked to implement a program for
the "Programming pearls" column in the Communications of
ACM journal.
The task: Read a file of text, determine the n most frequently
used words, and print out a sorted list of those words along
with their frequencies.
9
Functional design Reactive programming CODE: meetingcpp
Word frequency
1986: Donald Knuth was asked to implement a program for
the "Programming pearls" column in the Communications of
ACM journal.
The task: Read a file of text, determine the n most frequently
used words, and print out a sorted list of those words along
with their frequencies.
His solution written in Pascal was 10 pages long.
9
Functional design Reactive programming CODE: meetingcpp
Word frequency
Response by Doug McIlroy was a 6-line shell script that did
the same:
t r −cs A−Za−z ’ \ n ’ |
t r A−Z a−z |
sort |
u n i q −c |
s o r t −rn |
sed ${1} q
10
Functional design Reactive programming CODE: meetingcpp
Functional thinking – data transformation
11
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
I t was a b r i g h t cold day i n A p r i l , \n
and the c l o c k s were s t r i k i n g t h i r t e e n . \n
Winston Smith , h i s c h i n nuzzled
data | transfo r m (
[ ] ( char c ) {
return isalnum ( c ) ? c : ’\n ’ ;
})
I t \nwas\na\n b r i g h t \ncold\nday\n i n \n A p r i l \n\n
and\nthe\n c l o c k s \nwere\n s t r i k i n g \n t h i r t e e n \n\n
Winston\nSmith\n\n h i s \n c h i n \nnuzzled
12
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
I t \nwas\na\n b r i g h t \ncold\nday\n i n \n A p r i l \n\n
and\nthe\n c l o c k s \nwere\n s t r i k i n g \n t h i r t e e n \n\n
Winston\nSmith\n\n h i s \n c h i n \nnuzzled
... | transfo r m ( tolower )
i t \nwas\na\n b r i g h t \ncold\nday\n i n \n a p r i l \n\n
and\nthe\n c l o c k s \nwere\n s t r i k i n g \n t h i r t e e n \n\n
winston\n s m i t h \n\n h i s \n c h i n \nnuzzled
13
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
i t \nwas\na\n b r i g h t \ncold\nday\n i n \n a p r i l \n\n
and\nthe\n c l o c k s \nwere\n s t r i k i n g \n t h i r t e e n \n\n
winston\n s m i t h \n\n h i s \n c h i n \nnuzzled
... | split ( ’\n ’)
it was a bright cold day in april
and the clocks were striking thirteen
winston smith his chin nuzzled
14
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
it was a bright cold day in april
and the clocks were striking thirteen
winston smith his chin nuzzled
... | sort
| group_by ( equal_to < > ( ) )
{ a a a a a ... },
{ as as as as as . . . } ,
{ at at at at at . . . }
15
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
{ a a a a a ... },
{ and and and and and . . . }
{ as as as as as ... },
... | transfo r m ( [ ] ( const auto &grp ) {
r e t u r n make_pair (
count ( grp ) , * grp . c b e g i n ( ) ) ;
})
( 181, a ),
( 163, and ) ,
( 39 , as ) ,
16
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
( 181, a ),
( 163, and ) ,
( 39 , as ) ,
... | sort
| reverse
| take ( 2 )
( 439, the ),
( 256, of ),
17
Functional design Reactive programming CODE: meetingcpp
Word frequency in C++
data | transform ( [ ] ( c h a r c ) {
return isalnum ( c ) ? c : ’ \ n ’ ;
})
| transform ( tolower )
| split ( ’\n ’)
| sort
| group_by ( equal_to < > ( ) )
| transform ( [ ] ( const auto &grp ) {
r e t u r n make_pair (
count ( grp ) , * grp . c b e g i n ( ) ) ;
})
| sort
| reverse
| take ( n )
* Inspired by the solution written by N. Milev in Haskell
18
Functional design Reactive programming CODE: meetingcpp
Purity and referential transparency
i n t answer ( )
{
std::cout « "Calculating the result\n" ;
r e t u r n 42;
}
...
auto r e s u l t = answer() ;
...
$ ./a.out
Calculating the result
19
Functional design Reactive programming CODE: meetingcpp
Purity and referential transparency
i n t answer ( )
{
std::cout « "Calculating the result\n" ;
r e t u r n 42;
}
...
auto r e s u l t = 42 ;
...
$ ./a.out
20
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Handling the program state
v o i d o n _ c l i c k e d ( const c l i c k _ e v e n t &ev ent )
{
employees_view−> v i s i b l e = t r u e ;
employees_view−>load_team ( ) ;
}
21
Functional design Reactive programming CODE: meetingcpp
Object-oriented design
Don’t ask for the information you need to do the work;
ask the object that has the information to do the work
for you.
Allen Holub
22
Functional design Reactive programming CODE: meetingcpp
Object-oriented design
Step one in the transformation of a successful
procedural developer into a successful object
developer is a lobotomy.
David West, Object Thinking
23
Functional design Reactive programming CODE: meetingcpp
Object-oriented design
[...] Besides that, object thinking will lead to object
immutability [...]
Yegor Bugayenko
24
Functional design Reactive programming CODE: meetingcpp
Object-oriented design
25
Functional design Reactive programming CODE: meetingcpp
State in pure functional programs
26
Functional design Reactive programming CODE: meetingcpp
State in pure functional programs
27
Functional design Reactive programming CODE: meetingcpp
Isn’t creating new worlds expensive?
Option 1: We don’t really want copies:
c l a s s world {
world w i t h _ p o p u l a t i o n
( i n t new_population ) &&
{
world r e s u l t ( std : : move( * t h i s ) ) ;
...
return result ;
}
};
Option 2: Use immutable data structures (see Okasaki)
28
Functional design Reactive programming CODE: meetingcpp
Isn’t creating new worlds expensive?
c l a s s world {
world w i t h _ p o p u l a t i o n ( i n t ) && ;
};
auto brave_new_world =
world.with_population(6) ; // error!
auto new_world =
move(world).with_population(420) ;
29
Functional design Reactive programming CODE: meetingcpp
Isn’t creating new worlds expensive?
c l a s s world {
world w i t h _ p o p u l a t i o n ( i n t ) && ;
};
The compiler enforces us not to write inneficient code.
If we provide anything else, we explicitly tell through our API
that we support having parallel worlds.
30
Functional design Reactive programming CODE: meetingcpp
Benefits of having parallel worlds
Time travel (and reverse debugging, like gdb does)
Testing different possible scenarios at the same time
Maybe even having them interact with each other
31
REACTIVE PROGRAMMING
What is reactive?
Functional design Reactive programming CODE: meetingcpp
What is reactive?
We believe that a coherent approach to systems
architecture is needed, and we believe that all
necessary aspects are already recognised individually:
we want systems that are Responsive, Resilient, Elastic
and Message Driven. We call these Reactive Systems.
Systems built as Reactive Systems are more flexible,
loosely-coupled and scalable. This makes them easier
to develop and amenable to change. They are
significantly more tolerant of failure and when failure
does occur they meet it with elegance rather than
disaster. Reactive Systems are highly responsive, giving
users effective interactive feedback.
Reactive Manifesto 2.0
33
.
Functional design Reactive programming CODE: meetingcpp
Reactive systems
One view of being reactive:
responds quickly
resilient to failure
responsive under workload
based on message-passing
35
Functional design Reactive programming CODE: meetingcpp
What is reactive?
Showing a response to a stimulus
Oxford Dictionary
36
Functional design Reactive programming CODE: meetingcpp
Ways to be reactive?
C: event call-backs
Java: event listeners
C++/Qt: signals and slots
Threads for all!
37
Functional design Reactive programming CODE: meetingcpp
Ways to be reactive?
C: event call-backs
Java: event listeners
C++/Qt: signals and slots
Threads for all!
even IO streams?
37
Functional design Reactive programming CODE: meetingcpp
Lets try this again...
Design components:
to react to requests, not to respond
to request, not to need the response
38
Functional design Reactive programming CODE: meetingcpp
Lets try this again...
39
Functional design Reactive programming CODE: meetingcpp
Lets try this again...
40
Functional design Reactive programming CODE: meetingcpp
Lets try this again...
41
Functional design Reactive programming CODE: meetingcpp
Lets try this again...
42
Functional design Reactive programming CODE: meetingcpp
Modify and pass on
No shared mutable state
Separate isolated components
Communication only through message passing
No upstream response messages
43
Functional design Reactive programming CODE: meetingcpp
Modify and pass on
44
Functional design Reactive programming CODE: meetingcpp
Modify and pass on
45
Functional design Reactive programming CODE: meetingcpp
What is a source?
Web server client connection requests
User interface events
Database results
I/O
Any data collection
...
46
Functional design Reactive programming CODE: meetingcpp
Streams are ranges
Streams can only be transformed with algorithms that accept
input ranges, since we don’t have all the items. We don’t even
know when (if) they will end.
transform, filter, take, drop, etc.
47
Functional design Reactive programming CODE: meetingcpp
Small demo
48
Functional design Reactive programming CODE: meetingcpp
Small demo
We have a stream of mouse cordinates: mouse_stream
And a set of receivers like mouse_cursor,
top_ruler_marker, etc.
Basic direct connection:
mouse_stream | mouse_cursor −>move_to ;
49
Functional design Reactive programming CODE: meetingcpp
Transforming the input
We want to transform the mouse coordinate, to project it on
the x axis:
mouse_stream |
transform ( p r o j e c t _ o n _ x ) |
top_ruler_marker −>move_to ;
But the mouse cursor marker is no longer moving.
50
Functional design Reactive programming CODE: meetingcpp
Forking the stream
mouse_stream |
/ / Pass the events to the mouse cursor ,
/ / and pass them to the next
/ / t r a n s f o r m a t i o n i n the c h a i n
tee ( mouse_cursor −>move_to ) |
/ / p r o j e c t i n g the mouse c o o r d i n a t e s on
/ / the x a x i s
transform ( p r o j e c t _ o n _ x ) |
top_ruler_marker −>move_to ;
51
Functional design Reactive programming CODE: meetingcpp
Properly forking the stream
mouse_stream |
tee ( mouse_cursor −>move_to ) |
/ / I f we want to do something more
/ / complex with both streams a f t e r
/ / f o r k i n g , tee i s not r e a d a b l e
fork (
transfo r m ( p r o j e c t _ o n _ x ) |
top_ruler_marker −>move_to ,
transfo r m ( p r o j e c t _ o n _ y ) |
l e f t _ r u l e r _ m a r k e r −>move_to
);
52
Functional design Reactive programming CODE: meetingcpp
Transformations with state
class gravity_object {
public :
...
p o i n t o p e r a t o r ( ) ( const p o i n t &new_point )
{
m_point . x = m_point . x * .99
+ new_point . x * . 0 1 ;
m_point . y = ... ;
r e t u r n m_point ;
}
private :
p o i n t m_point ;
...
}; 53
Functional design Reactive programming CODE: meetingcpp
Transformations with state
54
Functional design Reactive programming CODE: meetingcpp
Transformations with state
mouse_stream |
tee ( mouse_cursor −>move_to ) |
fork (
map ( p r o j e c t _ o n _ x ) |
top_ruler_marker −>move_to ,
map ( p r o j e c t _ o n _ y ) |
l e f t _ r u l e r _ m a r k e r −>move_to ,
map(gravity_object()) |
g r a v i t y _ m a r k e r −>move_to
);
55
Functional design Reactive programming CODE: meetingcpp
Stream filtering
We want only points where point.y % 100 == 0
mouse_stream |
tee ( mouse_cursor −>move_to ) |
fork (
...
filter(point_filter) |
f i l t e r _ m a r k e r −>move_to
);
56
Functional design Reactive programming CODE: meetingcpp
Generating new events
class continuous_points {
public :
vector < p o i n t >
o p e r a t o r ( ) ( const p o i n t &new_point ) {
/ / gener a t e a l l the p o i n t s between the
/ / p r e v i o u s one and the new one
vector < p o i n t > r e s u l t = ...
m_previous_point = new_point ;
return result ;
}
private :
p o i n t m_previous_point ;
};
57
Functional design Reactive programming CODE: meetingcpp
Generating new events
mouse_stream |
tee ( mouse_cursor −>move_to ) |
fork (
...
/ / or tr a n sf o r m ( . . . ) | f l a t t e n
flatmap(continuous_points()) |
filter ( point_filter ) |
f i l t e r _ m a r k e r −>move_to
);
58
Functional design Reactive programming CODE: meetingcpp
What are the benefits?
Separate components
Reusable, composable transformations
Asynchronousness built into the software design
But that is not all...
59
Functional design Reactive programming CODE: meetingcpp
Microservices?
60
Functional design Reactive programming CODE: meetingcpp
Microservices?
61
Functional design Reactive programming CODE: meetingcpp
Microservices?
62
Functional design Reactive programming CODE: meetingcpp
Microservices?
KDE Frameworks 5
63
Functional design Reactive programming CODE: meetingcpp
Libraries
For the lower level parts:
SObjectizer
C++ Actor Framework
ZeroMQ
For the higher level:
RxCpp
64
Functional design Reactive programming CODE: meetingcpp
Answers? Questions! Questions? Answers!
Kudos:
Friends at KDE and blueSystems
Dr Saša Malkov, Dr Zoltan Porkolab
MEAP – Manning Early Access Program
Functional Programming in C++
cukic.co/to/fp-in-cpp
Discount code:
meetingcpp
65