### Conversational Concurrency

Tony Garnock-Jones

PhD Dissertation Defense
December 8th, 2017

more than one thing to do

### Concurrency

vs.

### Parallelism

progress on more than one at once

Concurrency - many tasks Parallelism - speed

more than one thing to do

### Concurrency

vs.

### Parallelism

progress on more than one at once

Concurrency - many tasks Parallelism - speed

Simon Marlow:

> Concurrency is [...] for structuring your program as a collection of interacting agents. Parallelism, on the other hand, is just about making your programs go faster.

(in a 2008 post to the Haskell-Cafe mailing list)

more than one interacting thing

### Concurrency

vs.

### Parallelism

progress on more than one at once

This work: - focus on *concurrency* - takes a particular perspective

more than one interacting thing

### Concurrency

This work: - focus on *concurrency* - takes a particular perspective

more than one interacting thing

### Concurrency

is about

- groups of components
- working together
- to achieve some shared goal.

This work: - focus on *concurrency* - takes a particular perspective

more than one interacting thing

### Concurrency

is about

### cooperation.

This work: - focus on *concurrency* - takes a particular perspective

#### Coordinate

- arrange to take turns performing helpful tasks
- via communication

#### Communicate

- build shared understanding
- of relevant knowledge
- required to achieve the shared goal
  = manage conversational state

But how do they work together?

What does it mean to cooperate?

Act of communication - contribute to shared understanding

The purpose of communication - to share state.

To replicate information from peer to peer.

Comm. that does not affect receiver's worldview literally has no effect.

#### Coordinate

- arrange to take turns performing helpful tasks
- via communication

#### Communicate

- build shared understanding
- of relevant knowledge
- required to achieve the shared goal
  = manage conversational state

But how do they work together?

What does it mean to cooperate?

Act of communication - contribute to shared understanding

The purpose of communication - to share state.

To replicate information from peer to peer.

Comm. that does not affect receiver's worldview literally has no effect.

#### Coordinate

- arrange to take turns performing helpful tasks
- via communication

#### Communicate

- build shared understanding
- of relevant knowledge
- required to achieve the shared goal
  = manage conversational state

But how do they work together?

What does it mean to cooperate?

Act of communication - contribute to shared understanding

The purpose of communication - to share state.

To replicate information from peer to peer.

Comm. that does not affect receiver's worldview literally has no effect.

#### Coordinate

- arrange to take turns performing helpful tasks
- via communication

#### Communicate

- build shared understanding
- of relevant knowledge
- required to achieve the shared goal
  = manage conversational state

But how do they work together?

What does it mean to cooperate?

Act of communication - contribute to shared understanding

The purpose of communication - to share state.

To replicate information from peer to peer.

Comm. that does not affect receiver's worldview literally has no effect.

#### Coordinate

- arrange to take turns performing helpful tasks
- via communication

#### Communicate

- build shared understanding
- of relevant knowledge
- required to achieve the shared goal
  = manage conversational state

But how do they work together?

What does it mean to cooperate?

Act of communication - contribute to shared understanding

The purpose of communication - to share state.

To replicate information from peer to peer.

Comm. that does not affect receiver's worldview literally has no effect.

(dissertation fig. 2)

- each task shared
- entails acts of communication
- in the frame of an overall conversation

- each act contributes to overall conv. state of shared task

- when the shared task has subtasks,
- there are often sub-conversations
- each framed within the overall context
- and logically dependent on the overall conversation

Concurrency is about | cooperation
through | communication
of | conversational state

So, all told, we could say that...

### Unpredictability

- ✓ pure, total functions
- ✗ effects
- ✗ coroutines
- ✗ threads & shared memory
- ✗ network conditions

But there's a second important aspect to concurrency ...

...

- Partly about programmer control.
- The unknown is unpredictable.
- A function cannot usually "predict" its arguments.

Concurrency is about | cooperation
through | communication
of | conversational state
in an | unpredictable setting

... so we could expect our languages:

- to make cooperation easy
- to make communication easy and useful
- to help synchronize perspectives on a conversation's state
- to minimize or mitigate unpredictability, incl partial failure

Syndicate provides a new, effective, realizable linguistic mechanism for sharing state in a concurrent setting.
To this end, I have developed new programming language design, Syndicate, which rests on a new model of concurrent computation, the dataspace model. This brings me to my thesis statement:

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

not distributed - Deutsch's fallacies - control latency, scheduling

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

not distributed - Deutsch's fallacies - control latency, scheduling

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

The dataspace model is, at heart

