12 Event Driven Programming
12 Event Driven Programming
Event-driven programming
Thalesians Ltd
Level39, One Canada Square, Canary Wharf, London E14 5AB
2022.06.23
Event-driven programming
Event-driven programming
import logging
import sys
import websocket
try:
import thread
except ImportError :
import _thread as thread
Game loop
I Many other examples of event-driven programming occur in games.
I There is an interesting tutorial by Mark Brown, peer reviewed by Andrew Ray and
Sebastian Seitz, Quick Tip: How to Make a Game Loop in JavaScript (2016.08.03).
I In this context the main loop is called the game loop and usually takes the following
form:
function draw () {
// Draw the state of the world
}
update ( progress )
draw ()
lastRender = timestamp
window . requestAnimationFrame (loop)
}
var lastRender = 0
window . requestAnimationFrame (loop)
Event-driven programming
Analysis
A specific example
I Our first animation will be simple: a red square that moves to the right until it reaches
the edge of the canvas and loops back around to the start.
I We’ll need to store the square’s position and increment the x position in our update
function. When we hit a boundary we can subtract the canvas width to loop back
around.
var state = {
x: width / 2,
y: height / 2
}
I The draw function simply renders the current state of the world. On each frame we’ll
clear the canvas and then draw a 10px red square with its centre at the position stored
in our state object:
function draw () {
ctx. clearRect (0, 0, width , height )
I Next we’ll get keyboard input to control the position of our object, state.pressedKeys
will keep track of which keys are pressed.
var state = {
x: (width / 2),
y: ( height / 2),
pressedKeys : {
left: false ,
right: false ,
up: false ,
down: false
}
}
I Let’s listen to all keydown and keyup events and update state.pressedKeys
accordingly.
I The keys we’ll be using are D for right, A for left, W for up, and S for down.
Event-driven programming
var keyMap = {
68: ’right ’,
65: ’left ’,
87: ’up ’,
83: ’down ’
}
function keydown (event) {
var key = keyMap [event. keyCode ]
state . pressedKeys [key] = true
}
function keyup(event) {
var key = keyMap [event. keyCode ]
state . pressedKeys [key] = false
}
According to [BJ16]:
I Unpredictable order—In a complex network of listeners, the order in which events are
received can depend on the order you registered the listeners in, which is not helpful.
I Missed first event—It can be difficult to guarantee that you have registered your
listeners before you send the first event.
I Messy state—Callbacks push your code into a traditional state machine style.
I Threading issues—Attempting to make listeners thread-safe can lead to deadlocks,
and it can be difficult to guarantee that no more callbacks will be received after
deregistering a listener.
I Leaking callbacks—If you forget to deregister your listener, your program will leak
memory. Listeners reverse the natural data dependency, but do not reverse the
keep-alive dependency, as we would like them to.
I Accidental recursion—The order in which you update local state and notify listeners
can be critical, and it’s easy to make mistakes.
Event-driven programming
Functional reactive programming (FRP) [EH97] can be viewed from different angles [BJ16]:
I It’s a replacement for the widely used observer pattern.
I It’s a composable, modular way to code event-driven logic.
I It’s a different way of thinking: the program is expressed as a reaction to its inputs, or
as a flow of data.
I It brings order to the management of program state.
I It’s normally implemented as a lightweight software library in a standard programming
language.
I It can be seen as a complete embedded language for stateful logic. It can be viewed
as a minimal complete domain-specific language (DSL) for stateful logic.
Event-driven programming
A stricter definition
Conal Elliot stated in a StackOverflow post, Specification for a Functional Reactive
Programming Language1 :
I’m glad you’re starting by asking about a specification rather than implementation
first. There are a lot of ideas floating around about what FRP is. For me it’s always
been two things: (a) denotative and (b) temporally continuous. Many folks drop
both of these properties and identify FRP with various implementation notions, all
of which are beside the point in my perspective. To reduce confusion, I would like
to see the term “functional reactive programming” replaced by the more accurate
& descriptive “denotative, continuous-time programming” (DCTP), as suggested
by Jake McArthur in a conversation last year.
By “denotative”, I mean founded on a precise, simple, implementation-
independent, compositional semantics that exactly specifies the meaning of each
type and building block. The compositional nature of the semantics then deter-
mines the meaning of all type-correct combinations of the building blocks. For me,
denotative is the heart & essence of functional programming, and is what enables
precise & tractable reasoning and thus a foundation for correctness, derivation,
and optimization. Peter Landin recommended “denotative” as a substantive re-
placement to the fuzzier term “functional” and a way to distinguish deeply/gen-
uinely functional programming from merely functional-looking notations.
1 https://stackoverflow.com/questions/5875929/
specification-for-a-functional-reactive-programming-language
Event-driven programming
More definitions
2 A definition from [Lel19]: Reactive programming is a programming paradigm oriented toward data flows and the
propagation of change: programming with asynchronous data streams.
Event-driven programming
Pure functions
Function composition
Shared state
I Shared state is any variable, object, or memory space that exists in a shared scope,
or as the property of an object being passed between scopes.
I A shared scope can include global scope or closure scopes.
I In object oriented programming, objects are shared between scopes by adding
properties to other objects.
I The problem with shared state is that in order to understand the effects of a function,
you have to know the entire history of every shared variable that the function uses or
affects.
Event-driven programming
Race condition
Timing dependency
// With shared state , the order in which function calls are made
// changes the result of the function calls.
const x = {
val: 2
};
const x1 = () => x.val += 1;
const x2 = () => x.val *= 2;
x1 ()
x2 ();
console .log(x.val); // 6
const y = {
val: 2
};
const y1 = () => y.val += 1;
const y2 = () => y.val *= 2;
y2 ();
y1 ();
console .log(y.val); // 5
Event-driven programming
I When you avoid shared state, the timing and order of function calls don’t change the
result of calling the function.
I With pure functions, given the same input, you’ll always get the same output.
I This makes function calls completely independent of other function calls, which can
radically simplify changes and refactoring.
I A change in one function, or the timing of a function call won’t ripple out and break
other parts of the program.
Event-driven programming
// With shared state , the order in which function calls are made
// changes the result of the function calls.
const x = {
val: 2
};
const x1 = x => Object . assign ({}, x, {val: x.val + 1});
const x2 = x => Object . assign ({}, x, {val: x.val * 2};
console .log(x1(x2(x)).val); // 5
const y = {
val: 2
};
Order matters
I Of course, if you change the order of the composition, the output will change.
I Order of operations still matters.
I f(g(x)) is not always equal to g(f(x)), but what doesn’t matter anymore is what
happens to variables outside the function—and that’s a big deal.
I With impure functions, it’s possible to fully understand what a function does unless you
know the entire history of every variable that the function uses or affects.
I Remove function call timing dependency, and you eliminate an entire class of potential
bugs.
Event-driven programming
Immutability
I An immutable object is an object that cannot be modified after it has been created.
I Conversely, a mutable object is an object that can be modified after it has been
created.
I Immutability is a central concept of functional programming because without it the data
flow in your program is lossy. State history is abandoned and strange bugs can creep
into your software.
I Don’t confuse constness with immutability. Immutable objects can’t be changed at all.
Event-driven programming
Side effects
I A side effect is any application state change that is observable outside the called
function other than its return value.
I Side effects include:
I Modifying any external variable or object property (e.g. a global variable or a variable in the
parent function scope chain);
I Logging to the console;
I Writing to the screen;
I Writing to a file;
I Writing to the network;
I Triggering any external process;
I Calling any other functions with side effects.
I Side effects are mostly avoided in functional programming, which makes the effects of
a program much easier to understand and much easier to test.
I Haskell and other functional languages frequently isolate and encapsulate side effects
from pure functions using monads.
I In functional programming side-effect actions need to be isolated from the rest of your
software.
I If you keep side effects separate from the rest of your program logic, your software will
be easier to extend, refactor, debug, test, and maintain.
Event-driven programming
Stream
Operations on streams
int main ()
{
std :: vector <int > ages{ 9, 20, 13, 4, 5, 6, 10, 28, 19, 15, 60, 23, 47, 12, 19, 99
,→ };
return 0;
}
Event-driven programming
Fluent interface
FRP libraries
I ReactiveX ecosystem:
I RxJS
I RxJava
I Rx.NET
I RxCpp
I Bacon.js
I Kefir.js
I Cycle.js
I Reactive Streams and java.util.concurrent.Flow
I Sodium (C++, C#, F#, Java, Kotlin, Scala, Typescript/Javascript, Embedded-C, Rust)
I Reactive Banana (Haskell)
Event-driven programming
I Conal Elliott. The essence and origins of FRP or How you could have invented
Functional Reactive Programming. LambdaJam, 2015.10.18,
https://www.youtube.com/watch?v=j3Q32brCUAI
I Andre Staltz. Cycle.js and functional reactive user interfaces. ReactiveConf,
2015.11.28, https://www.youtube.com/watch?v=uNZnftSksYg
I Colby CheeZe. Functional Programming for Beginners. 2016.03.09,
https://www.youtube.com/watch?v=vLmaZxegahk
I Adam M. Intrator. FRP, Observables, and React. Fullstack Academy, 2017.01.29,
https://www.youtube.com/watch?v=IfFfvfCl4A8
I Stephen Blackheath. FRP in Java using Sodium. FP Auckland Meetup, 2017.10.14,
https://www.youtube.com/watch?v=xHaoPVSgtiM
Event-driven programming