a mechanism for sharing state among neighboring concurrent components.

Focus on mechanisms for sharing state because communication and coordination follow as special cases.

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

DS model explains communication and coordination among components

Does not offer assistance in structuring internals of components.

New language constructs reifying conversations within an actor,

bridge between the language’s model and the dataspace style of interaction

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

I demonstrate realizability with two prototype Syndicate implementations (Racket, JS)

And a custom data structure based on the old idea of a trie to allow efficient implementation

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

Dissertation: many examples solving various programming problems

Also, have developed a handful of larger applications

Based on these, argue:

- Syndicate eliminates various patterns
- thus simplifying programming tasks

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

Finally, it's a new idea.

Dissertation: design landscape

Talk: brief mention of the actor model and the tuplespace model

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

Finally, it's a new idea.

Dissertation: design landscape

Talk: brief mention of the actor model and the tuplespace model

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

At the time of my proposal, ...

dataspace model + a few key properties

Racket prototype of dataspace model only

assertion-trie data structure

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

Since then,

- conversational language design features
- two complete prototype implementations
- qualitative, pattern-based evaluation
- analysis in terms of a broader concurrency design landscape

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

Since then,

- conversational language design features
- two complete prototype implementations
- qualitative, pattern-based evaluation
- analysis in terms of a broader concurrency design landscape

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

### Dataspace model

Syndicate: based on a collection of actors running in a dataspace

- borrowed "actor" from actor model
- actor analog of "dataspace": msg fabric
- "dataspace": chosen to recall "tuplespace" from TS model
- DS model: kind of a hybrid of actor + tuplespace models

1. each DS is an actor: recursive (dis)aggregation...

### Dataspace model

2. ... main diff: instead of messages, actors in a dataspace communicate by placing assertions in their shared dataspace.

An assertion is just a record, a piece of data: essentially, an S-expression.

Similar to the TS model: where a shared "blackboard"-style store holds "tuples".

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

`(out (balance 'account1 123.0))`

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

`(out (balance 'account1 123.0))`

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

`(rd (balance 'account1 _))`

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

`(in 'lock)`

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

`(in 'lock)`

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Tuplespace model

Actions: `eval`, `out`, `rd`, `in`

``

Tuples have independent existence

Tuples move from place to place

"lost tuple" problem

Reads are blocking operations

Extensions allow event-handlers for reacting to changes in the tuplespace

### Dataspace model

By contrast, in DS model, job of DS is to keep actors up-to-date as the contents of the dataspace changes.

In effect: a DS replicates assertions among the actors it contains.

### Dataspace model

Each assertion recorded with provenance: track who asserted what

### Dataspace model

Assertions are like Prolog assertions - ground facts in a logic-programming system

Multiple assertions of the same value: equivalent to just one

DS replicates a set view of a bag of assertions

Crash → owned assertions removed

Compare TS "lost tuple" problem

### Dataspace model

Assertions are like Prolog assertions - ground facts in a logic-programming system

Multiple assertions of the same value: equivalent to just one

DS replicates a set view of a bag of assertions

Crash → owned assertions removed

Compare TS "lost tuple" problem

### Dataspace model

Assertions are like Prolog assertions - ground facts in a logic-programming system

Multiple assertions of the same value: equivalent to just one

DS replicates a set view of a bag of assertions

Crash → owned assertions removed

Compare TS "lost tuple" problem

### Dataspace model

Assertions are like Prolog assertions - ground facts in a logic-programming system

Multiple assertions of the same value: equivalent to just one

DS replicates a set view of a bag of assertions

Crash → owned assertions removed

Compare TS "lost tuple" problem

`(observe P)`

Assertion of interest in `P`

`(color 'boat 'blue)`

"The color of the boat is blue"

`(observe (color 'boat _))`

"Interest exists in the color of the boat being anything at all"

Tuplespace model: each subprogram uses patterns over tuples to select items of interest.

Likewise, DS: each actor uses patterns to select assertions of interest.

Big difference: it asserts interest in other assertions

DS uses `observe` assertions to...

Each actor gets events describing every relevant change and only relevant changes to the dataspace.

Messages too: "short" assertions

`(observe P)`

Assertion of interest in `P`

`(color 'boat 'blue)`

"The color of the boat is blue"

`(observe (color 'boat _))`

"Interest exists in the color of the boat being anything at all"

Tuplespace model: each subprogram uses patterns over tuples to select items of interest.

Likewise, DS: each actor uses patterns to select assertions of interest.

Big difference: it asserts interest in other assertions

DS uses `observe` assertions to...

Each actor gets events describing every relevant change and only relevant changes to the dataspace.

Messages too: "short" assertions

`(observe P)`

Assertion of interest in `P`

`(color 'boat 'blue)`

"The color of the boat is blue"

`(observe (color 'boat _))`

"Interest exists in the color of the boat being anything at all"

Tuplespace model: each subprogram uses patterns over tuples to select items of interest.

Likewise, DS: each actor uses patterns to select assertions of interest.

Big difference: it asserts interest in other assertions

DS uses `observe` assertions to...

Each actor gets events describing every relevant change and only relevant changes to the dataspace.

Messages too: "short" assertions

### Figure 11, chapter 4

Dissertation: program syntax, evaluation syntax, reduction rules

### Figure 13, chapter 4

### Figure 14, chapter 4

Rather than go into extreme detail, I will show enough to get the intuition and follow the examples.

Actor | Event transducer
Actions | Spawn new actor Replace assertions Message
Events | Dataspace has changed Message

Key things: Actors are roughly functions from an event to actions

plus a private state value they can access and update

Actions are just like the actor model, except can update its own assertion set

Events likewise like actor model, except events describe relevant changes to the aggregate assertion set of the dataspace

Reduction rules: deliver events; gather actions; interpret actions; step contained actors

The syntax can be drawn graphically. Often I will elide the details

Every actor connects to its DS via two queues

Every DS has a queue of pending actions to interpret

It also tracks local names for actors

Names not accessible to programmer!

Finally, DS recursive: actor in a wider DS

`(struct dns-entry (name address))`

`(dns-entry "localhost" "127.0.0.1")`

"The address of `localhost` is `127.0.0.1`"

`(observe (dns-entry "localhost" _))`

"Interest exists in the address of `localhost`"

`(observe (observe (dns-entry _ _)))`

"Interest exists in interest in `dns-entry` records"

Concrete example: local DNS API -- for a library

`(struct dns-entry (name address))`

`(dns-entry "localhost" "127.0.0.1")`

"The address of `localhost` is `127.0.0.1`"

`(observe (dns-entry "localhost" _))`

"Interest exists in the address of `localhost`"

`(observe (observe (dns-entry _ _)))`

"Interest exists in interest in `dns-entry` records"

Concrete example: local DNS API -- for a library

`(struct dns-entry (name address))`

`(dns-entry "localhost" "127.0.0.1")`

"The address of `localhost` is `127.0.0.1`"

`(observe (dns-entry "localhost" _))`

"Interest exists in the address of `localhost`"

`(observe (observe (dns-entry _ _)))`

"Interest exists in interest in `dns-entry` records"

Concrete example: local DNS API -- for a library

`(struct dns-entry (name address))`

`(dns-entry "localhost" "127.0.0.1")`

"The address of `localhost` is `127.0.0.1`"

`(observe (dns-entry "localhost" _))`

"Interest exists in the address of `localhost`"

`(observe (observe (dns-entry _ _)))`

"Interest exists in interest in `dns-entry` records"

Concrete example: local DNS API -- for a library

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions

Server, Cache: MULTIPLE CONCURRENT ENTRIES

Reads a nested structure left-to-right as a sequence of tokens

Takes care to share structure

Reads a nested structure left-to-right as a sequence of tokens

Takes care to share structure

- Supports S-expression-like data and wildcards well
- Closed under ∪, ∩, −
- Reasonably efficient ∪, ∩, −
- Reasonably compact
- Gives efficient routing of assertions and messages

Reads a nested structure left-to-right as a sequence of tokens

Takes care to share structure

### Properties

- ✓ No errors and stuck-free
- ✓ Deterministic
- ✓ Order-preserving
- ✓ Conversational "soundness", "completeness"

- actions correctly interpreted
- an event for every relevant change
- every event is
  - truthful,
  - relevant, and
  - complete.

The dataspace is network-like: you don't want your network to crash or "signal an exception"

Determinism: mostly to show a whole DS can be viewed as an event-transducing function

Can relax determinism with simple changes to the reduction rules

Order-preserving: programmer relies on this

NEW: conversational soundness/completeness

- ✓ No errors and stuck-free
- ✓ Deterministic
- ✓ Order-preserving
- ✓ Conversational "soundness", "completeness"

- actions correctly interpreted
- an event for every relevant change
- every event is
  - truthful,
  - relevant, and
  - complete.

The dataspace is network-like: you don't want your network to crash or "signal an exception"

Determinism: mostly to show a whole DS can be viewed as an event-transducing function

Can relax determinism with simple changes to the reduction rules

Order-preserving: programmer relies on this

NEW: conversational soundness/completeness

- ✓ No errors and stuck-free
- ✓ Deterministic
- ✓ Order-preserving
- ✓ Conversational "soundness", "completeness"

- actions correctly interpreted
- an event for every relevant change
- every event is
  - truthful,
  - relevant, and
  - complete.

The dataspace is network-like: you don't want your network to crash or "signal an exception"

Determinism: mostly to show a whole DS can be viewed as an event-transducing function

Can relax determinism with simple changes to the reduction rules

Order-preserving: programmer relies on this

NEW: conversational soundness/completeness

NEW: event trace

Programming model, mental model - line up with reduction semantics

So does the implementation

Capture log entries = reduction steps = useful information for programmer

Quite a direct rendering of a trace, generated by the implementation

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

DS model lets us communicate changes in conversational state

Awesome!

However, most actors engage in multiple conversations simultaneously.

Consider the DNS cache actor.

When there's something to cache, it communicates with both the "server" and "timer" actors for that item.

And there will be multiple items active at once.

Keeping track of which assertions relate to which of an actor's tasks and responsibilities is difficult, error prone, ripe for automation.

We need support in the languages we use to write leaf actors to help us interpret the events we receive and produce appropriate actions corresponding to the actor's changes in internal state.

### Facet

- Assertions
- Local fields
- Data flow → control flow
- Control flow → data flow
- Local data → shared data
- Shared data → local data
- Subfacets

In response to this need, I've introduced a new concept called a facet.

Scopes state/behavior for partic. conv. within an actor

Roughly: everything an actor needs to know and do within a partic. conv. frame

- public aspect
- private aspect
- ...

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

    (react (field [field-name expr] ...)
           endpoint-expr ...)

    endpoint-expr
      = (assert expr)
      | (on (asserted pattern) expr ...)
      | (on (retracted pattern) expr ...)
      | (on (message pattern) expr ...)
      | (on-start expr ...)
      | (on-stop expr ...)

    (stop-when E expr ...)
      = (on E (stop-facet (current-facet-id) expr ...))

    (during pattern endpoint-expr ...)
      = (on (asserted pattern)
            (react (stop-when (retracted pattern′))
                   endpoint-expr ...))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (on (asserted (observe (dns-entry $name _)))
               (react (stop-when (retracted (observe (dns-entry ···))))
                 (assert (dns-entry "localhost" ···)))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (on (asserted (observe (dns-entry $name _)))
               (react (stop-when (retracted (observe (dns-entry ···))))
                 (assert (dns-entry "localhost" ···)))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

Client | Asserts `(observe (dns-entry "localhost" _))` When notified of a `(dns-entry "localhost" $addr)`, prints `addr` and quits
    (spawn (stop-when (asserted (dns-entry "localhost" $addr))
             (printf "localhost is ~a\n" addr)))
Server | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, looks up the `addr` for `name` and asserts `(dns-entry name addr)`
    (spawn (during (observe (dns-entry $name _))
             (define addr (engage-in-internet-dns-protocol-for name))
             (assert (dns-entry name addr))))
Cache | Asserts `(observe (observe (dns-entry _ _)))` In response to `(observe (dns-entry $name _))`, asserts the same, and also `(observe (laterThan ···))` In response to `(laterThan ···)`, removes the corresponding assertions
    (spawn (on (asserted (observe (dns-entry $name _)))
               (define deadline (+ (current-inexact-milliseconds) 2000))
               (react (stop-when (asserted (later-than deadline)))
                      (assert (observe (dns-entry name _))))))

### Figures 16 & 17, chapter 5

The dissertation includes a stripped-back description of the new language features in a very small host language called Syndicate/λ

The syntax and reduction rules that explain the features are in chapter 5 of the dissertation

### Figures 19 & 20, chapter 5

### Figure 23, chapter 5

The same chapter lays out a "well-formedness" judgement, which will form the heart of a soundness argument that programmers can rely on.

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

### Syndicate/js

In-browser and node.js implementation

Assertions can place DOM elements on the page

DOM events generate Syndicate/js messages

Websocket protocol connects browser to Syndicate/rkt

    function todoListItemModel(initialId, initialTitle, initialCompleted) {
      spawn {
        field this.id = initialId;
        field this.title = initialTitle;
        field this.completed = initialCompleted;

        stop on message deleteTodo(this.id);

        assert todo(this.id, this.title, this.completed);

        on message setCompleted(this.id, $v) { this.completed = v; }
        on message setAllCompleted($v)       { this.completed = v; }

        on message setTitle(this.id, $v)     { this.title = v;     }

        on message clearCompletedTodos() {
          if (this.completed) :: deleteTodo(this.id);
        }
      }
    }

It's more or less a curly-brace version of the same additions to the language

And of course we built a few other reasonably large programs.

This is a 2D platform game written in Syndicate/rkt.

Everything you see on screen is an assertion.

The same is true for this windowing system.

Another nice feature is the window-list on the bottom. Both that and the windows themselves are from the same assertion.

Good fault-tolerance properties.

- IRC Server
- TCP/IP Stack
- Collaborative text editor server
- Broker: embeds Syndicate/js in Syndicate/rkt
- Web-based chat application
- Many, many, many smaller examples

http://syndicate-lang.org/

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

#### How should we evaluate a language design idea?

Quantitatively? | ✗ Benchmark suites ✗ Error rates ✗ Programmer productivity
Qualitatively | ✓ Simplification of programs ✓ Asymptotic performance

### Patterns

Simplify by eliminating patterns.

### Patterns

Programming Pattern [Felleisen 1991]

Design Pattern [Gamma et al. 1994]

Informal → Formal → Invisible

[Norvig 1996]

1. Event Broadcast (encoding)
2. The "Observer" Pattern [Gamma et al. 1994]
3. State Replication Pattern
4. The "State" Pattern [Gamma et al. 1994]
5. The "Cancellation" Pattern [Russell et al. 2016]

### State Replication

| Event broadcasting | Observer pattern | State replication
Smalltalk | informal/invisible | formal | informal
Ruby | informal/invisible | formal | informal
Java | informal/invisible | informal | informal
Erlang/OTP | informal/invisible | informal | informal
Syndicate | invisible | invisible | invisible

### "State" Pattern

Java | informal
Syndicate | invisible

### "Cancellation" Pattern

JavaScript | informal
Syndicate | invisible

    (struct service-a (request response))
    (struct service-b (request response))

    (spawn (during (service-a 'request-from-a $response)
             (on-start (printf "Response: ~v\n" response))))

    (spawn (during (observe (service-a $req-a _))
             (during (service-b 'request-from-b $resp-b)
               (assert (service-a req-a (make-answer resp-b))))))

### Asymptotic performance

Message routing & delivery, sec/event vs k

Unicast: Õ(1) | Broadcast: Õ(1/k + 1)

Message-routing and -delivery as expected

### Asymptotic performance

Assertion set update cost, sec/event vs k

k-independent: Õ(1) | k-dependent: Õ(1)

Complex space

A few extreme points in this space: no surprises

### Asymptotic performance

TCP echo server, sec/conn vs k

Marginal cost of additional connection: Õ(1)

### Roadmap

1. Dataspace model and assertion tries
2. Reifying conversations
3. Programming experience with Syndicate
4. Evaluation
5. Conclusion & future work

### Syndicate provides a...

new | → | design landscape
effective | → | evaluation
realizable | → | prototypes, tries
linguistic | → | reified conversations
mechanism for sharing state | → | dataspace model

in a concurrent setting.

### Future Work

- Enhancements to the formal models
  types; names; grouping & relaying; formal properties
- System model
  performance; tool support; generic protocols; process management;
  stdio; contracts; security; persistence; polyglot
- Distributed systems
  unpredictable latency & scheduling; message loss; subnets

### Thank you!

Committee: Thank You for Signing my Dissertation! :-)

### Future Work

- Enhancements to the formal models
  types; names; grouping & relaying; formal properties
- System model
  performance; tool support; generic protocols; process management;
  stdio; contracts; security; persistence; polyglot
- Distributed systems
  unpredictable latency & scheduling; message loss; subnets

### Thank you!

Committee: Thank You for Signing my Dissertation! :-)

### Backup

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

New expressions: |
    (spawn endpoint-expr ...)
    (spawn* expr ...)
    (dataspace expr ...)
    (react endpoint-expr ...)
    (stop-facet facet-id-expr expr ...)
    (current-facet-id)
    (send! expr)
Field access: |
    (fieldname)
Field update: |
    (fieldname expr)

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))

    (struct set-box (new-value))
    (struct box-state (value))

    (spawn (field [current-value 0])
           (assert (box-state (current-value)))
           (on (message (set-box $new-value))
               (current-value new-value)))

    (spawn (on (asserted (box-state $v))
               (send! (set-box (+ v 1)))))