syndicate-2017/tonyg-dissertation/html/index.nomath.html

4117 lines
1.3 MiB
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Conversational Concurrency</title><link rel="stylesheet" href="reset.css"/><link rel="stylesheet" href="tonyg-dissertation.css"/><script src="tonyg-dissertation.js"></script></head><body class="lyx-mathjax-ignore"><h1 id="title">Conversational Concurrency</h1><div class="author">Tony Garnock-Jones</div><div class="main">
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_1">\(\newcommand{\NOTFOUND}{\mathsf{notfound}}
\newcommand{\FOUND}[1]{\mathsf{found}(#1)}
\newcommand{\SETOF}[1]{\mathcal{P}(#1)}
\newcommand{\PACK}[2]{\mathsf{pack}\left\langle #1,#2\right\rangle }
\newcommand{\UNPACK}[4]{\mathsf{unpack}\,\left\langle #1,#2\right\rangle =#3\,\mathsf{in}\,#4}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_2">\(\newcommand{\CONTINUEName}{\mathsf{continue}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_3">\(\newcommand{\INITName}{\mathsf{init}}
\newcommand{\EXITName}{\mathsf{exit}}
\newcommand{\CONTINUE}[1]{\CONTINUEName(#1)}
\newcommand{\INIT}[1]{\INITName(#1)}
\newcommand{\EXIT}[1]{\EXITName(#1)}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_4">\(\newcommand{\LISTOF}[1]{[#1]}
\newcommand{\VECOF}[1]{\overrightarrow{#1}}
\newcommand{\PL}{\textsc{Syndicate}}
\newcommand{\PLJS}{\textsc{Syndicate/js}}
\newcommand{\PLRACKET}{\textsc{Syndicate/rkt}}
\newcommand{\PLLAMBDA}{\textsc{Syndicate/}\lambda}
\newcommand{\T}[1]{\mathbf{#1}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_5">\(\newcommand{\LIME}{\textsc{Lime}}
\newcommand{\CRIME}{\textsc{Crime}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_6">\(\newcommand{\ROUTES}{\pi}
\newcommand{\ROUTESADD}{\ROUTES_{\mathit{in}}}
\newcommand{\ROUTESDEL}{\ROUTES_{\mathit{out}}}
\newcommand{\ROUTESADDpad}{\rlap{\ROUTESADD}\phantom{\ROUTESDEL}}{\ROUTESADD}
\newcommand{\ROUTESstar}{\ROUTES^{\circ}}
\newcommand{\ROUTESbullet}{\ROUTES^{\bullet}}
\newcommand{\ROUTESDELbullet}{\ROUTESDEL^{\bullet}}
\newcommand{\ROUTESADDbullet}{\rlap{\ROUTESADD^{\bullet}}\phantom{\ROUTESDELbullet}}{\ROUTESADD^{\bullet}}
\newcommand{\DeltaOther}{\Delta_{\mathit{other}}}
\newcommand{\DeltaFb}{\Delta_{\mathit{fb}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_7">\(\newcommand{\FBCDName}{\mathsf{bc}_{\Delta}}
\newcommand{\FBCD}[4]{\FBCDName\ #1\ #2\ #3\ #4}
\newcommand{\FASSERTIONSName}{\mathit{assertions}}
\newcommand{\FPROJECTName}{\mathit{project}}
\newcommand{\KDuring}{\mathsf{during}}
\newcommand{\KSelect}{\mathsf{select}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_8">\(\newcommand{\SUBSTfrac}[2]{\left\{ \frac{#1}{#2}\right\} }
\newcommand{\PlainSUBST}[3]{\SUBSTfrac{#2}{#3}#1}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_9">\(\newcommand{\SUBSTval}[3]{\PlainSUBST{#1}{#2}{#3}}
\newcommand{\SUBSTfield}[3]{\PlainSUBST{#1}{#2}{#3}}
\newcommand{\SUBSTfacet}[3]{\PlainSUBST{#1}{#2}{#3}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_10">\(\newcommand{\EXTEND}[3]{#1[#2\mapsto#3]}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_11">\(\newcommand{\SOURCEFILEPOINTER}[1]{\textrm{Source code file \texttt{#1} in the \PL\ repository.}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_12">\(\newcommand{\CBoot}{f_{\mathit{boot}}}
\newcommand{\CBehF}{f_{\mathit{beh}}}
\newcommand{\CBehPack}[3]{\PACK{#1}{(#2,#3)}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_13">\(\newcommand{\TProg}{\T{Prog}}
\newcommand{\TEvt}{\T{Evt}}
\newcommand{\TAct}{\T{Act}}
\newcommand{\TBoot}{\T{Boot}}
\newcommand{\TBehF}[1]{\mathcal{F}_{#1}}
\newcommand{\TBehPack}[1]{\exists#1.(\TBehF{#1}\times#1)}
\newcommand{\TVal}{\T{Val}}
\newcommand{\TASet}{\T{ASet}}
\newcommand{\TBVal}{\T{BVal}}
\newcommand{\AActorName}{\mathsf{actor}}
\newcommand{\ADSName}{\mathsf{dataspace}}
\newcommand{\AActor}[2]{\AActorName\;#1\;#2}
\newcommand{\ADS}[1]{\ADSName\;#1}
\newcommand{\AMsg}[1]{\langle#1\rangle}
\newcommand{\Obs}[1]{?#1}
\newcommand{\In}[1]{\upharpoonleft#1}
\newcommand{\Out}[1]{\downharpoonleft#1}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_14">\(\newcommand{\TCfg}{\T{Cfg}}
\newcommand{\TActor}{\T{Actor}}
\newcommand{\TState}{\T{State}}
\newcommand{\TBeh}{\T{Beh}}
\newcommand{\TQAct}{\T{QAct}}
\newcommand{\TSpace}{\T{Space}}
\newcommand{\TID}{\T{ID}}
\newcommand{\TLoc}{\T{Loc}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_15">\(\newcommand{\TActorQ}{\T{Actor_{Q}}}
\newcommand{\TStateQ}{\T{State_{Q}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_16">\(\newcommand{\TCfgI}{\T{Cfg_{I}}}
\newcommand{\TActorI}{\T{Actor_{I}}}
\newcommand{\TStateI}{\T{State_{I}}}
\newcommand{\TBehI}{\T{Beh_{I}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_17">\(\newcommand{\CCfg}[3]{[#1;#2;#3]}
\newcommand{\CActor}[2]{#1\mapsto#2}
\newcommand{\CState}[3]{\langle#1\triangleright#2\triangleright#3\rangle}
\newcommand{\CQAct}[2]{(#1,#2)}
\newcommand{\CMeta}{\downharpoonleft}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_18">\(\newcommand{\FBOOT}{\mathsf{boot}}
\newcommand{\FNOOP}{\mathsf{noop}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_19">\(\newcommand{\RULENAME}[1]{\textsf{#1}}
\newcommand{\RNotifyLeaf}{\RULENAME{notify-leaf}}
\newcommand{\RQuit}{\RULENAME{quit}}
\newcommand{\RNotifyDS}{\RULENAME{notify-ds}}
\newcommand{\RGather}{\RULENAME{gather}}
\newcommand{\RNewtable}{\RULENAME{newtable}}
\newcommand{\RMessage}{\RULENAME{message}}
\newcommand{\RSpawn}{\RULENAME{spawn}}
\newcommand{\RSchedule}{\RULENAME{schedule}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_20">\(\newcommand{\FINP}{\mathsf{inp}}
\newcommand{\FBCName}{\mathsf{bc}}
\newcommand{\FBC}[4]{\FBCName\ #1\ #2\ #3\ #4}
\newcommand{\FOUTName}{\mathsf{out}}
\newcommand{\FOUT}[3]{\FOUTName\ #1\ #2\ #3}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_21">\(\newcommand{\TPatch}{\T{Patch}}
\newcommand{\CPatch}[2]{\frac{#1}{#2}}
\newcommand{\RPatch}{\RULENAME{patch}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_22">\(\newcommand{\KSend}{\mathsf{send}}
\newcommand{\KSpawn}{\mathsf{spawn}}
\newcommand{\KDataspace}{\mathsf{dataspace}}
\newcommand{\KLet}{\mathsf{let}}
\newcommand{\KAsserted}{\mathsf{asserted}}
\newcommand{\KRetracted}{\mathsf{retracted}}
\newcommand{\KMessage}{\mathsf{message}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_23">\(\newcommand{\CPr}{Pr}
\newcommand{\TPr}{\T{Pr}}
\newcommand{\TPrg}{\T{Prg}}
\newcommand{\TExpr}{\T{Expr}}
\newcommand{\THVal}{\TVal^{\lambda}}
\newcommand{\TVar}{\T{Var}}
\newcommand{\TEPat}{\T{EPat}}
\newcommand{\TPat}{\T{Pat}}
\newcommand{\TTemplate}{\T{Tmpl}}
\newcommand{\TPVal}{\T{PVal}}
\newcommand{\TTemplates}{\T{Tmpls}}
\newcommand{\TPrim}{\T{Prim}}
\newcommand{\THEvt}{\TEvt^{+}}
\newcommand{\CEvt}{\epsilon}
\newcommand{\CHEvt}{\CEvt^{+}}
\newcommand{\DStart}{\mathsf{start}}
\newcommand{\DStop}{\mathsf{stop}}
\newcommand{\DAsserted}[1]{\KAsserted\;#1}
\newcommand{\CProc}[1]{\lambda\left[#1\right]}
\newcommand{\CClause}[2]{\left(#1.#2\right)}
\newcommand{\DRetracted}[1]{\KRetracted\;#1}
\newcommand{\DMessage}[1]{\KMessage\;\AMsg{#1}}
\newcommand{\CPVal}{\mathcal{I}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_24">\(\newcommand{\CS}{S}
\newcommand{\TTree}{\T{Tree}}
\newcommand{\CSI}{S_{I}}
\newcommand{\TTreeI}{\T{Tree_{I}}}
\newcommand{\CE}{E}
\newcommand{\TE}{\T{Ctxt}}
\newcommand{\CM}{M}
\newcommand{\TM}{\T M}
\newcommand{\CMI}{M_{I}}
\newcommand{\TMI}{\T{M_{I}}}
\newcommand{\CStore}{\sigma}
\newcommand{\TStore}{\T{Store}}
\newcommand{\Machine}[5]{\left\langle #1,#2,#3,#4,#5\right\rangle }
\newcommand{\CErr}{\spadesuit}
\newcommand{\OrError}[1]{#1_{\CErr}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_25">\(\newcommand{\EQPAR}{\;\rlap{\;|}\phantom{:=\;}}{|\;}
\newcommand{\hole}{\square}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_26">\(\newcommand{\CInert}{0}
\newcommand{\CSeq}[2]{#1;#2}
\newcommand{\CCall}[2]{#1\;#2}
\newcommand{\CField}[3]{\KLet\;#1\;:=\;#2\;\mathsf{in}\;#3}
\newcommand{\CBind}[3]{\KLet\;#1\;=\;#2\;\mathsf{in}\;#3}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_27">\(\newcommand{\CUpdate}[2]{#1\shortleftarrow#2}
\newcommand{\CSend}[1]{\KSend\;#1}
\newcommand{\CSpawn}[1]{\KSpawn\;#1}
\newcommand{\CDS}[1]{\KDataspace\;#1}
\newcommand{\CStop}[2]{\DStop\;#1\;#2}
\newcommand{\CFacet}[2]{#1\left[#2\right]}
\newcommand{\CEndpoint}[2]{\;\left(#1\;#2\right)}
\newcommand{\EFacet}[3]{\CFacet{#1}{#2}.#3}
\newcommand{\EFacetStop}[3]{\CFacet{#1}{#2}\dagger#3}
\newcommand{\EKill}[1]{\%\left[#1\right]}
\newcommand{\CVar}[1]{\$#1}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_28">\(\newcommand{\FVName}{\mathsf{fv}}
\newcommand{\FV}[1]{\FVName(#1)}
\newcommand{\BVName}{\mathsf{bv}}
\newcommand{\BV}[1]{\BVName(#1)}
\newcommand{\FORMALSName}{\mathit{formals}}
\newcommand{\FORMALS}[1]{\FORMALSName(#1)}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_29">\(\newcommand{\FSETUP}{\mathit{setup}}
\newcommand{\FHLL}{\mathit{interp}}
\newcommand{\FEMIT}{\mathit{emit}}
\newcommand{\FINJECTName}{\mathit{inject}}
\newcommand{\FINJECT}[5]{\FINJECTName\:#1\;#2\;#3\;#4\;#5}
\newcommand{\FPATCHName}{\mathit{patch}}
\newcommand{\FPATCH}[3]{\FPATCHName\;#1\;#2\;#3}
\newcommand{\FHANDLEName}{\mathit{handle}}
\newcommand{\FHANDLE}[5]{\FHANDLEName\;#1\;#2\;#3\;#4\;#5}
\newcommand{\FPROJECT}[6]{\FPROJECTName\;#1\;#2\;#3\;#4\;#5\;#6}
\newcommand{\FMATCHINORDERName}{\mathit{matchInOrder}}
\newcommand{\FMATCHINORDER}[3]{\FMATCHINORDERName\;#1\;#2\;#3}
\newcommand{\FMATCHName}{\mathit{match}}
\newcommand{\FMATCH}[3]{\FMATCHName\;#1\;#2\;#3}
\newcommand{\FINSTName}{\mathit{inst}}
\newcommand{\FINST}[2]{\FINSTName\;#1\;#2}
\newcommand{\FKNOWNName}{\mathit{known}}
\newcommand{\FKNOWN}[2]{\FKNOWNName(#1,#2)}
\newcommand{\FSNAPSHOTName}{\mathit{snapshot}}
\newcommand{\FSNAPSHOT}[2]{\FSNAPSHOTName\;#1\;#2}
\newcommand{\FASSERTIONS}[2]{\FASSERTIONSName\;#1\;#2}
\newcommand{\FEVALName}{\mathit{eval}}
\newcommand{\FEVAL}[2]{\FEVALName\;#1\;#2}
\newcommand{\FEVALLName}{\mathit{eval}^{\lambda}}
\newcommand{\FEVALL}[2]{\FEVALLName\;#1\;#2}
\newcommand{\FDELTAName}{\mathit{delta}}
\newcommand{\FDELTA}[2]{\FDELTAName\;#1\;#2}
\newcommand{\FDELTALName}{\mathit{delta}^{\lambda}}
\newcommand{\FDELTAL}[2]{\FDELTALName\;#1\;#2}
\newcommand{\FUNROLL}{\mathit{unroll}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_30">\(\newcommand{\RCall}{\RULENAME{call}}
\newcommand{\RLet}{\RULENAME{let}}
\newcommand{\RNewField}{\RULENAME{new-field}}
\newcommand{\RSetField}{\RULENAME{set-field}}
\newcommand{\RSend}{\RULENAME{send}}
\newcommand{\RDataspace}{\RULENAME{dataspace}}
\newcommand{\RBootFacet}{\RULENAME{boot-facet}}
\newcommand{\RStopFacetA}{\RULENAME{stop-facet-1}}
\newcommand{\RStopFacetB}{\RULENAME{stop-facet-2}}
\newcommand{\RStopChildA}{\RULENAME{stop-child-1}}
\newcommand{\RStopChildB}{\RULENAME{stop-child-2}}
\newcommand{\RStopChildC}{\RULENAME{stop-child-3}}
\newcommand{\RBurial}{\RULENAME{burial}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_31">\(\newcommand{\CDuring}[1]{\KDuring\;#1}
\newcommand{\CSelect}[4]{\KSelect\;#1\;\mathsf{into}\;#2:=#3\;\mathsf{in}\;#4}
\newcommand{\CDuringSpawn}[1]{\KDuring\;#1\;\KSpawn}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_0_0_0_0_32">\(\newcommand{\MEANINGName}{\mathit{meaning}}
\newcommand{\MEANING}[1]{\MEANINGName(#1)}
\newcommand{\MEANINGn}[2]{\MEANINGName\left(#1,#2\right)}
\newcommand{\ARITY}[1]{\##1}
\newcommand{\ATOM}{\mathbf{Atom}}
\newcommand{\SEXP}{\mathbf{Sexp}}
\newcommand{\TOK}{\mathbf{Tok}}
\newcommand{\LL}[1]{\ll_{#1}}
\newcommand{\SER}[1]{\llbracket#1\rrbracket}
\newcommand{\DESER}[1]{\llparenthesis#1\rrparenthesis}
\newcommand{\WFname}{\mathcal{WF}}
\newcommand{\WF}[1]{\WFname(#1)}
\newcommand{\WFn}[2]{\WFname_{#1}(#2)}
\newcommand{\WFplus}[1]{\WFname^{+}(#1)}
\newcommand{\WFnplus}[2]{\WFname_{#1}^{+}(#2)}
\newcommand{\NODE}[1]{\mathbf{Node}_{\mathbf{#1}}}
\newcommand{\TRIE}[1]{\mathbf{Trie}_{\mathbf{#1}}}
\newcommand{\MT}{\mathsf{mt}}
\newcommand{\OK}[1]{\mathsf{ok}(#1)}
\newcommand{\OKunit}{\OK{()}}
\newcommand{\BRname}{\mathsf{br}}
\newcommand{\BRx}[2]{\BRname(#1,#2)}
\newcommand{\BR}[2]{\BRx{#1}{\{#2\}}}
\newcommand{\PAT}[3]{\mathit{pat}_{\mathbf{#1}}(#2,#3)}
\newcommand{\PATseq}[3]{\mathit{pat}_{\mathbf{#1}}^{\prime}(#2,#3)}
\newcommand{\NEGTRIE}[1]{\mathit{neg}(#1)}
\newcommand{\COLLECTname}{\mathit{collect}}
\newcommand{\COLLECT}[4]{\COLLECTname\left(#4,#1,#2,#3\right)}
\newcommand{\LOC}{\mathbf{Loc}}
\newcommand{\SETTRIE}{\TRIE 1}
\newcommand{\DSTRIE}{\TRIE{\SETOF{\LOC}}}
\newcommand{\RELABELname}{\mathit{relabel}}
\newcommand{\RELABEL}[2]{\RELABELname\ #1\ #2}
\newcommand{\SEARCHname}{\mathit{search}}
\newcommand{\SEARCH}[3]{\SEARCHname_{\mathbf{#1}}(#2,#3)}
\newcommand{\makeTail}[2]{\mathit{makeTail\ #1}\ #2}
\newcommand{\COMBINEname}{\mathit{combine}}
\newcommand{\COMBINE}[5]{\COMBINEname\ #1\ #2\ #3\ #4\ #5}
\newcommand{\COLLAPSE}[1]{\mathit{collapse}\ #1}
\newcommand{\FOLDKEYS}{\mathit{foldKeys}}
\newcommand{\LOOKUP}{\mathit{lookup}}
\newcommand{\PROJ}{\mathbf{Proj}}
\newcommand{\CAP}{\$}
\newcommand{\DISCARD}{\_}
\newcommand{\MATCHname}{\mathit{match}}
\newcommand{\MATCH}[2]{\MATCHname\ #1\ #2}
\newcommand{\PROJECTSPECname}{\mathit{project}_{\mathit{spec}}}
\newcommand{\PROJECTname}{\mathit{project}}
\newcommand{\PROJECT}[2]{\PROJECTname\ #1\ #2}
\newcommand{\PROJECTSPEC}[2]{\PROJECTSPECname\ #1\ #2}
\newcommand{\WALKname}{\mathit{walk}}
\newcommand{\WALK}[3]{\WALKname\ #1\ #2\ #3}
\newcommand{\WALKCname}{\mathit{capture}}
\newcommand{\WALKC}[3]{\WALKCname\ #1\ #2\ #3}
\newcommand{\KEYSETname}{\mathit{keySet}}
\newcommand{\KEYSET}[1]{\KEYSETname\ #1}
\newcommand{\TTAKEname}{\mathit{take}}
\newcommand{\TTAKE}[4]{\TTAKEname\ #1\ #2\ #3\ #4}
\newcommand{\LISTTOK}[1]{\mathsf{list}_{#1}}
\newcommand{\VECTOK}[1]{\mathsf{vec}_{#1}}
\)</div><p id="x_0_0_0_0_45">
<h3 class="unnumbered" id="x_0_0_0_0_33"><a name="toc_0"></a><span class="heading-text chapter">Abstract</span></h3><p id="x_0_0_0_0_34">Concurrent computations resemble conversations. In a conversation, participants direct utterances at others and, as the conversation evolves, exploit the known common context to advance the conversation. Similarly, collaborating software components share knowledge with each other in order to make progress as a group towards a common goal.</p><p id="x_0_0_0_0_35">This dissertation studies concurrency from the perspective of cooperative knowledge-sharing, taking the conversational exchange of knowledge as a central concern in the design of concurrent programming languages. In doing so, it makes five contributions:</p>
<ol id="x_0_0_0_0_43"><li id="x_0_0_0_0_37">It develops the idea of a common <em>dataspace</em> as a medium for knowledge exchange among concurrent components, enabling a new approach to concurrent programming. <p id="x_0_0_0_0_36">While dataspaces loosely resemble both “fact spaces” from the world of Linda-style languages and Erlang's collaborative model, they significantly differ in many details.</p></li><li id="x_0_0_0_0_38">It offers the first crisp formulation of cooperative, conversational knowledge-exchange as a mathematical model.</li><li id="x_0_0_0_0_39">It describes two faithful implementations of the model for two quite different languages.</li><li id="x_0_0_0_0_41">It proposes a completely novel suite of linguistic constructs for organizing the internal structure of individual actors in a conversational setting.<p id="x_0_0_0_0_40">The combination of dataspaces with these constructs is dubbed <span class="small-caps">Syndicate</span>.</p></li><li id="x_0_0_0_0_42">It presents and analyzes evidence suggesting that the proposed techniques and constructs combine to simplify concurrent programming.</li></ol><p id="x_0_0_0_0_44">The dataspace concept stands alone in its focus on representation and manipulation of conversational frames and conversational state and in its integral use of explicit epistemic knowledge. The design is particularly suited to integration of general-purpose I/O with otherwise-functional languages, but also applies to actor-like settings more generally.</p></p><p id="x_0_0_0_0_60">
<h3 class="unnumbered" id="x_0_0_0_0_46"><a name="toc_0"></a><span class="heading-text chapter">Acknowledgments</span></h3>
<blockquote id="x_0_0_0_0_49">
<p id="x_0_0_0_0_47">Networking is interprocess communication.</p>
<p class="align-right" id="x_0_0_0_0_48">—Robert Metcalfe, 1972, quoted in <span class="citation citet"><a class="citation" id="cite-1" href="#bib-Day2008"><span>Day<span class="parens"> (</span>2008<span class="parens">)</span></span></a></span></p></blockquote><p id="x_0_0_0_0_50">I am deeply grateful to the many, many people who have supported, taught, and encouraged me over the past seven years.</p><p id="x_0_0_0_0_51">My heartfelt thanks to my advisor, Matthias Felleisen. Matthias, it has been an absolute privilege to be your student. Without your patience, insight and willingness to let me get the crazy ideas out of my system, this work would not have been possible. My gratitude also to the members of my thesis committee, Mitch Wand, Sam Tobin-Hochstadt, and Jan Vitek. Sam in particular helped me convince Matthias that there might be something worth looking into in this concurrency business. I would also like to thank Olin Shivers for providing early guidance during my studies.</p><p id="x_0_0_0_0_52">Thanks also to my friends and colleagues from the Programming Research Lab, including Claire Alvis, Leif Andersen, William Bowman, Dan Brown, Sam Caldwell, Stephen Chang, Ben Chung, Andrew Cobb, Ryan Culpepper, Christos Dimoulas, Carl Eastlund, Spencer Florence, Oli Flückiger, Dee Glaze, Ben Greenman, Brian LaChance, Ben Lerner, Paley Li, Max New, Jamie Perconti, Gabriel Scherer, Jonathan Schuster, Justin Slepak, Vincent St-Amour, Paul Stansifer, Stevie Strickland, Asumu Takikawa, Jesse Tov, and Aaron Turon. Sam Caldwell deserves particular thanks for being the second ever <span class="small-caps">Syndicate</span> programmer and for being willing to pick up the ideas of <span class="small-caps">Syndicate</span> and run with them.</p><p id="x_0_0_0_0_53">Many thanks to Alex Warth and Yoshiki Ohshima, who invited me to intern at CDG Labs with a wonderful research group during summer and fall 2014, and to John Day, whose book helped motivate me to return to academia. Thanks also to the DARPA CRASH program and to several NSF grants that helped to fund my PhD research.</p><p id="x_0_0_0_0_54">I wouldn't have made it here without crucial interventions over the past few decades from a wide range of people. Nigel Bree hooked me on Scheme in the early '90s, igniting a lifelong interest in functional programming. A decade later, while working at a company called LShift, my education as a computer scientist truly began when Matthias Radestock and Greg Meredith introduced me to the <span class="lyx-mathjax mathjax-inline">$\pi$</span>-calculus and many related ideas. Andy Wilson broadened my mind with music, philosophy and political ideas both new and old. A few years later, Alexis Richardson showed me the depth and importance of distributed systems as we developed new ideas about messaging middleware and programming languages while working together on RabbitMQ. My colleagues at LShift were instrumental to the development of the ideas that ultimately led to this work. My thanks to all of you. In particular, I owe an enormous debt of gratitude to my good friend Michael Bridgen. Michael, the discussions we have had over the years contributed to this work in so many ways that I'm still figuring some of them out.</p><p id="x_0_0_0_0_55">Life in Boston wouldn't have been the same without the friendship and hospitality of Scott and Megs Stevens. Thank you both.</p><p id="x_0_0_0_0_56">Finally, I'm grateful to my family. The depth of my feeling prevents me from adequately conveying quite how grateful I am. Thank you Mum, Dad, Karly, Casey, Sabrina, and Blyss. Each of you has made an essential contribution to the person I've become, and I love you all. Thank you to the Yates family and to Warren, Holden and Felix for much-needed distraction and moments of zen in the midst of the write-up. But most of all, thank you to Donna. You're my person.</p><p id="x_0_0_0_0_58">
<p class="align-right" id="x_0_0_0_0_57">Tony Garnock-Jones<br/>Boston, Massachusetts<br/>December 2017</p></p><p id="x_0_0_0_0_59"><div class="toc"><h3 id="toc">Contents</h3><ul class="toc"><li class="part"><a href="#toc_I"><span class="toc-counter part"><span>I</span></span><span class="heading-text part">Background</span></a></li><li class="chapter"><a href="#CHAP:INTRODUCTION"><span class="toc-counter chapter"><span>1</span></span><span class="heading-text chapter">Introduction</span></a></li><li class="chapter"><a href="#CHAP:PHILOSOPHY-AND-OVERVIEW"><span class="toc-counter chapter"><span>2</span></span><span class="heading-text chapter">Philosophy and Overview of the <span class="small-caps">Syndicate</span> Design</span></a></li><li class="section"><a href="#sec:Cooperating-by-sharing-knowledge"><span class="toc-counter section"><span>2.1</span></span><span class="heading-text section">Cooperating by sharing knowledge</span></a></li><li class="section"><a href="#toc_2.2"><span class="toc-counter section"><span>2.2</span></span><span class="heading-text section">Knowledge types and knowledge flow</span></a></li><li class="section"><a href="#sec:Unpredictability-at-run-time"><span class="toc-counter section"><span>2.3</span></span><span class="heading-text section">Unpredictability at run-time</span></a></li><li class="section"><a href="#sec:Unpredictability-in-design"><span class="toc-counter section"><span>2.4</span></span><span class="heading-text section">Unpredictability in the design process</span></a></li><li class="section"><a href="#sec:Syndicate's-approach-to-concurrency"><span class="toc-counter section"><span>2.5</span></span><span class="heading-text section"><span class="small-caps">Syndicate</span>'s approach to concurrency</span></a></li><li class="section"><a href="#sec:Syndicate-design-principles"><span class="toc-counter section"><span>2.6</span></span><span class="heading-text section"><span class="small-caps">Syndicate</span> design principles</span></a></li><li class="section"><a href="#toc_2.7"><span class="toc-counter section"><span>2.7</span></span><span class="heading-text section">On the name “<span class="small-caps">Syndicate</span>”</span></a></li><li class="chapter"><a href="#CHAP:APPROACHES-TO-COORDINATION"><span class="toc-counter chapter"><span>3</span></span><span class="heading-text chapter">Approaches to Coordination</span></a></li><li class="section"><a href="#sec:A-concurrency-design-landscape"><span class="toc-counter section"><span>3.1</span></span><span class="heading-text section">A concurrency design landscape</span></a></li><li class="section"><a href="#sec:Shared-memory"><span class="toc-counter section"><span>3.2</span></span><span class="heading-text section">Shared memory</span></a></li><li class="section"><a href="#sec:Message-passing"><span class="toc-counter section"><span>3.3</span></span><span class="heading-text section">Message-passing</span></a></li><li class="section"><a href="#toc_3.4"><span class="toc-counter section"><span>3.4</span></span><span class="heading-text section">Tuplespaces and databases</span></a></li><li class="section"><a href="#sec:The-fact-space-model"><span class="toc-counter section"><span>3.5</span></span><span class="heading-text section">The fact space model</span></a></li><li class="section"><a href="#sec:Surveying-the-landscape"><span class="toc-counter section"><span>3.6</span></span><span class="heading-text section">Surveying the landscape</span></a></li><li class="part"><a href="#toc_II"><span class="toc-counter part"><span>II</span></span><span class="heading-text part">Theory</span></a></li><li class="chapter"><a href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES"><span class="toc-counter chapter"><span>4</span></span><span class="heading-text chapter">Computational Model I: The Dataspace Model</span></a></li><li class="section"><a href="#sec:Informal-DS-semantics"><span class="toc-counter section"><span>4.1</span></span><span class="heading-text section">Abstract dataspace model syntax and informal semantics</span></a></li><li class="section"><a href="#sec:Formal-DS-semantics"><span class="toc-counter section"><span>4.2</span></span><span class="heading-text section">Formal semantics of the dataspace model</span></a></li><li class="section"><a href="#toc_4.3"><span class="toc-counter section"><span>4.3</span></span><span class="heading-text section">Cross-layer communication</span></a></li><li class="section"><a href="#sec:Messages-versus-Assertions"><span class="toc-counter section"><span>4.4</span></span><span class="heading-text section">Messages versus assertions</span></a></li><li class="section"><a href="#sec:DS-properties"><span class="toc-counter section"><span>4.5</span></span><span class="heading-text section">Properties</span></a></li><li class="section"><a href="#sec:incremental-DS"><span class="toc-counter section"><span>4.6</span></span><span class="heading-text section">Incremental assertion-set maintenance</span></a></li><li class="section"><a href="#sec:incremental-examples"><span class="toc-counter section"><span>4.7</span></span><span class="heading-text section">Programming with the incremental protocol</span></a></li><li class="section"><a href="#subsec:Styles-of-interaction"><span class="toc-counter section"><span>4.8</span></span><span class="heading-text section">Styles of interaction</span></a></li><li class="chapter"><a href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE"><span class="toc-counter chapter"><span>5</span></span><span class="heading-text chapter">Computational Model II: <span class="small-caps">Syndicate</span></span></a></li><li class="section"><a href="#sec:Informal-PLLAMBDA-semantics"><span class="toc-counter section"><span>5.1</span></span><span class="heading-text section">Abstract <span class="small-caps">Syndicate/λ</span> syntax and informal semantics</span></a></li><li class="section"><a href="#sec:Formal-PLLAMBDA-semantics"><span class="toc-counter section"><span>5.2</span></span><span class="heading-text section">Formal semantics of <span class="small-caps">Syndicate/λ</span></span></a></li><li class="section"><a href="#sec:PLLAMBDA-interpretation-of-events"><span class="toc-counter section"><span>5.3</span></span><span class="heading-text section">Interpretation of events</span></a></li><li class="section"><a href="#sec:PLLAMBDA-DS-interface"><span class="toc-counter section"><span>5.4</span></span><span class="heading-text section">Interfacing <span class="small-caps">Syndicate/λ</span> to the dataspace model</span></a></li><li class="section"><a href="#sec:Well-formedness-and-errors"><span class="toc-counter section"><span>5.5</span></span><span class="heading-text section">Well-formedness and Errors</span></a></li><li class="section"><a href="#sec:Atomicity-and-isolation"><span class="toc-counter section"><span>5.6</span></span><span class="heading-text section">Atomicity and isolation</span></a></li><li class="section"><a href="#sec:PLLAMBDA-derived-forms"><span class="toc-counter section"><span>5.7</span></span><span class="heading-text section">Derived forms: <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> and <span class="lyx-mathjax mathjax-inline">$\KSelect$</span></span></a></li><li class="section"><a href="#sec:PLLAMBDA-properties"><span class="toc-counter section"><span>5.8</span></span><span class="heading-text section">Properties</span></a></li><li class="part"><a href="#toc_III"><span class="toc-counter part"><span>III</span></span><span class="heading-text part">Practice</span></a></li><li class="chapter"><a href="#CHAP:TUTORIAL"><span class="toc-counter chapter"><span>6</span></span><span class="heading-text chapter"><span class="small-caps">Syndicate/rkt</span> Tutorial</span></a></li><li class="section"><a href="#toc_6.1"><span class="toc-counter section"><span>6.1</span></span><span class="heading-text section">Installation and brief example</span></a></li><li class="section"><a href="#sec:rkt:ground-and-drivers"><span class="toc-counter section"><span>6.2</span></span><span class="heading-text section">The structure of a running program: ground dataspace, driver actors</span></a></li><li class="section"><a href="#toc_6.3"><span class="toc-counter section"><span>6.3</span></span><span class="heading-text section">Expressions, values, mutability, and data types</span></a></li><li class="section"><a href="#sec:rkt-Core-forms"><span class="toc-counter section"><span>6.4</span></span><span class="heading-text section">Core forms</span></a></li><li class="section"><a href="#sec:rkt:Derived-and-additional"><span class="toc-counter section"><span>6.5</span></span><span class="heading-text section">Derived and additional forms</span></a></li><li class="section"><a href="#sec:Ad-hoc-assertions"><span class="toc-counter section"><span>6.6</span></span><span class="heading-text section">Ad-hoc assertions</span></a></li><li class="chapter"><a href="#CHAP:IMPLEMENTATION"><span class="toc-counter chapter"><span>7</span></span><span class="heading-text chapter">Implementation</span></a></li><li class="section"><a href="#sec:Representing-Assertion-Sets"><span class="toc-counter section"><span>7.1</span></span><span class="heading-text section">Representing Assertion Sets</span></a></li><li class="subsection"><a href="#toc_7.1.1"><span class="toc-counter subsection"><span>7.1.1</span></span><span class="heading-text subsection">Background</span></a></li><li class="subsection"><a href="#subsec:Semi-structured-assertions"><span class="toc-counter subsection"><span>7.1.2</span></span><span class="heading-text subsection">Semi-structured assertions &amp; wildcards</span></a></li><li class="subsection"><a href="#toc_7.1.3"><span class="toc-counter subsection"><span>7.1.3</span></span><span class="heading-text subsection">Assertion trie syntax</span></a></li><li class="subsection"><a href="#toc_7.1.4"><span class="toc-counter subsection"><span>7.1.4</span></span><span class="heading-text subsection">Compiling patterns to tries</span></a></li><li class="subsection"><a href="#toc_7.1.5"><span class="toc-counter subsection"><span>7.1.5</span></span><span class="heading-text subsection">Representing <span class="small-caps">Syndicate</span> data structures with assertion tries</span></a></li><li class="subsection"><a href="#subsec:Searching"><span class="toc-counter subsection"><span>7.1.6</span></span><span class="heading-text subsection">Searching</span></a></li><li class="subsection"><a href="#toc_7.1.7"><span class="toc-counter subsection"><span>7.1.7</span></span><span class="heading-text subsection">Set operations</span></a></li><li class="subsection"><a href="#toc_7.1.8"><span class="toc-counter subsection"><span>7.1.8</span></span><span class="heading-text subsection">Projection</span></a></li><li class="subsection"><a href="#toc_7.1.9"><span class="toc-counter subsection"><span>7.1.9</span></span><span class="heading-text subsection">Iteration</span></a></li><li class="subsection"><a href="#subsec:Implementation-Considerations"><span class="toc-counter subsection"><span>7.1.10</span></span><span class="heading-text subsection">Implementation considerations</span></a></li><li class="subsection"><a href="#toc_7.1.11"><span class="toc-counter subsection"><span>7.1.11</span></span><span class="heading-text subsection">Evaluation of assertion tries</span></a></li><li class="subsection"><a href="#toc_7.1.12"><span class="toc-counter subsection"><span>7.1.12</span></span><span class="heading-text subsection">Work related to assertion tries</span></a></li><li class="section"><a href="#sec:implementing-dataspaces"><span class="toc-counter section"><span>7.2</span></span><span class="heading-text section">Implementing the dataspace model</span></a></li><li class="subsection"><a href="#subsec:Assertions"><span class="toc-counter subsection"><span>7.2.1</span></span><span class="heading-text subsection">Assertions</span></a></li><li class="subsection"><a href="#subsec:Patches-and-multiplexors"><span class="toc-counter subsection"><span>7.2.2</span></span><span class="heading-text subsection">Patches and multiplexors</span></a></li><li class="subsection"><a href="#subsec:Processes-and-behavior-functions"><span class="toc-counter subsection"><span>7.2.3</span></span><span class="heading-text subsection">Processes and behavior functions</span></a></li><li class="subsection"><a href="#subsec:Dataspaces"><span class="toc-counter subsection"><span>7.2.4</span></span><span class="heading-text subsection">Dataspaces</span></a></li><li class="subsection"><a href="#subsec:Relays"><span class="toc-counter subsection"><span>7.2.5</span></span><span class="heading-text subsection">Relays</span></a></li><li class="section"><a href="#sec:implementing-PLLAMBDA"><span class="toc-counter section"><span>7.3</span></span><span class="heading-text section">Implementing the full <span class="small-caps">Syndicate</span> design</span></a></li><li class="subsection"><a href="#toc_7.3.1"><span class="toc-counter subsection"><span>7.3.1</span></span><span class="heading-text subsection">Runtime</span></a></li><li class="subsection"><a href="#toc_7.3.2"><span class="toc-counter subsection"><span>7.3.2</span></span><span class="heading-text subsection">Syntax</span></a></li><li class="subsection"><a href="#subsec:Dataflow"><span class="toc-counter subsection"><span>7.3.3</span></span><span class="heading-text subsection">Dataflow</span></a></li><li class="section"><a href="#sec:Programming-tools"><span class="toc-counter section"><span>7.4</span></span><span class="heading-text section">Programming tools</span></a></li><li class="subsection"><a href="#subsec:Sequence-diagrams"><span class="toc-counter subsection"><span>7.4.1</span></span><span class="heading-text subsection">Sequence diagrams</span></a></li><li class="subsection"><a href="#subsec:Live-program-display"><span class="toc-counter subsection"><span>7.4.2</span></span><span class="heading-text subsection">Live program display</span></a></li><li class="chapter"><a href="#CHAP:IDIOMATIC-SYNDICATE"><span class="toc-counter chapter"><span>8</span></span><span class="heading-text chapter">Idiomatic <span class="small-caps">Syndicate</span></span></a></li><li class="section"><a href="#toc_8.1"><span class="toc-counter section"><span>8.1</span></span><span class="heading-text section">Protocols and Protocol Design</span></a></li><li class="section"><a href="#toc_8.2"><span class="toc-counter section"><span>8.2</span></span><span class="heading-text section">Built-in protocols</span></a></li><li class="section"><a href="#sec:Shared,-mutable-state"><span class="toc-counter section"><span>8.3</span></span><span class="heading-text section">Shared, mutable state</span></a></li><li class="section"><a href="#sec:I/O,-time,-timers"><span class="toc-counter section"><span>8.4</span></span><span class="heading-text section">I/O, time, timers and timeouts</span></a></li><li class="section"><a href="#toc_8.5"><span class="toc-counter section"><span>8.5</span></span><span class="heading-text section">Logic, deduction, databases, and elaboration</span></a></li><li class="subsection"><a href="#subsec:Forward-chaining"><span class="toc-counter subsection"><span>8.5.1</span></span><span class="heading-text subsection">Forward-chaining</span></a></li><li class="subsection"><a href="#subsec:Backward-chaining"><span class="toc-counter subsection"><span>8.5.2</span></span><span class="heading-text subsection">Backward-chaining and Hewitt's “Turing” Syllogism</span></a></li><li class="subsection"><a href="#subsec:External-knowledge-sources"><span class="toc-counter subsection"><span>8.5.3</span></span><span class="heading-text subsection">External knowledge sources: The file-system driver</span></a></li><li class="subsection"><a href="#subsec:Procedural-knowledge"><span class="toc-counter subsection"><span>8.5.4</span></span><span class="heading-text subsection">Procedural knowledge and Elaboration: “Make”</span></a></li><li class="subsection"><a href="#subsec:Incremental-truth-maintenance-and-Aggregation"><span class="toc-counter subsection"><span>8.5.5</span></span><span class="heading-text subsection">Incremental truth-maintenance and Aggregation: All-pairs shortest paths</span></a></li><li class="subsection"><a href="#subsec:Modal-reasoning-Advertisement"><span class="toc-counter subsection"><span>8.5.6</span></span><span class="heading-text subsection">Modal reasoning: Advertisement</span></a></li><li class="section"><a href="#sec:Dependency-resolution-and-Startup"><span class="toc-counter section"><span>8.6</span></span><span class="heading-text section">Dependency resolution and lazy startup: Service presence</span></a></li><li class="section"><a href="#sec:RPC"><span class="toc-counter section"><span>8.7</span></span><span class="heading-text section">Transactions: RPC, Streams, Memoization</span></a></li><li class="section"><a href="#sec:Dataflow-and-reactive"><span class="toc-counter section"><span>8.8</span></span><span class="heading-text section">Dataflow and reactive programming</span></a></li><li class="part"><a href="#toc_IV"><span class="toc-counter part"><span>IV</span></span><span class="heading-text part">Reflection</span></a></li><li class="chapter"><a href="#CHAP:PATTERNS"><span class="toc-counter chapter"><span>9</span></span><span class="heading-text chapter">Evaluation: Patterns</span></a></li><li class="section"><a href="#toc_9.1"><span class="toc-counter section"><span>9.1</span></span><span class="heading-text section">Patterns</span></a></li><li class="section"><a href="#toc_9.2"><span class="toc-counter section"><span>9.2</span></span><span class="heading-text section">Eliminating and simplifying patterns</span></a></li><li class="section"><a href="#toc_9.3"><span class="toc-counter section"><span>9.3</span></span><span class="heading-text section">Simplification as key quality attribute</span></a></li><li class="section"><a href="#toc_9.4"><span class="toc-counter section"><span>9.4</span></span><span class="heading-text section">Event broadcast, the observer pattern and state replication</span></a></li><li class="section"><a href="#toc_9.5"><span class="toc-counter section"><span>9.5</span></span><span class="heading-text section">The state pattern</span></a></li><li class="section"><a href="#sec:The-cancellation-pattern"><span class="toc-counter section"><span>9.6</span></span><span class="heading-text section">The cancellation pattern</span></a></li><li class="section"><a href="#toc_9.7"><span class="toc-counter section"><span>9.7</span></span><span class="heading-text section">The demand-matcher pattern</span></a></li><li class="section"><a href="#toc_9.8"><span class="toc-counter section"><span>9.8</span></span><span class="heading-text section">Actor-language patterns</span></a></li><li class="chapter"><a href="#CHAP:PERFORMANCE"><span class="toc-counter chapter"><span>10</span></span><span class="heading-text chapter">Evaluation: Performance</span></a></li><li class="section"><a href="#sec:Cost-intuition"><span class="toc-counter section"><span>10.1</span></span><span class="heading-text section">Reasoning about routing time and delivery time</span></a></li><li class="section"><a href="#sec:Measuring-abstract-performance"><span class="toc-counter section"><span>10.2</span></span><span class="heading-text section">Measuring abstract <span class="small-caps">Syndicate</span> performance</span></a></li><li class="section"><a href="#sec:Concrete-performance"><span class="toc-counter section"><span>10.3</span></span><span class="heading-text section">Concrete <span class="small-caps">Syndicate</span> performance</span></a></li><li class="chapter"><a href="#CHAP:DISCUSSION"><span class="toc-counter chapter"><span>11</span></span><span class="heading-text chapter">Discussion</span></a></li><li class="section"><a href="#sec:Placing-PL-on-the-map"><span class="toc-counter section"><span>11.1</span></span><span class="heading-text section">Placing <span class="small-caps">Syndicate</span> on the map</span></a></li><li class="section"><a href="#toc_11.2"><span class="toc-counter section"><span>11.2</span></span><span class="heading-text section">Placing <span class="small-caps">Syndicate</span> in a wider context</span></a></li><li class="subsection"><a href="#toc_11.2.1"><span class="toc-counter subsection"><span>11.2.1</span></span><span class="heading-text subsection">Functional I/O</span></a></li><li class="subsection"><a href="#toc_11.2.2"><span class="toc-counter subsection"><span>11.2.2</span></span><span class="heading-text subsection">Functional operating systems</span></a></li><li class="subsection"><a href="#toc_11.2.3"><span class="toc-counter subsection"><span>11.2.3</span></span><span class="heading-text subsection">Process calculi</span></a></li><li class="subsection"><a href="#toc_11.2.4"><span class="toc-counter subsection"><span>11.2.4</span></span><span class="heading-text subsection">Formal actor models</span></a></li><li class="subsection"><a href="#toc_11.2.5"><span class="toc-counter subsection"><span>11.2.5</span></span><span class="heading-text subsection">Messaging middleware</span></a></li><li class="section"><a href="#sec:limitations"><span class="toc-counter section"><span>11.3</span></span><span class="heading-text section">Limitations and challenges</span></a></li><li class="chapter"><a href="#CHAP:CONCLUSION"><span class="toc-counter chapter"><span>12</span></span><span class="heading-text chapter">Conclusion</span></a></li><li class="section"><a href="#toc_12.1"><span class="toc-counter section"><span>12.1</span></span><span class="heading-text section">Review</span></a></li><li class="section"><a href="#toc_12.2"><span class="toc-counter section"><span>12.2</span></span><span class="heading-text section">Next steps</span></a></li><li class="appendix"><a href="#APPENDIX:PLJS-SYNTAX"><span class="toc-counter appendix"><span>A</span></span><span class="heading-text appendix"><span class="small-caps">Syndicate/js</span> Syntax</span></a></li><li class="appendix"><a href="#APPENDIX:IRC-CASE-STUDY"><span class="toc-counter appendix"><span>B</span></span><span class="heading-text appendix">Case study: IRC server</span></a></li><li class="appendix"><a href="#APPENDIX:POLYGLOT"><span class="toc-counter appendix"><span>C</span></span><span class="heading-text appendix">Polyglot <span class="small-caps">Syndicate</span></span></a></li><li class="appendix"><a href="#APPENDIX:DATAFLOW"><span class="toc-counter appendix"><span>D</span></span><span class="heading-text appendix">Racket Dataflow Library</span></a></li></ul></div></p></p>
<h2 id="x_0_0_0_0_1"><a name="toc_I"></a><span class="counter part"><span>I</span></span><span class="heading-text part">Background</span></h2><p id="x_1_0_0_0_22">
<h3 id="x_1_0_0_0_1"><a name="toc_1"></a><span class="counter chapter"><span>1</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:INTRODUCTION"></a><a name="CHAP:INTRODUCTION"></a>Introduction</span></h3><p id="x_1_0_0_0_2">Concurrency and its constant companions, communication and coordination, are ubiquitous in computing. From warehouse-sized datacenters through multi-processor operating systems to interactive or multi-threaded programs, coroutines, and even the humble function, every computation exists in some context and must exchange information with that context in a prescribed manner at a prescribed time. Functions receive inputs from and transmit outputs to their callers; impure functions may access or update a mutable store; threads update shared memory and transfer control via locks; and network services send and receive messages to and from their peers.</p><p id="x_1_0_0_0_3">Each of these acts of communication contributes to a shared understanding of the relevant knowledge required to undertake some task common to the involved parties. That is, the purpose of communication is to share state: to <em>replicate</em> information from peer to peer. After all, a communication that does not affect a receiver's view of the world literally has no effect. Put differently, each task shared by a group of components entails various acts of communication in the frame of an overall conversation, each of which conveys knowledge to components that need it. Each act of communication contributes to the overall <em>conversational state</em> involved in the shared task. Some of this conversational state relates to <em>what</em> must be or has been done; some relates to <em>when</em> it must be done. Traditionally, the “what” corresponds closely to “communication,” and the “when” to “coordination.”</p><p id="x_1_0_0_0_4">The central challenge in programming for a concurrent world is the <em>unpredictability</em> of a component's interactions with its context. Pure, total functions are the only computations whose interactions are completely predictable: a single value in leads to a terminating computation which yields a single value out. Introduction of effects such as non-termination, exceptions, or mutability makes function output unpredictable. Broadening our perspective to coroutines makes even the <em>inputs</em> to a component unpredictable: an input may arrive at an unexpected time or may not arrive at all. Threads may observe shared memory in an unexpected state, or may manipulate locks in an unexpected order. Networks may corrupt, discard, duplicate, or reorder messages; network services may delegate tasks to third parties, transmit out-of-date information, or simply never reply to a request.</p><p id="x_1_0_0_0_5">This seeming chaos is intrinsic: unpredictability is a defining characteristic of concurrency. To remove the one would eliminate the other. However, we shall not declare defeat. If we cannot eliminate harmful unpredictability, we may try to minimize it on one hand, and to cope with it on the other. We may seek a model of computation that helps programmers eliminate some forms of unpredictability and understand those that remain.</p><p id="x_1_0_0_0_6">To this end, I have developed new programming language design, <span class="small-caps">Syndicate</span>, which rests on a new model of concurrent computation, the <em>dataspace model</em>. In this dissertation I will defend the thesis that</p><p id="x_1_0_0_0_8">
<div class="thesisstatement" id="x_1_0_0_0_7"><span class="small-caps">Syndicate</span> provides a new, effective, realizable linguistic mechanism for sharing state in a concurrent setting.</div></p><p id="x_1_0_0_0_9">This claim must be broken down before it can be understood.</p>
<dl id="x_1_0_0_0_20"><dt id="x_1_0_0_0_10">Mechanism&nbsp;for&nbsp;sharing&nbsp;state.</dt><dd id="x_1_0_0_0_11"> The dataspace model is, at heart, a mechanism for sharing state among neighboring concurrent components. The design focuses on mechanisms for sharing state because effective mechanisms for communication and coordination follow as special cases. Chapter <a class="cross-reference" href="#CHAP:PHILOSOPHY-AND-OVERVIEW">2</a> motivates the <span class="small-caps">Syndicate</span> design, and chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> surveys a number of existing linguistic approaches to coordination and communication, outlining the multi-dimensional design space which results. Chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> then presents a vocabulary for and formal model of dataspaces along with basic correctness theorems.</dd><dt id="x_1_0_0_0_12">Linguistic&nbsp;mechanism.</dt><dd id="x_1_0_0_0_13"> The dataspace model, taken alone, explains communication and coordination among components but does not offer the programmer any assistance in structuring the internals of components. The full <span class="small-caps">Syndicate</span> design presents the primitives of the dataspace model to the programmer by way of new language constructs. These constructs extend the underlying programming language used to write a component, bridging between the language's own computational model and the style of interaction offered by the dataspace model. Chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> presents these new constructs along with an example of their application to a simple programming language. </dd><dt id="x_1_0_0_0_14">Realizability.</dt><dd id="x_1_0_0_0_15"> A design that cannot be implemented is useless; likewise an implementation that cannot be made performant enough to be fit-for-purpose. Chapter <a class="cross-reference" href="#CHAP:TUTORIAL">6</a> examines an example of the integration of the <span class="small-caps">Syndicate</span> design with an existing host language. Chapter <a class="cross-reference" href="#CHAP:IMPLEMENTATION">7</a> discusses the key data structures, algorithms, and implementation techniques that allowed construction of the two <span class="small-caps">Syndicate</span> prototypes, <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span>. </dd><dt id="x_1_0_0_0_16">Effectiveness.</dt><dd id="x_1_0_0_0_17"> Chapter <a class="cross-reference" href="#CHAP:IDIOMATIC-SYNDICATE">8</a> argues informally for the effectiveness of the programming model by explaining idiomatic <span class="small-caps">Syndicate</span> style through dissection of example protocols and programs. Chapter <a class="cross-reference" href="#CHAP:PATTERNS">9</a> goes further, arguing that <span class="small-caps">Syndicate</span> eliminates various<em> patterns</em> prevalent in concurrent programming, thereby <em>simplifying</em> programming tasks. Chapter <a class="cross-reference" href="#CHAP:PERFORMANCE">10</a> discusses the performance of the <span class="small-caps">Syndicate</span> design, first in terms of the needs of the programmer and second in terms of the actual measured characteristics of the prototype implementations.</dd><dt id="x_1_0_0_0_18">Novelty.</dt><dd id="x_1_0_0_0_19"> Chapter <a class="cross-reference" href="#CHAP:DISCUSSION">11</a> places <span class="small-caps">Syndicate</span> within the map sketched in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>, showing that it occupies a point in design space not covered by other models of concurrency.</dd></dl>
<div class="footnote" id="fn_1_1"><span class="counter footnote-counter"><span>1</span></span>That is, <span class="small-caps">Syndicate</span> does not yet address the issues of unreliable or congested media, uncontrollable latency or scheduling, or secure separation of powers familiar from Deutsch's “fallacies of distributed computing” <span class="citation citep">(<a class="citation" id="cite-2" href="#bib-RotemGalOz2006">Rotem-Gal-Oz 2006</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_1_0_0_0_21">Concurrency is ubiquitous in computing, from the very smallest scales to the very largest. This dissertation presents <span class="small-caps">Syndicate</span> as an approach to concurrency within a <em>non-distributed</em> program.<label class="footnote-number" for="fn_1_1">1</label> However, the design has consequences that may be of use in broader settings such as distributed systems, network architecture, or even operating system design. Chapter <a class="cross-reference" href="#CHAP:CONCLUSION">12</a> concludes the dissertation, sketching possible connections between <span class="small-caps">Syndicate</span> and these areas that may be examined more closely in future work.</p></p><p id="x_2_7_0_0_19">
<h3 id="x_2_0_0_0_1"><a name="toc_2"></a><span class="counter chapter"><span>2</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:PHILOSOPHY-AND-OVERVIEW"></a><a name="CHAP:PHILOSOPHY-AND-OVERVIEW"></a>Philosophy and Overview of the <span class="small-caps">Syndicate</span> Design</span></h3>
<blockquote id="x_2_0_0_0_5">
<p id="x_2_0_0_0_3">
<p class="align-right" id="x_2_0_0_0_2">Computer Scientists don't do philosophy.</p></p>
<p class="align-right" id="x_2_0_0_0_4">—Mitch Wand</p></blockquote><p id="x_2_0_0_0_6">Taking seriously the idea that concurrency is fundamentally about knowledge-sharing has consequences for programming language design. In this chapter I will explore the ramifications of the idea and outline a mechanism for communication among and coordination of concurrent components that stems directly from it.</p>
<div class="footnote" id="fn_2_2"><span class="counter footnote-counter"><span>2</span></span>This example reinforces the useful distinction of <em>concurrency</em> from <em>parallelism</em>: the former results when multiple independent ongoing activities exist; the latter, when more than one can be pursued <em>simultaneously</em>.<span class="plain-layout-boundary"></span></div><p id="x_2_0_0_0_7">Concurrency demands special support from our programming languages. Often specific communication mechanisms like message-passing or shared memory are baked in to a language. Sometimes additional coordination mechanisms such as locks, condition variables, or transactions are provided; in other cases, such as in the actor model, the chosen communication mechanisms double as coordination mechanisms. In some situations, the provided coordination mechanisms are even disguised: the event handlers of browser-based JavaScript programs are carefully sequenced by the system, showing that even sequential programming languages exhibit internal concurrency and must face issues arising from the unpredictability of the outside world.<label class="footnote-number" for="fn_2_2">2</label></p><p id="x_2_0_0_0_8">Let us step back from consideration of specific conversational mechanisms, and take a broader viewpoint. Seen from a distance, all these approaches to communication and coordination appear to be means to an end: namely, they are means by which <em>relevant knowledge</em> is shared among <em>cooperating components</em>. Knowledge-sharing is then simply the means by which they cooperate in performing their common task.</p><p id="x_2_0_0_0_9">Focusing on knowledge-sharing allows us to ask high-level questions that are unavailable to us when we consider specific communication and coordination mechanisms alone:</p>
<ol class="custom-label" id="x_2_0_0_0_13"><li id="x_2_0_0_0_10"><span class="custom-label">K1</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#Q-cooperation"></a><a name="Q-cooperation"></a>What does it mean to <em>cooperate</em> by sharing knowledge?</li><li id="x_2_0_0_0_11"><span class="custom-label">K2</span><a class="label-anchor" href="#Q-knowledge"></a><a name="Q-knowledge"></a>What general sorts of facts do components know?</li><li id="x_2_0_0_0_12"><span class="custom-label">K3</span><a class="label-anchor" href="#Q-interests"></a><a name="Q-interests"></a>What do they need to know to do their jobs?</li></ol><p id="x_2_0_0_0_14">It also allows us to frame the inherent unpredictability of concurrent systems in terms of knowledge. Unpredictability arises in many different ways. Components may crash, or suffer errors or exceptions during their operation. They may freeze, deadlock, enter unintentional infinite loops, or merely take an unreasonable length of time to reply. Their actions may interleave arbitrarily. New components may join and existing components may leave the group without warning. Connections to the outside world may fail. Demand for shared resources may wax and wane. Considering all these issues in terms of knowledge-sharing allows us to ask:</p>
<ol class="custom-label" id="x_2_0_0_0_17" start="4"><li id="x_2_0_0_0_15"><span class="custom-label">K4</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#Q-robust-sharing"></a><a name="Q-robust-sharing"></a>Which forms of knowledge-sharing are robust in the face of such unpredictability?</li><li id="x_2_0_0_0_16"><span class="custom-label">K5</span><a class="label-anchor" href="#Q-mitigate-unpredictability"></a><a name="Q-mitigate-unpredictability"></a>What knowledge helps the programmer mitigate such unpredictability?</li></ol><p id="x_2_0_0_0_18">Beyond the unpredictability of the operation of a concurrent system, the task the system is intended to perform can itself change in unpredictable ways. Unforeseen program change requests may arrive. New features may be invented, demanding new components, new knowledge, and new connections and relationships between existing components. Existing relationships between components may be altered. Again, our knowledge-sharing perspective allows us to raise the question:</p>
<ol class="custom-label" id="x_2_0_0_0_20" start="6"><li id="x_2_0_0_0_19"><span class="custom-label">K6</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#Q-robust-goal-change"></a><a name="Q-robust-goal-change"></a>Which forms of knowledge-sharing are robust to and help mitigate the impact of changes in the goals of a program?</li></ol><p id="x_2_0_0_0_21">In the remainder of this chapter, I will examine these questions generally and will outline <span class="small-caps">Syndicate</span>'s position on them in particular, concluding with an overview of the <span class="small-caps">Syndicate</span> approach to concurrency. We will revisit these questions in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> when we make a detailed examination of and comparison with other forms of knowledge-sharing embodied in various programming languages and systems.</p>
<h4 id="x_2_1_0_0_1"><a name="toc_2.1"></a><span class="counter section"><span>2.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Cooperating-by-sharing-knowledge"></a><a name="sec:Cooperating-by-sharing-knowledge"></a>Cooperating by sharing knowledge</span></h4><p id="x_2_1_0_0_2">We have identified conversation among concurrent components abstractly as a mechanism for knowledge-sharing, which itself is the means by which components work together on a common task. However, taken alone, the mere exchange of knowledge is insufficient to judge whether an interaction is cooperative, neutral, or perhaps even malicious. As programmers, we will frequently wish to orchestrate multiple components, all of which are under our control, to cooperate with each other. From time to time, we must equip our programs with the means for responding to non-cooperative, possibly-malicious interactions with components that are <em>not</em> under our control. To achieve these goals, an understanding of what it is to be cooperative is required.</p><p id="x_2_1_0_0_3">H. Paul Grice, a philosopher of language, proposed the <em>cooperative principle</em> of conversation in order to make sense of the meanings people derive from utterances they hear:</p>
<dl id="x_2_1_0_0_6"><dt id="x_2_1_0_0_4">Cooperative&nbsp;Principle&nbsp;(CP).</dt><dd id="x_2_1_0_0_5"> Make your conversational contribution such as is required, at the stage at which it occurs, by the accepted purpose or direction of the talk exchange in which you are engaged. <span class="citation citep">(<a class="citation" id="cite-3" href="#bib-Grice1975">Grice 1975</a>)</span></dd></dl>
<figure id="x_2_1_0_0_27"><a name="fig:Grice's-Conversational-Maxims"></a>
<dl id="x_2_1_0_0_26"><dt id="x_2_1_0_0_7">Quantity.</dt><dd id="x_2_1_0_0_11">
<ol id="x_2_1_0_0_10"><li id="x_2_1_0_0_8">Make your contribution as informative as required (for the current purposes of the exchange).</li><li id="x_2_1_0_0_9">Do not make your contribution more informative than is required.</li></ol></dd><dt id="x_2_1_0_0_12">Quality.</dt><dd id="x_2_1_0_0_16"> Try to make your contribution one that is true.
<ol id="x_2_1_0_0_15"><li id="x_2_1_0_0_13">Do not say what you believe to be false.</li><li id="x_2_1_0_0_14">Do not say that for which you lack adequate evidence.</li></ol></dd><dt id="x_2_1_0_0_17">Relation.</dt><dd id="x_2_1_0_0_18"> Be relevant.</dd><dt id="x_2_1_0_0_19">Manner.</dt><dd id="x_2_1_0_0_25"> Be perspicuous.
<ol id="x_2_1_0_0_24"><li id="x_2_1_0_0_20">Avoid obscurity of expression.</li><li id="x_2_1_0_0_21">Avoid ambiguity.</li><li id="x_2_1_0_0_22">Be brief (avoid unnecessary prolixity).</li><li id="x_2_1_0_0_23">Be orderly.</li></ol></dd></dl><figcaption><span class="counter figure"><span>1</span></span><span class="figcaption-text"><span class="lyx-argument">Grice's Conversational Maxims<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Grice's-Conversational-Maxims"></a>Grice's Conversational Maxims <span class="citation citep">(<a class="citation" id="cite-4" href="#bib-Grice1975">Grice 1975</a>)</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_2_3"><span class="counter footnote-counter"><span>3</span></span>As opposed to other kinds of maxims, “aesthetic, social, or moral in nature” <span class="citation citep">(<a class="citation" id="cite-5" href="#bib-Grice1975">Grice 1975</a> <span class="citation-after">p. 47</span>)</span><span class="plain-layout-boundary"></span></div><p id="x_2_1_0_0_28">He further proposed four <em>conversational maxims<label class="footnote-number" for="fn_2_3">3</label></em> as corollaries to the CP, presented in figure <a class="cross-reference" href="#fig:Grice's-Conversational-Maxims">1</a>. It is important to note the character of these maxims:</p>
<blockquote id="x_2_1_0_0_30">
<p id="x_2_1_0_0_29">They are not sociological generalizations about speech, nor they are moral prescriptions or proscriptions on what to say or communicate. Although Grice presented them in the form of guidelines for how to communicate successfully, I think they are better construed as presumptions about utterances, presumptions that we as listeners rely on and as speakers exploit. <span class="citation citep">(<a class="citation" id="cite-6" href="#bib-Bach2005">Bach 2005</a>)</span></p></blockquote><p id="x_2_1_0_0_31">Grice's principle and maxims can help us tackle question <a class="cross-reference" href="#Q-cooperation">K1</a> in two ways. First, they can be read directly as constructive advice for designing conversational protocols for cooperative interchange of information. Second, they can attune us to particular families of design mistakes in such protocols that result from cases in which these “presumptions” are invalid. This can in turn help us come up with guidelines for protocol design that help us avoid such mistakes. Thus, we may use these maxims to judge a given protocol among concurrent components, asking ourselves whether each communication that a component makes lives up to the demands of each maxim.</p><p id="x_2_1_0_0_32">Grice introduces various ways of failing to fulfill a maxim, and their consequences:</p>
<ol id="x_2_1_0_0_37"><li id="x_2_1_0_0_33">Unostentatious violation of a maxim, which can mislead peers.</li><li id="x_2_1_0_0_34">Explicit opting-out of participation in a maxim or even the Cooperative Principle in general, making plain a deliberate lack of cooperation.</li><li id="x_2_1_0_0_35">Conflict between maxims: for example, there may be tension between speaking some necessary (Quantity(1)) truth (Quality(1)), and a lack of evidence in support of it (Quality(2)), which may lead to shaky conclusions down the line.</li><li id="x_2_1_0_0_36"><em>Flouting</em> of a maxim: blatant, obviously deliberate violation of a conversational maxim, which “<em>exploits</em>” the maxim, with the intent to force a hearer out of the usual frame of the conversation and into an analysis of some higher-order conversational context.</li></ol><p id="x_2_1_0_0_38">Many, but not all, of these can be connected to analogous features of computer communication protocols. In this dissertation, I am primarily assuming a setting involving components that deliberately <em>aim</em> to cooperate. We will not dwell on deliberate violation of conversational maxims. However, we will from time to time see that consideration of <em>accidental</em> violation of conversational maxims is relevant to the design and analysis of computer protocols. For example, Grice writes that</p>
<blockquote id="x_2_1_0_0_40">
<p id="x_2_1_0_0_39">[the] second maxim [of Quantity] is disputable; it might be said that to be overinformative is not a transgression of the [Cooperative Principle] but merely a waste of time. However, it might be answered that such overinformativeness may be confusing in that it is liable to raise side issues; and there may also be an indirect effect, in that the hearers may be misled as a result of thinking that there is some particular <em>point</em> in the provision of the excess of information. <span class="citation citep">(<a class="citation" id="cite-7" href="#bib-Grice1975">Grice 1975</a>)</span></p></blockquote><p id="x_2_1_0_0_41">This directly connects to (perhaps accidental) excessive bandwidth use (“waste of time”) as well as programmer errors arising from exactly the misunderstanding that Grice describes.</p><p id="x_2_1_0_0_42">It may seem surprising to bring ideas from philosophy of language to bear in the setting of cooperating concurrent computerized components. However, Grice himself makes the connection between his specific conversational maxims and “their analogues in the sphere of transactions that are not talk exchanges,” drawing on examples of shared tasks such as cooking and car repair, so it does not seem out of place to apply them to the design and analysis of our <em>conversational </em>computer protocols. This is particularly the case in light of Grice's ambition to explain the Cooperative Principle as “something that it is <em>reasonable</em> for us to follow, that we <em>should not</em> abandon.” <span class="citation citep">(<a class="citation" id="cite-8" href="#bib-Grice1975">Grice 1975</a> <span class="citation-after">p. 48; emphasis in original</span>)</span></p>
<div class="footnote" id="fn_2_4"><span class="counter footnote-counter"><span>4</span></span>See also <span class="citation citet"><a class="citation" id="cite-10" href="#bib-Dunn"><span>Dunn<span class="parens"> (</span>2017<span class="parens">)</span></span></a></span> who places Kitcher's work in a wider context.<span class="plain-layout-boundary"></span></div><p id="x_2_1_0_0_43">The CP makes mention of the “purpose or direction” of a given conversation. We may view the fulfillment of the task shared by the group of collaborating components as the purpose of the conversation. Each individual component in the group has its own role to play and, therefore, its own “personal” goals in working toward successful completion of the shared task. <span class="citation citet"><a class="citation" id="cite-9" href="#bib-Kitcher1990"><span>Kitcher<span class="parens"> (</span>1990<span class="parens">)</span></span></a></span>, writing in the context of the social structure of scientific collaboration, introduces the notions of <em>personal</em> and <em>impersonal epistemic intention</em>.<label class="footnote-number" for="fn_2_4">4</label> We may adapt these ideas to our setting, explicitly drawing out the notion of a role within a conversational protocol. A cooperative component “wishes” for the group as a whole to succeed: this is its “impersonal” epistemic intention. It also has goals for itself, “personal” epistemic intentions, namely to successfully perform its roles within the group.</p><p id="x_2_1_0_0_44">Finally, the CP is a specific example of the general idea of <em>epistemic reasoning</em>, logical reasoning incorporating knowledge and beliefs about one's own knowledge and beliefs, and about the knowledge and beliefs of other parties <span class="citation citep">(<a class="citation" id="cite-11" href="#bib-Fagin2004">Fagin et al. 2004</a>; <a class="citation" id="cite-12" href="#bib-sep-logic-epistemic">Hendricks and Symons 2015</a>; <a class="citation" id="cite-13" href="#bib-VanDitmarsch">van Ditmarsch, van der Hoek and Kooi 2017</a>)</span>. However, epistemic reasoning has further applications in the design of conversational protocols among concurrent components, which brings us to our next topic.</p>
<h4 id="x_2_2_0_0_1"><a name="toc_2.2"></a><span class="counter section"><span>2.2</span></span><span class="heading-text section">Knowledge types and knowledge flow</span></h4><p id="x_2_2_0_0_2">The conversational state that accumulates as part of a collaboration among components can be thought of as a collection of facts. First, there are those facts that define the <em>frame</em> of a conversation. These are exactly the facts that identify the task at hand; we label them “framing knowledge”, and taken together, they are the “conversational frame” for the conversation whose purpose is completion of a particular shared task. Just as tasks can be broken down into more finely-focused subtasks, so can conversations be broken down into sub-conversations. In these cases, part of the conversational state of an overarching interaction will describe a frame for each sub-conversation, within which corresponding sub-conversational state exists. The knowledge framing a conversation acts as a bridge between it and its wider context, defining its “purpose” in the sense of the CP. Figure <a class="cross-reference" href="#fig:conversational-structure">2</a> schematically depicts these relationships.</p><p id="x_2_2_0_0_3">Some facts define conversational frames, but <em>every</em> shared fact is contextualized <em>within</em> some conversational frame. Within a frame, then, some facts will pertain directly to the task at hand. These, we label “domain knowledge”. Generally, such facts describe global aspects of the common problem that remain valid as we shift our perspective from participant to participant. Other facts describe the knowledge or beliefs of particular components. These, we label “epistemic knowledge”.</p>
<figure id="x_2_2_0_0_6"><a name="fig:conversational-structure"></a>
<p class="align-center" id="x_2_2_0_0_5"><img id="x_2_2_0_0_4" src="Figures/conversation.svg"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>2</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:conversational-structure"></a>Components, tasks, and conversational structure<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_2_5"><span class="counter footnote-counter"><span>5</span></span>Is the receiver telling the truth, or has it been discarding the received data, falsely acknowledging safe receipt of it? This is where the Cooperative Principle comes in. Acting as if the transmitter's beliefs are in fact knowledge trusts that the receiver is properly cooperating.<span class="plain-layout-boundary"></span></div><p id="x_2_2_0_0_7">For example, as a file transfer progresses, the actual content of the file does not change: it remains a global fact that byte number 300 (say) has value 255, no matter whether the transfer has reached that position or not. The content of the file is thus “domain knowledge”. However, as the transfer proceeds and acknowledgements of receipt stream from the recipient to the transmitter, the transmitter's beliefs<em> </em>about the receiver's knowledge change. Each successive acknowledgement leads the transmitter to believe that the receiver has learned a little more of the file's content. Information on the progress of the transfer is thus “epistemic knowledge”.<label class="footnote-number" for="fn_2_5">5</label></p>
<div class="footnote" id="fn_2_6"><span class="counter footnote-counter"><span>6</span></span>The fact of a “need to know” is also perhaps a form of epistemic knowledge, as it expresses a claim about the knowledge of a particular component: namely, that it does <em>not</em> know some specific thing or things.<span class="plain-layout-boundary"></span></div><p id="x_2_2_0_0_8">If domain knowledge is “what is true in the world”, and epistemic knowledge is “who knows what”, the third piece of the puzzle is “who <em>needs</em> to know what” in order to effectively make a contribution to the shared task at hand. We will use the term “interests” as a name for those facts that describe knowledge that a component needs to learn. Knowledge of the various interests in a group allows collaborators to plan their communication acts according to the needs of individual components and the group as a whole. In conversations among people, interests are expressed as <em>questions</em>; in a computational setting, they are conveyed by <em>requests</em>, <em>queries</em>, or <em>subscriptions</em>.<label class="footnote-number" for="fn_2_6">6</label></p><p id="x_2_2_0_0_9">The interests of components in a concurrent system thus direct the flow of knowledge within the system. The interests of a group may be constant, or may vary with time.</p><p id="x_2_2_0_0_10">When interest is fixed, remaining the same for a certain class of shared task, the programmer can plan paths for communication up front. For example, in the context of a single TCP connection, the interests of the two parties involved are always the same: each peer wishes to learn what the other has to say. As a consequence, libraries implementing TCP can bake in the assumption that clients will wish to access received data. As another example, a programmer charged with implementing a request counter in a web server may choose to use a simple global integer variable, safe in the knowledge that the only possible item of interest is the current value of the counter.</p>
<div class="footnote" id="fn_2_7"><span class="counter footnote-counter"><span>7</span></span>This perspective lines up very well with the Cooperative Principle, in that an expressed interest—a question or query—strongly suggests an immediately relevant, appropriate, required conversational contribution.<span class="plain-layout-boundary"></span></div><p id="x_2_2_0_0_11">A changing, dynamic set of interests, however, demands development of a vocabulary for communicating changes in interest during a conversation. For example, the query language of a SQL database is just such a vocabulary. The server's initial interest is in <em>what the client is interested in</em>, and is static, but the client's own interests vary with each request, and must be conveyed anew in the context of each separate interaction. Knowledge <em>about</em> dynamically-varying interests allows a group of collaborating components to change its interaction patterns on the fly.<label class="footnote-number" for="fn_2_7">7</label></p><p id="x_2_2_0_0_12">With this ontology in hand, we may answer questions <a class="cross-reference" href="#Q-knowledge">K2</a> and <a class="cross-reference" href="#Q-interests">K3</a>. Each task is delimited by a conversational frame. Within that frame, components share knowledge related to the domain of the task at hand, and knowledge related to the knowledge, beliefs, needs, and interests of the various participants in the collaborative group. Conversations are recursively structured by shared knowledge of (sub-)conversational frames, defined in terms of any or all of the types of knowledge we have discussed. Some conversations take place at different levels within a larger frame, bridging between tasks and their subtasks. Components are frequently engaged in multiple tasks, and thus often participate in multiple conversations at once. The knowledge a component needs to do its job is provided to it when it is created, or later supplied to it in response to its interests.</p>
<h4 id="x_2_3_0_0_1"><a name="toc_2.3"></a><span class="counter section"><span>2.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Unpredictability-at-run-time"></a><a name="sec:Unpredictability-at-run-time"></a>Unpredictability at run-time</span></h4><p id="x_2_3_0_0_2">A full answer to question <a class="cross-reference" href="#Q-robust-sharing">K4</a> must wait until the survey of communication and coordination mechanisms of chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>. However, this dissertation will show that at least one form of knowledge-sharing, the <span class="small-caps">Syndicate</span> design, encourages robust handling of many kinds of concurrency-related unpredictability.</p><p id="x_2_3_0_0_3">The epistemological approach we have taken to questions <a class="cross-reference" href="#Q-cooperation">K1</a><a class="cross-reference" href="#Q-interests">K3</a> suggests some initial steps toward an answer to question <a class="cross-reference" href="#Q-mitigate-unpredictability">K5</a>. In order for a program to be robust in the face of unpredictable events, it must first be able to detect these events, and second be able to muster an appropriate response to them. Certain kinds of events can be reliably detected and signaled, such as component crashes and exceptions, and arrivals and departures of components in the group. Others cannot easily be detected reliably, such as nontermination, excessive slowness, or certain kinds of deadlock and datalock. Half-measures such as use of timeouts must suffice for the latter sort. Still other kinds of unpredictability such as memory races or message races may be explicitly worked around via careful protocol design, perhaps including information tracking causality or provenance of a piece of knowledge or arranging for extra coordination to serialize certain sensitive operations.</p><p id="x_2_3_0_0_4">No matter the source of the unpredictability, once detected it must be signaled to interested parties. Our epistemic, knowledge-sharing focus allows us to treat the <em>facts</em> of an unpredictable event as knowledge within the system. Often, such a fact will have an epistemic consequence. For example, learning that a component has crashed will allow us to discount any partial results we may have learned from it, and to discard any records we may have been keeping of the state of the failed component itself. Generally speaking, an epistemological perspective can help each component untangle intact from damaged or potentially untrustworthy pieces of knowledge. Having classified its records into “salvageable” and “unrecoverable”, it may discard items as necessary and engage with the remaining portion of the group in actions to repair the damage and continue toward the ultimate goal.</p><p id="x_2_3_0_0_5">One particular strategy is to retry a failed action. Consideration of the <em>roles</em> involved in a shared task can help determine the scope of the action to retry. For example, the idea of <em>supervision</em> that features so prominently in Erlang programming <span class="citation citep">(<a class="citation" id="cite-14" href="#bib-Armstrong2003">Armstrong 2003</a>)</span> is to restart entire failing components from a specification of their roles. Here, consideration of the epistemic intentions of components can be seen to help the programmer design a system robust to certain forms of unpredictable failure.</p>
<h4 id="x_2_4_0_0_1"><a name="toc_2.4"></a><span class="counter section"><span>2.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Unpredictability-in-design"></a><a name="sec:Unpredictability-in-design"></a>Unpredictability in the design process</span></h4><p id="x_2_4_0_0_2">Programs are seldom “finished”. Change must be accommodated at every stage of a program's life cycle, from the earliest phases of development to, in many cases, long after a program is deployed. When concurrency is involved, such change often involves emendations to protocol definitions and shifts in the roles and relationships within a group of components. Just as with question <a class="cross-reference" href="#Q-robust-sharing">K4</a>, a full examination of question <a class="cross-reference" href="#Q-robust-goal-change">K6</a> must wait for chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>. However, approaching the question in the abstract, we may identify a few desirable characteristics of linguistic support for concurrent programming.</p><p id="x_2_4_0_0_3">First, debugging of concurrent programs can be extremely difficult. A language should have tools for helping programmers gain insight into the intricacies of the interactions among each program's components. Such tools depend on information gleaned from the knowledge-sharing mechanism of the language. As such, a mechanism that generates trace information that matches the mental model of the programmer is desirable.</p><p id="x_2_4_0_0_4">Second, changes to programs often introduce new interactions among existing components. A knowledge-sharing mechanism should allow for straightforward composition of pieces of program code describing (sub)conversations that a component is to engage in. It should be possible to introduce an existing component to a new conversation without heavy revision of the code implementing the conversations the component already supports.</p><p id="x_2_4_0_0_5">Finally, service programs must often run for long periods of time without interruption. In cases where new features or important bug-fixes must be introduced, it is desirable to be able to replace or upgrade program components without interrupting service availability. Similar concerns arise even for user-facing graphical applications, where upgrades to program code must preserve various aspects of program state and configuration across the change. </p>
<h4 id="x_2_5_0_0_1"><a name="toc_2.5"></a><span class="counter section"><span>2.5</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Syndicate's-approach-to-concurrency"></a><a name="sec:Syndicate's-approach-to-concurrency"></a><span class="small-caps">Syndicate</span>'s approach to concurrency</span></h4><p id="x_2_5_0_0_2"><span class="small-caps">Syndicate</span> places knowledge front and center in its design in the form of <em>assertions</em>. An assertion is a representation of an item of knowledge that one component wishes to communicate to another. Assertions may represent framing knowledge, domain knowledge, and epistemic knowledge, as a component sees fit. Each component in a group exists within a <em>dataspace</em> which both keeps track of the group's current set of assertions and schedules execution of its constituent components. Components add and remove assertions from the dataspace freely, and the dataspace ensures that components are kept informed of <em>relevant</em> assertions according to their <em>declared interests</em>.</p><p id="x_2_5_0_0_3">In order to perform this task, <span class="small-caps">Syndicate</span> dataspaces place just one constraint on the interpretation of assertions: there must exist, in a dataspace implementation, a distinct piece of syntax for constructing assertions that will mean <em>interest in some other assertion</em>. For example, if “the color of the boat is blue” is an assertion, then so is “there exists some interest in the color of the boat being blue”. A component that asserts interest in a set of other assertions will be kept informed as members of that set appear and disappear in the dataspace through the actions of the component or its peers.</p>
<div class="footnote" id="fn_2_8"><span class="counter footnote-counter"><span>8</span></span>We defer selection of a specific universe of assertions to chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_4"><span class="small-caps">Syndicate</span> makes extensive use of <em>wildcards</em> for generating large—in fact, often infinite—sets of assertions. For example, “interest in the color of the boat being anything at all” is a valid and useful set of assertions, generated from a piece of syntax with a wildcard marker in the position where a specific color would usually reside. Concretely, we might write <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{color}(\mathit{boat},\star))$</span>, which generates the set of assertions <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{color}(\mathit{boat},x))$</span>, with <span class="lyx-mathjax mathjax-inline">$x$</span> ranging over the entire universe of assertions.<label class="footnote-number" for="fn_2_8">8</label></p>
<div class="footnote" id="fn_2_9"><span class="counter footnote-counter"><span>9</span></span>Assertions thus have an additional, intrinsic epistemic character: the existence of an assertion implies the existence of an asserter.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_5">The design of the dataspace model thus far seems similar to the tuplespace model <span class="citation citep">(<a class="citation" id="cite-15" href="#bib-Gelernter1985">Gelernter 1985</a>; <a class="citation" id="cite-16" href="#bib-Gelernter1992">Gelernter and Carriero 1992</a>; <a class="citation" id="cite-17" href="#bib-Carriero1994">Carriero et al. 1994</a>)</span>. There are two vital distinctions. The first is that tuples in the tuplespace model are “generative”, taking on independent existence once placed in the shared space, whereas assertions in the dataspace model are not. Assertions in a dataspace never outlive the component that is currently asserting them;<label class="footnote-number" for="fn_2_9">9</label> when a component terminates, <em>all its assertions are retracted</em> from the shared space. This occurs whether termination was normal or the result of a crash or an exception. The second key difference is that multiple <em>copies</em> of a particular tuple may exist in a tuplespace, while redundant assertions in a dataspace cannot be distinguished by observers. If two components separately place an assertion <span class="lyx-mathjax mathjax-inline">$x$</span> into their common dataspace, a peer that has previously asserted interest in <span class="lyx-mathjax mathjax-inline">$x$</span> is informed merely that <span class="lyx-mathjax mathjax-inline">$x$</span> has been asserted, not <em>how many times</em> it has been asserted. If one redundant assertion of <span class="lyx-mathjax mathjax-inline">$x$</span> is subsequently withdrawn, the observer will not be notified; only when every assertion of <span class="lyx-mathjax mathjax-inline">$x$</span> is retracted is the observer notified that <span class="lyx-mathjax mathjax-inline">$x$</span> is no longer present in the dataspace. Observers are shown only a <em>set</em> view on an underlying <em>bag</em> of assertions. In other words, producing a tuple is non-idempotent, while making an assertion is idempotent.</p><p id="x_2_5_0_0_6">Even more closely related is the <em>fact space model</em> <span class="citation citep">(<a class="citation" id="cite-18" href="#bib-Mostinckx2007">Mostinckx et al. 2007</a>; <a class="citation" id="cite-19" href="#bib-Mostinckx2008a">Mostinckx, Lombide Carreton and De Meuter 2008</a>)</span>, an approach to middleware for connecting programs in mobile networks. The model is based on an underlying tuplespace, interpreting tuples as <em>logical facts</em> by working around the generativity and poor fault-tolerance properties of the tuplespace mechanism in two ways. First, tuples are recorded alongside the identity of the program that produced them. This provenance information allows tuples to be removed when their producer crashes or is otherwise disconnected from the network. Second, tuples can be interpreted in an idempotent way by programs. This allows programs to ignore redundant tuples, recovering a set view from the bag of tuples they observe. While the motivations and foundations of the two works differ, in many ways the dataspace and fact space models address similar concerns. Conceptually, the dataspace model can be viewed as an adaptation and integration of the fact space model into a programming language setting. The fact space model focuses on scaling <em>up</em> to distributed systems, while our focus is instead on a mechanism that scales <em>down</em> to concurrency in the small. In addition, the dataspace model separates itself from the fact space model in its explicit, central epistemic constructions and its emphasis on conversational frames.</p><p id="x_2_5_0_0_7">The dataspace model maintains a strict isolation between components in a dataspace, forcing all interactions between peers through the shared dataspace. Components access and update the dataspace solely via message passing. Shared memory in the sense of multi-threaded models is ruled out. In this way, the dataspace model seems similar to the actor model <span class="citation citep">(<a class="citation" id="cite-20" href="#bib-Hewitt1973">Hewitt, Bishop and Steiger 1973</a>; <a class="citation" id="cite-21" href="#bib-Agha1986">Agha 1986</a>; <a class="citation" id="cite-22" href="#bib-Agha1997">Agha et al. 1997</a>; <a class="citation" id="cite-23" href="#bib-DeKoster2016">De Koster et al. 2016</a>)</span>. The core distinction between the models is that components in the dataspace model communicate <em>indirectly</em> by making and retracting assertions in the shared store which are observed by other components, while actors in the actor model communicate <em>directly</em> by exchange of messages which are addressed to other actors. Assertions in a dataspace are routed according to the intersection between sets of assertions and sets of asserted <em>interests</em> in assertions, while messages in the actor model are each routed to an explicitly-named target actor.</p><p id="x_2_5_0_0_8">The similarities between the dataspace model and the actor, tuplespace, and fact space models are strong enough that we borrow terminology from them to describe concepts in <span class="small-caps">Syndicate</span>. Specifically, we borrow the term “actor” to denote a <span class="small-caps">Syndicate</span> component. What the actor model calls a “configuration” we fold into our idea of a “dataspace”, a term which also denotes the shared knowledge store common to a group of actors. The term “dataspace” itself was chosen to highlight this latter denotation, making a connection to fact spaces and tuplespaces.</p><p id="x_2_5_0_0_9">We will touch again on the similarities and differences among these models in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>, examining details in chapter <a class="cross-reference" href="#CHAP:DISCUSSION">11</a>. In the remainder of this subsection, let us consider <span class="small-caps">Syndicate</span>'s relationship to questions <a class="cross-reference" href="#Q-cooperation">K1</a><a class="cross-reference" href="#Q-robust-goal-change">K6</a>.</p>
<h6 class="unnumbered" id="x_2_5_0_0_10"><a name="toc_2.5"></a><span class="heading-text paragraph">Cooperation, knowledge &amp; conversation.</span></h6><p id="x_2_5_0_0_11">The <span class="small-caps">Syndicate</span> design takes questions <a class="cross-reference" href="#Q-cooperation">K1</a><a class="cross-reference" href="#Q-interests">K3</a> to heart, placing them at the core of its choice of sharing mechanism and the concomitant approach to protocol design. Actors exchange knowledge encoded as assertions via a shared dataspace. <em>All</em> shared state in a <span class="small-caps">Syndicate</span> program is represented as assertions: this includes domain knowledge, epistemic knowledge, and frame knowledge. Key to <span class="small-caps">Syndicate</span>'s functioning is the use of a special form of epistemic knowledge, namely assertions of interest. It is these assertions that drive knowledge <em>flow</em> in a program from parties asserting some fact to parties asserting interest in that fact.</p>
<div class="footnote" id="fn_2_10"><span class="counter footnote-counter"><span>10</span></span>In linguistics, `pragmatics' means something slightly different to its meaning in the field of programming languages:<span class="plain-layout-boundary"></span>
<blockquote id="x_2_5_0_0_13">
<p id="x_2_5_0_0_12">Pragmatics is sometimes characterized as dealing with the effects of context [...] if one collectively refers to all the facts that can vary from utterance to utterance as context. <span class="citation citep">(<a class="citation" id="cite-24" href="#bib-sep-pragmatics">Korta and Perry 2015</a>)</span></p></blockquote><span class="citation citet"><a class="citation" id="cite-25" href="#bib-Mey2001"><span>Mey<span class="parens"> (</span>2001<span class="parens">)</span></span></a></span> defines pragmatics as the subfield of linguistics which “studies the use of language in human communication as determined by the conditions of society”. Broadening its scope to include <em>computer</em> languages in <em>software</em> communication as determined by the conditions of <em>the system as a whole</em> takes us into a somewhat speculative area.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_14">Viewing an interaction among actors as a <em>conversation</em> and shared assertions as <em>conversational state</em> allows programmers to employ the linguistic tools discussed in section <a class="cross-reference" href="#sec:Cooperating-by-sharing-knowledge">2.1</a>, taking steps toward a pragmatics of computer protocols.<label class="footnote-number" for="fn_2_10">10</label> <span class="small-caps">Syndicate</span> encourages programmers to design conversational protocols directly in terms of roles and to map conversational contributions onto the assertion and retraction of assertions in the shared space. Grice's maxims offer high-level guidance for defining the meaning of each assertion: the maxims of quantity guide the design of the individual records included in each assertion; those of quality and relevance help determine the criteria for when an assertion should be made and when it should be retracted; and those of manner shape a vocabulary of primitive assertions with precisely-defined meanings that <em>compose</em> when simultaneously expressed to yield complex derived meanings.</p><p id="x_2_5_0_0_15"><span class="small-caps">Syndicate</span>'s assertions of interest determine the movement of knowledge in a system. They define, in effect, the set of facts an actor is “listening” for. All communication mechanisms must have some equivalent feature, used to route information from place to place. Unusually, however, <span class="small-caps">Syndicate</span> allows actors to <em>react to</em> these assertions of interest, in that assertions of interest are ordinary assertions like any other. Actors may act based on their <em>knowledge</em> of the way knowledge moves in a system by expressing interest in interest and deducing <em>implicatures</em> from the discovered facts. <span class="citation citet"><a class="citation" id="cite-26" href="#bib-Mey2001"><span>Mey<span class="parens"> (</span>2001<span class="parens">)</span></span></a></span> defines a <em>conversational implicature</em> as “something which is implied in conversation, that is, something which is left implicit in actual language use.” <span class="citation citet"><a class="citation" id="cite-27" href="#bib-Grice1975"><span>Grice<span class="parens"> (</span>1975<span class="parens">)</span></span></a></span> makes three statements helpful in pinning down the idea of conversational implicature: 1. “To assume the presence of a conversational implicature, we have to assume that at least the Cooperative Principle is being observed.” 2. “Conversational implicata are not part of the meaning of the expressions to the employment of which they attach.” This is what distinguishes <em>implicature</em> from <em>implication</em>. 3. “To calculate a conversational implicature is to calculate what has to be supposed in order to preserve the supposition that the Cooperative Principle is being observed.”</p>
<div class="footnote" id="fn_2_11"><span class="counter footnote-counter"><span>11</span></span>See section <a class="cross-reference" href="#sec:RPC">8.7</a> for more on “procedure calls” and associated resource management.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_2_12"><span class="counter footnote-counter"><span>12</span></span>The semantic meaning of the assertion is general across <span class="small-caps">Syndicate</span> programs: interest in an assertion has a fixed meaning <em>to <span class="small-caps">Syndicate</span></em> no matter the domain of the protocol concerned. Implicatures deduced from assertions, however, have meaning only within a specific protocol.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_16">For example, imagine an actor <span class="lyx-mathjax mathjax-inline">$F$</span> responsible for answering questions about factorials. The assertion <span class="lyx-mathjax mathjax-inline">$\mathit{fact}(8,40320)$</span> means that the factorial of <span class="lyx-mathjax mathjax-inline">$8$</span> is <span class="lyx-mathjax mathjax-inline">$40320$</span>. If <span class="lyx-mathjax mathjax-inline">$F$</span> learns that some peer has asserted <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{fact}(8,\star))$</span>, which is to be interpreted as interest in the set of facts describing all <em>potential</em> answers to the question “what is the factorial of <span class="lyx-mathjax mathjax-inline">$8$</span>?,” it can act on this knowledge to compute a suitable answer and can then assert <span class="lyx-mathjax mathjax-inline">$\mathit{fact}(8,40320)$</span> in response. Once it learns that interest in the factorial of <span class="lyx-mathjax mathjax-inline">$8$</span> is no longer present in the group, it can retract its own assertion and release the corresponding storage resources.<label class="footnote-number" for="fn_2_11">11</label> Knowledge of interest in a topic acts as a signal of <em>demand</em> for some resource: here, computation (directly) and storage (indirectly). The raw fact of the interest itself has the direct semantic meaning “please convey to me any assertions matching this pattern”, but has an indirect, unspoken, pragmatic meaning—an implicature—in our imagined protocol of <em>“please compute the answer to this question.”</em><label class="footnote-number" for="fn_2_12">12</label></p><p id="x_2_5_0_0_17">The idea of implicature finds use beyond assertions of interest. For example, the process of deducing an implicature may be used to reconstruct temporarily- or permanently-unavailable information “from context,” based on the underlying assumption that the parties involved are following the Cooperative Principle. For example, a message describing successful fulfillment of an order carries an implicature of the existence of the order. A hearer of the message may infer the order's existence on this basis. Similarly, a reply implicates the existence of a request.</p><p id="x_2_5_0_0_18">Finally, the mechanism that <span class="small-caps">Syndicate</span> provides for conveying assertions from actor to actor via the dataspace allows reasoning about <em>common knowledge</em> <span class="citation citep">(<a class="citation" id="cite-28" href="#bib-Fagin2004">Fagin et al. 2004</a>)</span>. An actor placing some assertion into the dataspace knows both that all interested peers will automatically learn of the assertion and that each such peer <em>knows</em> that all others will learn of the assertion. Providing this guarantee at the language level encourages the use of epistemic reasoning in protocol design while avoiding the risks of implementing the necessary state-management substrate by hand.</p>
<h6 class="unnumbered" id="x_2_5_0_0_19"><a name="toc_2.5"></a><span class="heading-text paragraph">Run-time unpredictability.</span></h6><p id="x_2_5_0_0_20">Recall from section <a class="cross-reference" href="#sec:Unpredictability-at-run-time">2.3</a> that robust treatment of unpredictability requires that we must be able to either detect and respond to or forestall the occurrence of the various unpredictable situations inherent to concurrent programming. The dataspace model is the foundation of <span class="small-caps">Syndicate</span>'s approach to questions <a class="cross-reference" href="#Q-robust-sharing">K4</a> and <a class="cross-reference" href="#Q-mitigate-unpredictability">K5</a>, offering a means for signaling and detection of such events. However, by itself the dataspace model is not enough. The picture is completed with linguistic features for structuring state and control flow within each individual actor. These features allow programmers to concisely express appropriate responses to unexpected events. Finally, <span class="small-caps">Syndicate</span>'s knowledge-based approach suggests techniques for protocol design which can help avoid certain forms of unpredictability by construction.</p><p id="x_2_5_0_0_21">The dataspace model constrains the means by which <span class="small-caps">Syndicate</span> programs may communicate events within a group, including communication of unpredictable events. All communication must be expressed as changes in the set of assertions in the dataspace. Therefore, an obvious approach is to use assertions to express such ideas as demand for some service, membership of some group, presence in some context, availability of some resource, and so on. Actors expressing interest in such assertions will receive notifications as matching assertions come and go, including when they vanish unexpectedly. Combining this approach with the guarantee that the dataspace removes all assertions of a failing actor from the dataspace yields a form of exception propagation.</p><p id="x_2_5_0_0_22">For example, consider a protocol where actors assert <span class="lyx-mathjax mathjax-inline">$\mathit{userMessage}(S)$</span>, where <span class="lyx-mathjax mathjax-inline">$S$</span> is a message for the user, in order to cause a user interface element to appear on the user's display. The actor responsible for reacting to such assertions, creating and destroying graphical user interface elements, will react to <em>retraction</em> of a <span class="lyx-mathjax mathjax-inline">$\mathit{userMessage}$</span> assertion by removing the associated graphical element. The actor that <em>asserts</em> some <span class="lyx-mathjax mathjax-inline">$\mathit{userMessage}$</span> may deliberately retract it when it is no longer relevant for the user. However, it may also crash. If it does, the dataspace model ensures that its assertions are all retracted. Since this includes the <span class="lyx-mathjax mathjax-inline">$\mathit{userMessage}$</span> assertion, the actor managing the display learns automatically that its services are no longer required.</p><p id="x_2_5_0_0_23">Another example may be seen in the <span class="lyx-mathjax mathjax-inline">$\mathit{fact}$</span> example discussed above. The client asserting <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{fact}(8,\star))$</span> may “lose interest” before it receives an answer, or of course may crash unexpectedly. From the perspective of actor <span class="lyx-mathjax mathjax-inline">$F$</span>, the two situations are identical: <span class="lyx-mathjax mathjax-inline">$F$</span> is informed of the retraction, concludes that no interest in the factorial of <span class="lyx-mathjax mathjax-inline">$8$</span> remains, and may then choose to abandon the computation. The request implicated by assertion of <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{fact}(8,\star))$</span> is effectively <em>canceled</em> by retraction, whether this is caused by some active decision on the part of the requestor or is an automatic consequence of its unexpected failure.</p><p id="x_2_5_0_0_24">The dataspace model thus offers a mechanism for using changes in assertions to express changes in demand for some resource, including both expected and unpredictable changes. Building on this mechanism, <span class="small-caps">Syndicate</span> offers linguistic tools for <em>responding</em> appropriately to such changes. Assertions describing a demand or a request act as <em>framing knowledge</em> and thus delimit a conversation about the specific demand or request concerned. For example, the presence of <span class="lyx-mathjax mathjax-inline">$\mathit{userMessage}(S)$</span> for each particular <span class="lyx-mathjax mathjax-inline">$S$</span> corresponds to one particular “topic of conversation”. Likewise, the assertion <span class="lyx-mathjax mathjax-inline">$\mathit{interestExists}(\mathit{fact}(8,\star))$</span> corresponds to a particular “call frame” invoking the services of actor <span class="lyx-mathjax mathjax-inline">$F$</span>. Actors need tools for describing such conversational frames, associating local conversational state, relevant event handlers, and any conversation-specific assertions that need to be made with each conversational frame created.</p>
<div class="footnote" id="fn_2_13"><span class="counter footnote-counter"><span>13</span></span>The term “facet” is borrowed from a related use in the language E <span class="citation citep">(<a class="citation" id="cite-29" href="#bib-Miller2006">Miller 2006</a> <span class="citation-after">section 6.2</span>)</span>, which seems to have taken the name in turn from the language Joule <span class="citation citep">(<a class="citation" id="cite-30" href="#bib-Joule1995">Agorics, Inc. 1995</a> <span class="citation-after">chapter 3</span>)</span>.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_2_14"><span class="counter footnote-counter"><span>14</span></span>Almost all object-oriented languages turn to the <em>observer pattern</em> <span class="citation citep">(<a class="citation" id="cite-31" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span> to simulate this ability.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_25"><span class="small-caps">Syndicate</span> introduces a language construct called a <em>facet</em> for this purpose.<label class="footnote-number" for="fn_2_13">13</label> Each actor is composed of multiple facets; each facet represents a particular conversation that the actor is engaged in. A facet both scopes and specifies conversational responses to incoming events. Each facet includes private state variables related to the conversation concerned, as well as a bundle of assertions and event handlers. Each event handler has a pattern over assertions associated with it. Each of these patterns is translated into an assertion of interest and combined with the other assertions of the facet to form the overall contribution that the facet makes to the shared dataspace. An analogy to objects in object-oriented languages can be drawn. Like an object, a facet has private state. Its event handlers are akin to an object's methods. Unique to facets, though, is their contribution to the shared state in the dataspace: objects lack a means to automatically convey changes in their local state to interested peers.<label class="footnote-number" for="fn_2_14">14</label></p><p id="x_2_5_0_0_26">Facets may be nested. This can be used to reflect nested sub-conversations via nested facets. When a containing facet is terminated, its contained facets are also terminated, and when an actor has no facets left, the actor itself terminates. Of course, if the actor crashes or is explicitly shut down, all its facets are removed along with it. These termination-related aspects correspond to the idea that a thread of conversation that logically depends on some overarching discussion context clearly becomes irrelevant when the broader discussion is abandoned.</p><p id="x_2_5_0_0_27">The combination of <span class="small-caps">Syndicate</span>'s facets and its assertion-centric approach to state replication yields a mechanism for robustly detecting and responding to certain kinds of unpredictable event. However, not all forms of unpredictability lend themselves to explicit modeling as shared assertions. For these, we require an alternative approach.</p><p id="x_2_5_0_0_28">Consider unpredictable interleavings of events: for example, UDP datagrams may be reordered arbitrarily by the network. If some datagram <span class="lyx-mathjax mathjax-inline">$B$</span> can only be interpreted after datagram <span class="lyx-mathjax mathjax-inline">$A$</span> has been interpreted, a datagram receiver <span class="lyx-mathjax mathjax-inline">$R$</span> must arrange to buffer packets when they are received out of order, reconstructing an appropriate order to perform its task. The same applies to messages passed between actors in the actor model. The observation that datagram <span class="lyx-mathjax mathjax-inline">$A$</span> establishes necessary context for the subsequent message <span class="lyx-mathjax mathjax-inline">$B$</span> suggests an approach we may take in <span class="small-caps">Syndicate</span>. If instead of messages we model <span class="lyx-mathjax mathjax-inline">$A$</span> and <span class="lyx-mathjax mathjax-inline">$B$</span> as assertions, then we may write our program <span class="lyx-mathjax mathjax-inline">$R$</span> as follows:</p>
<ol id="x_2_5_0_0_33"><li id="x_2_5_0_0_29">Express interest in <span class="lyx-mathjax mathjax-inline">$A$</span>. Wait until notified that <span class="lyx-mathjax mathjax-inline">$A$</span> has been asserted.</li><li id="x_2_5_0_0_30">Express interest in <span class="lyx-mathjax mathjax-inline">$B$</span>. Wait until notified that <span class="lyx-mathjax mathjax-inline">$B$</span> has been asserted.</li><li id="x_2_5_0_0_31">Process <span class="lyx-mathjax mathjax-inline">$A$</span> and <span class="lyx-mathjax mathjax-inline">$B$</span> as usual.</li><li id="x_2_5_0_0_32">Withdraw the previously-asserted interests in <span class="lyx-mathjax mathjax-inline">$A$</span> and <span class="lyx-mathjax mathjax-inline">$B$</span>.</li></ol>
<div class="footnote" id="fn_2_15"><span class="counter footnote-counter"><span>15</span></span>Program <span class="lyx-mathjax mathjax-inline">$R$</span> recovers a form of logical monotonicity for the small protocol fragment it is engaging in. An interesting connection can be made here to the CALM principle of <span class="citation citet"><a class="citation" id="cite-32" href="#bib-Alvaro2011"><span>Alvaro et al.<span class="parens"> (</span>2011<span class="parens">)</span></span></a></span>.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_34">This program will function correctly no matter whether <span class="lyx-mathjax mathjax-inline">$A$</span> is asserted before <span class="lyx-mathjax mathjax-inline">$B$</span> or vice versa. The structure of program <span class="lyx-mathjax mathjax-inline">$R$</span> reflects the observation that <span class="lyx-mathjax mathjax-inline">$A$</span> supplies a <em>frame</em> within which <span class="lyx-mathjax mathjax-inline">$B$</span> is to be understood by paying attention to <span class="lyx-mathjax mathjax-inline">$B$</span> only after having learned <span class="lyx-mathjax mathjax-inline">$A$</span>. Use of assertions instead of messages allows an interpreter of knowledge to decouple itself from the precise order of events in which knowledge is acquired and shared, concentrating instead on the logical dependency ordering among items of knowledge.<label class="footnote-number" for="fn_2_15">15</label></p><p id="x_2_5_0_0_35">Finally, certain forms of unpredictability cannot be effectively detected or forestalled. For example, no system can distinguish nontermination from mere slowness in practice. In cases such as these, timeouts can be used in <span class="small-caps">Syndicate</span> just as in other languages. Modeling time as a protocol involving assertions <span class="lyx-mathjax mathjax-inline">$\mathit{laterThan}(t)$</span> in the dataspace allows us to smoothly incorporate time with other protocols, treating it as just like any other kind of knowledge about the world.</p>
<h6 class="unnumbered" id="x_2_5_0_0_36"><a name="toc_2.5"></a><span class="heading-text paragraph">Unpredictability in the design process.</span></h6><p id="x_2_5_0_0_37">Section <a class="cross-reference" href="#sec:Unpredictability-in-design">2.4</a>, expanding on question <a class="cross-reference" href="#Q-robust-goal-change">K6</a>, introduced the challenges of debuggability, flexibility, and upgradeability. The dataspace model contributes to debuggability, while facets and hierarchical layering of dataspaces contribute to flexibility. While this dissertation does not offer more than a cursory investigation of upgradeability, the limited exploration of the topic so far completed does suggest that it could be smoothly integrated with the <span class="small-caps">Syndicate</span> design.</p><p id="x_2_5_0_0_38">The dataspace model leads the programmer to reason about the group of collaborating actors as a whole in terms of two kinds of <em>change</em>: actions that alter the set of assertions in the dataspace, and events delivered to individual actors as a consequence of such actions. This suggests a natural tracing mechanism. There is nothing to the model other than events and actions, so capturing and displaying the sequence of actions and events not only accurately reflects the operation of a dataspace program, but directly connects to the programmer's mental model as well.</p><p id="x_2_5_0_0_39">Facets can be seen as atomic units of interaction. They allow decomposition of an actor's relationships and conversations into small, self-contained pieces with well-defined boundaries. As the overall goals of the system change, its actors can be evolved to match by making alterations to groups of related facets in related actors. Altering, adding, or removing one facet while leaving others in an actor alone makes perfect sense.</p><p id="x_2_5_0_0_40">The dataspace model is <em>hierarchical</em>. Each dataspace is modeled as a component in some wider context: as an actor in another, <em>outer</em> dataspace. This applies recursively. Certain assertions in the dataspace may be marked with a special constructor that causes them to be <em>relayed</em> to the next containing dataspace in the hierarchy, yielding cross-dataspace interaction. Peers in a particular dataspace are given no means of detecting whether their collaborators are simple actors or entire nested dataspaces with rich internal structure. This frees the program designer to decompose an actor into a nested dataspace with multiple contained actors, without affecting other actors in the system at large. This recursive, hierarchical (dis)aggregation of actors also contributes to the flexibility of a <span class="small-caps">Syndicate</span> program as time goes by and requirements change.</p>
<div class="footnote" id="fn_2_16"><span class="counter footnote-counter"><span>16</span></span>The content of a given dataspace is just the union of the assertions currently maintained by its contained actors. Each connected actor usually maintains a complete picture of its own assertions. When <em>all</em> the actors in a group do this, the <em>dataspace</em> underpinning the group could in principle be rebooted or upgraded seamlessly without disrupting the work of the group as a whole, reconstructing dataspace state from the records of the actors themselves.<span class="plain-layout-boundary"></span></div><p id="x_2_5_0_0_41">Code upgrade is a challenging problem for any system. Replacing a unit of code involves the old code marshaling its state into a bundle of information to be delivered to the new code. In other words, the actor involved sends a message to its “future self”. Systems like Erlang <span class="citation citep">(<a class="citation" id="cite-33" href="#bib-Armstrong2003">Armstrong 2003</a>)</span> incorporate sophisticated language- and library-level mechanisms for supporting such code replacement. <span class="small-caps">Syndicate</span> shares with Erlang some common ideas from the actor model. The strong isolation between actors allows each to be treated separately when it comes to code replacement. Logically, each is running an independent codebase. By casting all interactions among actors in terms of a protocol, both Erlang and <span class="small-caps">Syndicate</span> offer the possibility of protocol-mediated upgrades and reboots affecting anything from a small part to the entirety of a running system.<label class="footnote-number" for="fn_2_16">16</label></p>
<h4 id="x_2_6_0_0_1"><a name="toc_2.6"></a><span class="counter section"><span>2.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Syndicate-design-principles"></a><a name="sec:Syndicate-design-principles"></a><span class="small-caps">Syndicate</span> design principles</span></h4><p id="x_2_6_0_0_2">In upcoming chapters, we will see concrete details of the <span class="small-caps">Syndicate</span> design and its implementation and use. Before we leave the high-level perspective on concurrency, however, a few words on general principles of the design of concurrent and distributed systems are in order. I have taken these guidelines as principles to be encouraged in <span class="small-caps">Syndicate</span> and in <span class="small-caps">Syndicate</span> programs. To be clear, they are my own conjectures about what makes good software. I developed them both through my experiences with early <span class="small-caps">Syndicate</span> prototypes and my experiences of development of large-scale commercial software in my career before beginning this project. In some cases, the guidelines influenced the <span class="small-caps">Syndicate</span> design, having an indirect but universal effect on <span class="small-caps">Syndicate</span> programs. In others, they form a set of background assumptions intended to directly shape the protocols designed by <span class="small-caps">Syndicate</span> programmers.</p>
<h6 class="unnumbered" id="x_2_6_0_0_3"><a name="toc_2.6"></a><span class="heading-text paragraph">Exclude implementation concepts from domain ontologies.</span></h6><p id="x_2_6_0_0_4">When working with a <span class="small-caps">Syndicate</span> implementation, programmers must design conversational protocols that capture relevant aspects of the domain each program is intended to address. The most important overarching principle is that <span class="small-caps">Syndicate</span> programs and protocols should <em>make their domain manifest</em>, and <em>hide implementation constructs</em>. Generally, each domain will include an ontology of its own, relating to concepts largely internal to the domain. Such an ontology will seldom or never include concepts from the host language or even <span class="small-caps">Syndicate</span>-specific ideas.</p><p id="x_2_6_0_0_5">Following this principle, <span class="small-caps">Syndicate</span> takes care to avoid polluting a programmer's domain models with implementation- and programming-language-level concepts. As far as possible, the structure and meaning of each assertion is left to the programmer. <span class="small-caps">Syndicate</span> implementations reserve the contents of a dataspace for domain-level concepts. Access to information in the domain of <em>programs</em>, relevant to debugging, tracing and otherwise reflecting on the operation of a running program, is offered by other (non-dataspace, non-assertion) means. This separation of domain from implementation mechanism manifests in several specific corollaries:</p>
<ol id="x_2_6_0_0_22"><li id="x_2_6_0_0_8">Do not propagate host-language exception values across a dataspace.<p id="x_2_6_0_0_6">An actor that raises an uncaught exception is terminated and removed from the dataspace, but the details of the exception (stack traces, error messages, error codes etc.) are <em>not</em> made available to peers via the dataspace. After all, exceptions describe some aspect of a running computer program, and do not in general relate to the program's domain.</p>
<div class="footnote" id="fn_2_17"><span class="counter footnote-counter"><span>17</span></span><span class="small-caps">Syndicate</span> distinguishes itself from Erlang here. Erlang's failure-signaling primitives, links and monitors, necessarily operate in terms of actor IDs, so it is no great step to include stack traces and error messages alongside an actor ID in a failure description record.<span class="plain-layout-boundary"></span></div><p id="x_2_6_0_0_7">Instead, a special reflective mechanism is made available for host-language programs to access such information for debugging and other similar purposes. Actors in a dataspace do not use this mechanism when operating normally. As a rule, they instead depend on <em>domain-level</em> signaling of failures in terms of the (automatic) removal of domain-level assertions on failure, and do not depend on host-language exceptions to signal domain-level exceptional situations.<label class="footnote-number" for="fn_2_17">17</label></p></li><li id="x_2_6_0_0_14">Make internal actor identifiers completely invisible.<p id="x_2_6_0_0_9">The notion of a (programming-language) actor is almost never part of the application domain; this goes double for the notion of an actor's internal identifier (a.k.a. pointer, “pid”, or similar). Where identity of specific parties is relevant to a domain, <span class="small-caps">Syndicate</span> requires the protocol to explicitly specify and manage such identities, and they remain distinct from the internal identities of actors in a running <span class="small-caps">Syndicate</span> program. Again, during debugging, the identities of specific actors are relevant to the programmer, but this is because the programmer is operating in a different domain from that of the program under study.</p><p id="x_2_6_0_0_10">Explicit treatment of identity unlocks two desirable abilities:</p>
<ol id="x_2_6_0_0_13"><li id="x_2_6_0_0_11">One (implementation-level) actor can transparently perform multiple (domain-level) roles. Having decoupled implementation-level identity from domain-level information, we are free to choose arbitrary relations connecting them.</li><li id="x_2_6_0_0_12">One actor can transparently delegate portions of its responsibilities to others. Explicit management of identity allows actors to <em>share</em> a domain-level identity without needing to share an implementation-level identity. Peers interacting with such actors remain unaware of the particulars of any delegation being employed.</li></ol></li><li id="x_2_6_0_0_16">Multicast communication should be the norm; point-to-point, a special case.<p id="x_2_6_0_0_15">Conversational interactions can involve any number of participants. In languages where the implementation-provided medium of conversation always involves exactly two participants, programmers have to encode <span class="lyx-mathjax mathjax-inline">$n$</span>-party domain-level conversations using the two-party mechanism. Because of this, messages between components have to mention implementation-level conversation endpoints such as channel or actor IDs, polluting otherwise domain-specific ontologies with implementation-level constructs. In order to keep implementation ideas out of domain ontologies, <span class="small-caps">Syndicate</span> does not define any kind of value-level representation of a conversation. Instead, it leaves the choice of scheme for naming conversations up to the programmer.</p></li><li id="x_2_6_0_0_21">Equivalences on messages, assertions and other forms of shared state should be in terms of the domain, not in terms of implementation constructs.<p id="x_2_6_0_0_17">For example, consider deduplication of received messages. In some protocols, in order to make message receipt idempotent, a table of previously-seen messages must be maintained. To decide membership of this table, a particular equivalence must be chosen. Forcing this equivalence to involve implementation-level constructs entails a need for the programmer to explicitly normalize messages to ensure that the implementation-level equivalence reflects the desired domain-level equivalence. To be even more specific:</p>
<ol id="x_2_6_0_0_20"><li id="x_2_6_0_0_18">If a transport includes message sequence numbers, message identifiers, timestamps etc., then these items of information from the transport should not form part of the equivalence used.</li><li id="x_2_6_0_0_19">Sender identity should not form part of the equivalence used. If a particular protocol needs to know the identity of the sender of a message, it should explicitly include a definition of the relevant notion of identity (not necessarily the implementation-level identity of the sender) and explicitly include it in message type definitions.</li></ol></li></ol>
<h6 class="unnumbered" id="x_2_6_0_0_23"><a name="toc_2.6"></a><span class="heading-text paragraph">Support resource management decisions.</span></h6><p id="x_2_6_0_0_24">Concurrent programs in all their forms rely on being able to scope the size and lifetime of allocations of internal resources made in response to external demand. “Demand” and “resource” are extremely general ideas. As a result, resource management decisions appear in many different guises, and give rise to a number of related principles:</p>
<ol id="x_2_6_0_0_33"><li id="x_2_6_0_0_28"><em>Demand-matching</em> should be well-supported.<p id="x_2_6_0_0_25">Demand-matching is the process of automatic allocation <em>and release </em>of some resource in response to detected need elsewhere in a program. The concept applies in many different places.</p><p id="x_2_6_0_0_26">For example, in response to the <em>demand</em> of an incoming TCP connection, a server may allocate resources including a pair of memory buffers and a new thread. The buffers, combined with TCP back-pressure, give control over memory usage, and the thread gives control over compute resources as well as offering a convenient language construct to attach other kinds of resource-allocation and -release decisions to. When the connection closes, the server may terminate the thread, release other associated resources, and finalize its state.</p><p id="x_2_6_0_0_27">Another example can be found in graphical user interfaces, where various widgets manifest in response to the needs of the program. An entry in a “buddy list” in a chat program may be added in response to presence of a contact, making the “demand” the presence of the contact and the “resource” the resulting list entry widget. When the contact disconnects, the “demand” for the “resource” vanishes, and the list entry widget should be removed.</p></li><li id="x_2_6_0_0_32">Service presence <span class="citation citep">(<a class="citation" id="cite-34" href="#bib-Konieczny2009">Konieczny et al. 2009</a>)</span> and presence information generally should be well-supported.<p id="x_2_6_0_0_29">Consider linking multiple independent services together to form a concurrent application. A web-server may depend on a database: it “demands” the services of the database, which acts as a “resource”. The web-server and database may in turn depend upon a logging service. Each service cannot start its work before its dependencies are ready: it observes the <em>presence</em> of its dependencies as part of its initialization.</p><p id="x_2_6_0_0_30">Similarly, in a publish-subscribe system, it may be expensive to collect and broadcast a certain statistic. A publisher may use the availability of subscriber information to decide whether or not the statistic needs to be maintained. Consumers of the statistic act as “demand”, and the resource is the entirety of the activity of producing the statistic, along with the statistic itself. Presence of consumers is used to manage resource commitment.</p><p id="x_2_6_0_0_31">Finally, the AMQP messaging middleware protocol <span class="citation citep">(<a class="citation" id="cite-35" href="#bib-Group2008">The AMQP Working Group 2008</a>)</span> includes special flags named “immediate” and “mandatory” on each published message. They cause a special “return to sender” feature to be activated, triggering a notification to the sender only when <em>no receiver is present</em> for the message at the time of its publication. This form of presence allows a sender to take alternative action in case no peer is available to attend to its urgent message.</p></li></ol>
<h6 class="unnumbered" id="x_2_6_0_0_34"><a name="toc_2.6"></a><span class="heading-text paragraph">Support direct communication of public aspects of component state.</span></h6><p id="x_2_6_0_0_35">This is a generalization of the notion of presence, which is just one portion of overall state.</p>
<h6 class="unnumbered" id="x_2_6_0_0_36"><a name="toc_2.6"></a><span class="heading-text paragraph">Avoid dependence on timeouts.</span></h6><p id="x_2_6_0_0_37">In a distributed system, a failed component is indistinguishable from a slow one and from a network failure. Timeouts are a pragmatic solution to the problem in a distributed setting. Here, however, we have the luxury of a <em>non-</em>distributed design, and we may make use of specific forms of “demand” information or presence in order to communicate failure. Timeouts are still required for inter-operation with external systems, but are seldom needed as a normal part of greenfield <span class="small-caps">Syndicate</span> protocol design.</p>
<h6 class="unnumbered" id="x_2_6_0_0_38"><a name="toc_2.6"></a><span class="heading-text paragraph">Reduce dependence on order-of-operations.</span></h6><p id="x_2_6_0_0_39">The language should be designed to make programs robust by default to reordering of signals. As part of this, idempotent signals should be the default where possible.</p>
<ol id="x_2_6_0_0_42"><li id="x_2_6_0_0_40">Event-handlers should be written as if they were to be run in a (pseudo-) random order, even if a particular implementation does not rearrange them randomly. This is similar to the thinking behind the random event selection in CML's choice mechanism <span class="citation citep">(<a class="citation" id="cite-36" href="#bib-Reppy1992">Reppy 1992</a> <span class="citation-after">page 131</span>)</span>.</li><li id="x_2_6_0_0_41">Questions of deduplication, equivalence, and identity must be placed at the heart of each <span class="small-caps">Syndicate</span> protocol design, even if only at an abstract level.</li></ol>
<h6 class="unnumbered" id="x_2_6_0_0_43"><a name="toc_2.6"></a><span class="heading-text paragraph">Eschew transfer of higher-order data.</span></h6>
<div class="footnote" id="fn_2_18"><span class="counter footnote-counter"><span>18</span></span>Specifically, closures closing over <em>mutable</em> state; “pure” closures are in some sense not higher-order. See also Miller's work on “spores” <span class="citation citep">(<a class="citation" id="cite-37" href="#bib-Miller2014">Miller, Haller and Odersky 2014</a>; <a class="citation" id="cite-38" href="#bib-Miller2016">Miller et al. 2016</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_2_6_0_0_44">Mathematical and computational structures enjoy an enormous amount of freedom not available to structures that must be realized in the physical world. Similarly, patterns of interaction that can be realized in a non-distributed setting are often inappropriate, unworkable, or impossible to translate to a distributed setting. One example of this concerns <em>higher-order</em> data, by which I mean certain kinds of closure,<label class="footnote-number" for="fn_2_18">18</label> mutable data structures, and any other stateful kind of entity.</p><p id="x_2_6_0_0_45"><span class="small-caps">Syndicate</span> is not a distributed programming language, but was heavily inspired by my experience of distributed programming and by limitations of existing programming languages employed in a distributed setting. Furthermore, certain features of the design suggest that it may lead to a useful distributed programming model in future. With this in mind, certain principles relate to a form of physical realizability; chief among them, the idea of limiting information exchange to first-order data wherever possible. The language should encourage programmers to act as if transfer of higher-order data between peers in a dataspace were impossible. While non-distributed implementations of <span class="small-caps">Syndicate</span> can offer support for transfer of functions, objects containing mutable references, and so on, stepping to a distributed setting limits programs to exchange of first-order data only, since real physical communication networks are necessarily first-order. Transfer of higher-order data involves a hidden use/mention distinction. Higher-order data may be <em>encoded</em>, but cannot directly be <em>transmitted</em>.</p><p id="x_2_6_0_0_46">With that said, however, notions of stateful location or place are important to certain domains, and the ontologies of such domains may well naturally include references to such domain-relevant location information. It is host-language higher-order data that <span class="small-caps">Syndicate</span> discourages, not domain-level references to location and located state.</p>
<h6 class="unnumbered" id="x_2_6_0_0_47"><a name="toc_2.6"></a><span class="heading-text paragraph">Arrange actors hierarchically.</span></h6><p id="x_2_6_0_0_48">Many experiments in structuring groups of (actor model) actors have been performed over the past few decades. Some employ <em>hierarchies</em> of actors, that is, the overall system is structured as a tree, with each actor or group existing in exactly one group <span class="citation citep">(<span class="citation-before">e.g.</span> <a class="citation" id="cite-39" href="#bib-Varela1999">Varela and Agha 1999</a>)</span>. Others allow actors to be placed in more than one group at once, yielding a <em>graph</em> of actors <span class="citation citep">(<span class="citation-before">e.g.</span> <a class="citation" id="cite-40" href="#bib-Callsen1994">Callsen and Agha 1994</a>)</span>.</p><p id="x_2_6_0_0_49"><span class="small-caps">Syndicate</span> limits actor composition to tree-shaped hierarchies of actors, again inspired by physical realizability. Graph-like connectivity is encoded in terms of protocols layered atop the hierarchical medium provided. Recursive groupings of computational entities in real systems tend to be hierarchical: threads within processes within containers managed by a kernel running under a hypervisor on a core within a CPU within a machine in a datacenter.</p>
<h4 id="x_2_7_0_0_1"><a name="toc_2.7"></a><span class="counter section"><span>2.7</span></span><span class="heading-text section">On the name “<span class="small-caps">Syndicate</span>”</span></h4><p id="x_2_7_0_0_2">Now that we have seen an outline of the <span class="small-caps">Syndicate</span> design, the following definitions may shed light on the choice of the name “<span class="small-caps">Syndicate</span>”:</p>
<div class="footnote" id="fn_2_19"><span class="counter footnote-counter"><span>19</span></span>Definition retrieved from Wikipedia, <a href="https://en.wikipedia.org/wiki/Syndicate">https://en.wikipedia.org/wiki/Syndicate</a>, on 23 August 2017.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_2_20"><span class="counter footnote-counter"><span>20</span></span>Definition retrieved from the online Oxford Living Dictionaries, <a href="https://en.oxforddictionaries.com/definition/syndicate">https://en.oxforddictionaries.com/definition/syndicate</a> on 23 August 2017. The full Oxford English Dictionary entries for “syndicate” are much longer and do not make such a pleasing connection to the language design idea.<span class="plain-layout-boundary"></span></div>
<blockquote id="x_2_7_0_0_17">
<p id="x_2_7_0_0_3">A <b>syndicate</b> is a self-organizing group of individuals, companies, corporations or entities formed to transact some specific business, to pursue or promote a shared interest.</p>
<p class="align-right" id="x_2_7_0_0_4">— Wikipedia<label class="footnote-number" for="fn_2_19">19</label></p>
<p id="x_2_7_0_0_5"><b></b></p>
<p id="x_2_7_0_0_10"><b>Syndicate</b>, n.
<blockquote id="x_2_7_0_0_9">
<p id="x_2_7_0_0_8">1. A group of individuals or organizations combined to promote a common interest.
<blockquote id="x_2_7_0_0_7">
<p id="x_2_7_0_0_6">1.1 An association or agency supplying material simultaneously to a number of newspapers or periodicals.</p></blockquote></p></blockquote></p>
<p id="x_2_7_0_0_15"><b>Syndicate</b>, v.tr.
<blockquote id="x_2_7_0_0_14">
<p id="x_2_7_0_0_13">...
<blockquote id="x_2_7_0_0_12">
<p id="x_2_7_0_0_11">1.1 Publish or broadcast (material) simultaneously in a number of newspapers, television stations, etc.</p></blockquote></p></blockquote></p>
<p class="align-right" id="x_2_7_0_0_16">— Oxford Dictionary<label class="footnote-number" for="fn_2_20">20</label></p></blockquote><p id="x_2_7_0_0_18">An additional relevant observation is that a syndicate can be a group of companies, and a company can be a group of actors.</p></p><p id="x_3_6_0_0_11">
<h3 id="x_3_0_0_0_1"><a name="toc_3"></a><span class="counter chapter"><span>3</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:APPROACHES-TO-COORDINATION"></a><a name="CHAP:APPROACHES-TO-COORDINATION"></a>Approaches to Coordination</span></h3><p id="x_3_0_0_0_2">Our analysis of communication and coordination so far has yielded a high-level, abstract view on concurrency, taking<em> knowledge-sharing</em> as the linchpin of cooperation among components. The previous chapter raised several questions, answering some in general terms, and leaving others for investigation in the context of specific <em>mechanisms</em> for sharing knowledge. In this chapter, we explore these remaining questions. To do so, we survey the paradigmatic approaches to communication and coordination. Our focus is on the needs of programmers and the operational issues that arise in concurrent programming. That is, we look at ways in which an approach helps or hinders achievement of a program's goals in a way that is robust to unpredictability and change.</p>
<h4 id="x_3_1_0_0_1"><a name="toc_3.1"></a><span class="counter section"><span>3.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:A-concurrency-design-landscape"></a><a name="sec:A-concurrency-design-landscape"></a>A concurrency design landscape</span></h4><p id="x_3_1_0_0_2">The outstanding questions from chapter <a class="cross-reference" href="#CHAP:PHILOSOPHY-AND-OVERVIEW">2</a> define a multi-dimensional landscape within which we place different approaches to concurrency. A given concurrency model can be assigned to a point in this landscape based on its properties as seen through the lens of these questions. Each point represents a particular set of trade-offs with respect to the needs of programmers.</p><p id="x_3_1_0_0_3">To recap, the questions left for later discussion were:</p>
<ol class="custom-label" id="x_3_1_0_0_5"><li id="x_3_1_0_0_4"><span class="custom-label">K4</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span>Which forms of knowledge-sharing are robust in the face of the unpredictability intrinsic to concurrency?</li></ol>
<ol class="custom-label" id="x_3_1_0_0_7"><li id="x_3_1_0_0_6"><span class="custom-label">K6</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span>Which forms of knowledge-sharing are robust to and help mitigate the impact of changes in the goals of a program?</li></ol><p id="x_3_1_0_0_8">In addition, the investigation of question <a class="cross-reference" href="#Q-interests">K3</a> (“what do concurrent components need to know to do their jobs?”) concluded with a picture of domain knowledge, epistemic knowledge, framing knowledge, and knowledge flow within a group of components. However, it left unaddressed the question of <em>mechanism</em>, giving rise to a follow-up question:</p>
<ol class="custom-label" id="x_3_1_0_0_10"><li id="x_3_1_0_0_9"><span class="custom-label">K3bis</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#Q-mechanism"></a><a name="Q-mechanism"></a>How do components learn what they need to know as time goes by?</li></ol><p id="x_3_1_0_0_11">In short, the three questions relate to <em>robustness</em>, <em>operability</em> and <em>mechanism</em>, respectively. The rest of the chapter is structured around an informal investigation of characteristics refining these categories.</p>
<figure id="x_3_1_0_0_37"><a name="fig:Characteristics-of-approaches-to-concurrency"></a><span class="plain-layout-boundary"></span>
<dl id="x_3_1_0_0_36"><dt id="x_3_1_0_0_12">Mechanism&nbsp;(<a class="cross-reference" href="#Q-mechanism">K3bis</a>).</dt><dd id="x_3_1_0_0_19"> A central characteristic of a given concurrency model is its mechanism for exchange of knowledge among program components. Each mechanism yields a different set of possibilities for how concurrent conversations evolve. First, a conversation may have arbitrarily many participants, and a participant may engage in multiple conversations at once. Hence, models and language designs must be examined as to
<ol class="custom-label" id="x_3_1_0_0_15"><li id="x_3_1_0_0_13"><span class="custom-label">C1</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#c:conversation-size"></a><a name="c:conversation-size"></a>how they support various <em>conversation group sizes</em> and</li><li id="x_3_1_0_0_14"><span class="custom-label">C2</span><a class="label-anchor" href="#c:demux"></a><a name="c:demux"></a>how they support <em>correlation and demultiplexing</em> of incoming events.</li></ol>Second, conversations come with associated <em>state</em>. Each participating component must find out about changes to this state and must <em>integrate those changes</em> with its local view. The component may also wish to <em>change</em> conversational state; such changes must be <em>signaled</em> to relevant peers. A mechanism can thus be analyzed in terms of<span class="plain-layout-boundary"></span>
<ol class="custom-label" id="x_3_1_0_0_18" start="3"><li id="x_3_1_0_0_16"><span class="custom-label">C3</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><em><a class="label-anchor" href="#c:integration"></a><a name="c:integration"></a></em>how it supports<em> integration of state changes</em> with a component's local view and</li><li id="x_3_1_0_0_17"><span class="custom-label">C4</span><a class="label-anchor" href="#c:signalling"></a><a name="c:signalling"></a>how it arranges for state changes to be <em>signaled</em> to conversational peers.</li></ol></dd><dt id="x_3_1_0_0_20">Robustness&nbsp;(<a class="cross-reference" href="#Q-robust-sharing">K4</a>).</dt><dd id="x_3_1_0_0_29"> Each concurrency model offers a different level of support to the programmer for addressing the unpredictability intrinsic to concurrent programming. Programs rely on the <em>integrity</em> of each participant's view of overall conversational state; this may entail consideration of <em>consistency</em> among different views of the shared state in the presence of unpredictable latency in change propagation. These lead to investigation of
<ol class="custom-label" id="x_3_1_0_0_23" start="5"><li id="x_3_1_0_0_21"><span class="custom-label">C5</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><em><a class="label-anchor" href="#c:integrity"></a><a name="c:integrity"></a></em>how a model helps <em>maintain integrity</em> of conversational state and</li><li id="x_3_1_0_0_22"><span class="custom-label">C6</span><a class="label-anchor" href="#c:consistency"></a><a name="c:consistency"></a>how it helps <em>ensure consistency</em> of state as a program executes.</li></ol>In addition, viewing a conversation as a series of events describing changes in conversational state has direct implications for the connection between data flow and control flow. Clearly, the arrival of a notification (data) at a participant ought to reliably trigger control flow; but conversely, the creation and termination of components must also be able to reliably trigger notifications to peers. This includes exceptions and other forms of partial failure. Hence, we may ask<span class="plain-layout-boundary"></span>
<ol class="custom-label" id="x_3_1_0_0_26" start="7"><li id="x_3_1_0_0_24"><span class="custom-label">C7</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><em><a class="label-anchor" href="#c:data-to-control"></a><a name="c:data-to-control"></a></em>how data flow leads to control flow in programs and</li><li id="x_3_1_0_0_25"><span class="custom-label">C8</span><a class="label-anchor" href="#c:control-to-data"></a><a name="c:control-to-data"></a>how control flow, such as start-up or termination of a component, leads to data flow.</li></ol>Finally, robust programs demand effective strategies for management of computational, storage and other types of resources, leading us to inquire<span class="plain-layout-boundary"></span>
<ol class="custom-label" id="x_3_1_0_0_28" start="9"><li id="x_3_1_0_0_27"><span class="custom-label">C9</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><em><a class="label-anchor" href="#c:resources"></a><a name="c:resources"></a></em>how a concurrency model supports <em>resource management</em> during execution.</li></ol></dd><dt id="x_3_1_0_0_30">Operability&nbsp;(<a class="cross-reference" href="#Q-robust-goal-change">K6</a>).</dt><dd id="x_3_1_0_0_35"> The notion of operability is broad, including attributes pertaining to the ease of working with the model at design, development, debugging and deployment time. We will focus on the ability of a model to support
<ol class="custom-label" id="x_3_1_0_0_34" start="10"><li id="x_3_1_0_0_31"><span class="custom-label">C10</span><span class="lyx-argument"><span class="plain-layout-boundary"></span></span><em><a class="label-anchor" href="#c:debuggability"></a><a name="c:debuggability"></a>debuggability</em> and <em>visualizability</em> of interactions and relationships among components;</li><li id="x_3_1_0_0_32"><span class="custom-label">C11</span><em><a class="label-anchor" href="#c:evolvability"></a><a name="c:evolvability"></a>evolvability</em> of the pattern of interactions within a program; and</li><li id="x_3_1_0_0_33"><span class="custom-label">C12</span><em><a class="label-anchor" href="#c:durability"></a><a name="c:durability"></a>durability</em> of long-lived state as code evolves and features come and go.</li></ol></dd></dl><figcaption><span class="counter figure"><span>3</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Characteristics-of-approaches-to-concurrency"></a>Characteristics of approaches to concurrency<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_1_0_0_38">Characteristics <a class="cross-reference" href="#c:conversation-size">C1</a><a class="cross-reference" href="#c:durability">C12</a> in figure <a class="cross-reference" href="#fig:Characteristics-of-approaches-to-concurrency">3</a> will act as a lens through which we will examine three broad families of concurrency: shared memory models, message-passing models, and tuplespaces and external databases. In addition, we will analyze the fact space model briefly mentioned in the previous chapter.</p><p id="x_3_1_0_0_39">We illustrate our points throughout with a <em>chat server</em> that connects an arbitrary number of participants. It relays text typed by a user to all others and generates announcements about the arrival and departure of peers. A client may thus display a list of active users. The chat server involves chat-room state—the membership of the room—and demands many-to-many communication among the concurrent agents representing connected users. Each such agent receives events from two sources: its peers in the chat-room and the TCP connection to its user. If a user disconnects or a programming error causes a failure in the agent code, resources such as TCP sockets must be cleaned up correctly, and appropriate notifications must be sent to the remaining agents and users. </p>
<h4 id="x_3_2_0_0_1"><a name="toc_3.2"></a><span class="counter section"><span>3.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Shared-memory"></a><a name="sec:Shared-memory"></a>Shared memory</span></h4><p id="x_3_2_0_0_2">Shared memory languages are those where <em>threads</em> communicate via modifications to <em>shared memory</em>, usually <em>synchronized</em> via constructs such as monitors <span class="citation citep">(<a class="citation" id="cite-41" href="#bib-Gosling2014">Gosling et al. 2014</a>; <a class="citation" id="cite-42" href="#bib-IEEE-9945-2009">IEEE 2009</a>; <a class="citation" id="cite-43" href="#bib-ISO-14882-2014">ISO 2014</a>)</span>. Figure <a class="cross-reference" href="#fig:Monitor-style-chat-room">4</a> sketches the heart of a chat room implementation using a monitor <span class="citation citep">(<a class="citation" id="cite-44" href="#bib-BrinchHansen1993">Brinch Hansen 1993</a>)</span> to protect the shared members variable.</p><p id="x_3_2_0_0_3">(<a class="cross-reference" href="#c:conversation-size">C1</a>; <a class="cross-reference" href="#c:integration">C3</a>; <a class="cross-reference" href="#c:signalling">C4</a>) Mutable memory tracks shared state and also acts as a communications mechanism. Buffers and routing information for messages between threads are explicitly encoded as part of the conversational state, which naturally accommodates the multi-party conversations of our chat server. However, announcing changes in conversational state to peers—a connection or disconnection, for example—requires construction of a broadcast mechanism out of low-level primitives.</p><p id="x_3_2_0_0_4">(<a class="cross-reference" href="#c:demux">C2</a>) To engage in multiple conversations at once, a thread must monitor multiple regions of memory for changes. Languages with powerful memory transactions make this easy; the combination of “retry” and “orelse” gives the requisite power <span class="citation citep">(<a class="citation" id="cite-45" href="#bib-Harris2005">Harris et al. 2005</a>)</span>. Absent such transactions, and ruling out polling, threads must explicitly signal each other when making changes. If a thread must wait for any one of several possible events, it is necessary to reinvent multiplexing based on condition variables and write code to perform associated book-keeping. </p>
<figure id="x_3_2_0_0_6"><a name="fig:Monitor-style-chat-room"></a>
<pre class="listing" id="x_3_2_0_0_5"><code>class Chatroom
private Map&lt;String, (String-&gt;())&gt; members
public synchronized connect(user, callback)
for (existingUser, _) in members
callback(existingUser + " arrived")
members.put(user, callback)
announce(user + " arrived")
public synchronized speak(user, text)
announce(user + ": " + text)
public synchronized disconnect(user)
if (!members.containsKey(user)) { return }
members.remove(user)
announce(user + " left")
private announce(what)
for (user, callback) in members.clone()
try { callback(what) }
catch (exn) { disconnect(user) }
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>4</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Monitor-style-chat-room"></a>Monitor-style chat room<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_2_0_0_7">(<a class="cross-reference" href="#c:integrity">C5</a>) Maintaining the integrity of shared state is famously difficult. The burden of correctly placing transaction boundaries or locks and correctly ordering updates falls squarely on the programmer. It is reflected in figure <a class="cross-reference" href="#fig:Monitor-style-chat-room">4</a> not only in the use of the monitor concept itself, but also in the careful ordering of events in the <tt>connect</tt> and <tt>disconnect</tt> methods. In particular, the call to <tt>announce</tt> (line 13) must follow the removal of <tt>user</tt> (line 12), because otherwise, the system may invoke <tt>callback</tt> for the disconnected <tt>user</tt>. Similarly, cloning the<tt> members</tt> map (line 15) is necessary so that a disconnecting user (line 17) does not change the collection mid-iteration. Moreover, even with transactions and correct locking discipline, care must be taken to maintain logical invariants of an application. For example, if a chat user's thread terminates unexpectedly without calling <tt>disconnect</tt>, the system continues to send <em>output</em> to the associated TCP socket indefinitely, even though <em>input</em> from the socket is no longer being handled, meaning <tt>members</tt> has become logically corrupted. Conversely, a seemingly-correct program may call <tt>disconnect</tt> twice in corner cases, which explains the check (line 11) for preventing double departure announcements.</p>
<div class="footnote" id="fn_3_21"><span class="counter footnote-counter"><span>21</span></span>This line of reasoning recalls the explanation offered by Sun (now Oracle) for why the Java method <tt>Thread.stop</tt> is deprecated. <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html">http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html</a><span class="plain-layout-boundary"></span></div><p id="x_3_2_0_0_8">(<a class="cross-reference" href="#c:data-to-control">C7</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>) Memory transactions with “retry” allow control flow to follow directly from changes to shared data; otherwise, however, data flow is completely decoupled from inter-thread control flow. The latter is provided via synchronization primitives, which are only coincidentally associated with changes to the shared store. Coming from the opposite direction, control flow is also decoupled from data flow. For example, exceptions do not automatically trigger a clean-up of shared state or signal the termination of the thread to the relevant group of peers.<label class="footnote-number" for="fn_3_21">21</label> Determining responsibility for a failure and deciding on appropriate recovery actions is challenging. Consider an action by user A that leads to a call to announce. If the callback associated with user B (line 16) throws an exception, the handler on line 17 catches it. To deal with this situation, the developer must reason in terms of three separate, stateful entities with non-trivial responsibilities: the agents for A and B plus the chat room itself. If the exception propagates, it may not only damage the monitors state but terminate the thread representing A, even though it is the fault of Bs callback. Contrast the problems seen in this situation with the call to the callback in connect (line 5); it does not need an exception handler, because the data flow resulting from the natural control flow of exception propagation is appropriate.</p><p id="x_3_2_0_0_9">(<a class="cross-reference" href="#c:resources">C9</a>) The thread model also demands the manual management of resources for a given conversation. For example, disposal of unwanted or broken TCP sockets must be coded explicitly in every program.</p><p id="x_3_2_0_0_10">(<a class="cross-reference" href="#c:consistency">C6</a>) On the bright side, because it is common to have a single copy of any given piece of information, with all threads sharing access to that copy, explicit consideration of consistency among replicas is seldom necessary.</p><p id="x_3_2_0_0_11">The many interlocking problems described above are difficult to discover in realistic programs, either through testing or formal verification. To reach line 17, a callback must fail mid-way through an announcement caused by a different user. The need for the <tt>.clone()</tt> on line 15 is not directly obvious. To truly gain confidence in the implementation, one must consider cases where multiple failures occur during one announcement, including the scenario where a failure during <tt>speak</tt> causes <tt>disconnect</tt> and another failure occurs during the resulting announcement. The interactions between the various locks, loops, callbacks, exception handlers, and pieces of mutable state are manifold and non-obvious.</p><p id="x_3_2_0_0_12">(<a class="cross-reference" href="#c:debuggability">C10</a>; <a class="cross-reference" href="#c:evolvability">C11</a>; <a class="cross-reference" href="#c:durability">C12</a>) Because shared memory languages allow unconstrained access to shared memory, not connected to any kind of scoping construct or protocol description, recovering a clear picture of the relationships and interactions among threads is extremely challenging. Similarly, as discussed for character <a class="cross-reference" href="#c:demux">C2</a>, modifying a component to engage in multiple conversations at once or expanding the scope of a conversation to include multiple components is in general invasive. Finally, the lack of a clear linguistic specification of the structure of the shared memory and its relationship to a program's threads largely precludes automated support for orthogonal persistence and code upgrade.</p><p id="x_3_2_0_0_13">An important variation on shared memory is the single-threaded, event-based style of JavaScript <span class="citation citep">(<a class="citation" id="cite-46" href="#bib-ECMA-262">ECMA 2015</a>)</span>. While use of explicit locking is reduced in such cases, most of the analysis of the threaded approach continues to hold. </p>
<h4 id="x_3_3_0_0_1"><a name="toc_3.3"></a><span class="counter section"><span>3.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Message-passing"></a><a name="sec:Message-passing"></a>Message-passing</span></h4><p id="x_3_3_0_0_2">Message-passing models of concurrency include languages using Hoares CSP channels <span class="citation citep">(<a class="citation" id="cite-47" href="#bib-Hoare1983">Hoare 1985</a>)</span> or channels from the <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>-calculus <span class="citation citep">(<a class="citation" id="cite-48" href="#bib-Milner1999">Milner 1999</a>)</span>, and those based on the actor model <span class="citation citep">(<a class="citation" id="cite-49" href="#bib-Hewitt1973">Hewitt, Bishop and Steiger 1973</a>; <a class="citation" id="cite-50" href="#bib-Agha1986">Agha 1986</a>; <a class="citation" id="cite-51" href="#bib-Agha1997">Agha et al. 1997</a>; <a class="citation" id="cite-52" href="#bib-DeKoster2016">De Koster et al. 2016</a>)</span>. Channel languages include CML <span class="citation citep">(<a class="citation" id="cite-53" href="#bib-Donnelly2008">Donnelly and Fluet 2008</a>; <a class="citation" id="cite-54" href="#bib-Reppy1991">Reppy 1991</a>)</span>, Go, and Rust, which all use channels in a shared-memory setting, and the Join Calculus <span class="citation citep">(<a class="citation" id="cite-55" href="#bib-Gonthier">Fournet and Gonthier 2000</a>)</span>, which assumes an isolated-process setting. This section concentrates on isolated processes because channel-based systems using shared memory are like those discussed in section <a class="cross-reference" href="#sec:Shared-memory">3.2</a>. Actor languages include Erlang <span class="citation citep">(<a class="citation" id="cite-56" href="#bib-Armstrong2003">Armstrong 2003</a>)</span>, Scala <span class="citation citep">(<a class="citation" id="cite-57" href="#bib-Haller2009">Haller and Odersky 2009</a>)</span>, AmbientTalk <span class="citation citep">(<a class="citation" id="cite-58" href="#bib-VanCutsem2014">Van Cutsem et al. 2014</a>)</span>, and E <span class="citation citep">(<a class="citation" id="cite-59" href="#bib-Miller2005">Miller, Tribble and Shapiro 2005</a>)</span>.</p><p id="x_3_3_0_0_3">Channel- and actor-based models are closely related <span class="citation citep">(<a class="citation" id="cite-60" href="#bib-Fowler2016">Fowler, Lindley and Wadler 2016</a>)</span>. An actor receives input exclusively via a mailbox <span class="citation citep">(<a class="citation" id="cite-61" href="#bib-Agha1986">Agha 1986</a>)</span>, and messages are explicitly addressed by the sending actor to a specific recipient. In channel-based languages, messages are explicitly addressed to particular channels; each message goes to a single recipient, even when a channels receive capability is shared among a group of threads.</p>
<div class="footnote" id="fn_3_22"><span class="counter footnote-counter"><span>22</span></span>AmbientTalk is unusual among actor languages for the depth of its consideration for multicast communication and coordination, offering <span class="lyx-mathjax mathjax-inline">$n$</span>-way primitives alongside point-to-point communication. We discuss AmbientTalk further in section <a class="cross-reference" href="#sec:The-fact-space-model">3.5</a>.<span class="plain-layout-boundary"></span></div><p id="x_3_3_0_0_4">(<a class="cross-reference" href="#c:conversation-size">C1</a>) Both actor- and channel-based languages force an encoding of the chat rooms one-to-many medium in terms of built-in point-to-point communication constructs.<label class="footnote-number" for="fn_3_22">22</label> Compare figure <a class="cross-reference" href="#fig:Actor-style-chat-room">5</a>, which expresses the chat room as a process-style actor, with figure <a class="cross-reference" href="#fig:Channel-style-chat-room">6</a>, which presents pseudo-code for a channel-based implementation. In figure <a class="cross-reference" href="#fig:Actor-style-chat-room">5</a>, the actor embodying the chat rooms broadcast medium responds to <tt>Speak</tt> messages (line 15) by sending <tt>ChatOutput</tt> messages to actors representing users in the room. In figure <a class="cross-reference" href="#fig:Channel-style-chat-room">6</a>, the thread running the <tt>chatroom()</tt> procedure responds similarly to <tt>Speak</tt> instructions received on its control channel (line 13).</p>
<figure id="x_3_3_0_0_6"><a name="fig:Actor-style-chat-room"></a>
<pre class="listing" id="x_3_3_0_0_5"><code>def chatroom()
members = new Hashtable()
while True
match receiveMessage()
case Connect(user, PID)
monitor(PID) // Erlang-style "link"
for peer in members.keys
send(PID, ChatOutput(peer + " arrived"))
members.put(user, PID)
announce(members, user + " arrived")
case EXIT_SIGNAL(PID)
user = members.findKeyForValue(PID)
members.remove(user)
announce(members, user + " left")
case Speak(user, text)
announce(members, user + ": " + text)
def announce(members, what)
for PID in members.values
send(PID, ChatOutput(what))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>5</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Actor-style-chat-room"></a>Actor-style chat room<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_3_0_0_7">(<a class="cross-reference" href="#c:demux">C2</a>) Languages with channels often provide a “select” construct, so that programs can wait for events on any of a group of channels. Such constructs implement automatic demultiplexing by channel identity. For example, a thread acting as a user agent might await input from the chat room <em>or</em> the threads TCP connection (figure <a class="cross-reference" href="#fig:Demux-channels-actors">7</a>a). The language runtime takes care to atomically resolve the transaction. In these languages, a channel reference can stand directly for a specific conversational context. By contrast, actor languages lack such a direct representation of a conversation. Actors retrieve messages from their own <em>private</em> mailbox and then demultiplex manually by inspecting received messages for correlation identifiers (figure <a class="cross-reference" href="#fig:Demux-channels-actors">7</a>b). While the channel-based approach forces use of an implementation-level correlator—the channel reference—explicit pattern-based demultiplexing allows domain-level information in each received message to determine the relevant conversational context. The E language <span class="citation citep">(<a class="citation" id="cite-62" href="#bib-Miller2006">Miller 2006</a>; <a class="citation" id="cite-63" href="#bib-DeKoster2016b">De Koster, Van Cutsem and De Meuter 2016</a>)</span> is a hybrid of the two approaches, offering object references to denote specific conversations within the heap of a given actor, and employs method dispatch as a limited pattern matcher over received messages.</p>
<figure id="x_3_3_0_0_9"><a name="fig:Channel-style-chat-room"></a>
<pre class="listing" id="x_3_3_0_0_8"><code>def chatroom(ch)
members = new Hashtable()
while True
match ch.get()
case Connect(user, callbackCh)
for peer in members.keys
callbackCh &lt;- peer + " arrived"
members.put(user, callbackCh)
announce(members, user + " arrived")
case Disconnect(user)
members.remove(user)
announce(members, user + " left")
case Speak(user, text)
announce(members, user + ": " + text)
def announce(members, what)
for callbackCh in members.values
callbackCh &lt;- what
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>6</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Channel-style-chat-room"></a>Channel-style chat room<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_3_3_0_0_16"><a name="fig:Demux-channels-actors"></a>
<div class="frameless-box" id="x_3_3_0_0_12">
<pre class="listing" id="x_3_3_0_0_10"><code>select {
case line &lt;- callbackCh:
tcpOutputCh &lt;- line
case line &lt;- tcpInputCh:
chatroomCh &lt;- Speak(myName, line)
}
</code></pre><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_3_3_0_0_11"><span class="footnotesize">(a) channel-style</span></p><span class="plain-layout-boundary"></span></div>
<div class="frameless-box" id="x_3_3_0_0_15">
<pre class="listing" id="x_3_3_0_0_13"><code>match receiveMessage() {
case ChatOutput(line):
socket.write(line)
case TcpInput(_, line):
send(ChatroomPID, Speak(myName, line))
}
</code></pre><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_3_3_0_0_14"><span class="footnotesize">(b) Actor-style</span></p><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>7</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Demux-channels-actors"></a>Demultiplexing multiple conversations.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_3_0_0_17">(<a class="cross-reference" href="#c:integration">C3</a>; <a class="cross-reference" href="#c:signalling">C4</a>; <a class="cross-reference" href="#c:integrity">C5</a>) With either actors or channels, only a small amount of conversational state is managed by the language runtime. In actor systems, it is the routing table mapping actor IDs to mailbox addresses; in channel-based systems, the implementation of channel references and buffers performs the analogous role. Developers implement other kinds of shared state using message passing. This approach to conversational state demands explicit programming of updates to a local replica of the state based on received messages. Conversely, when an agent decides that a change to conversational state is needed, it must broadcast the change to the relevant parties. Correct notification of changes is crucial to maintaining integrity of conversational state. Most other aspects of integrity maintenance become local problems due to the isolation of individual replicas. In particular, a crashing agent cannot corrupt peers.</p><p id="x_3_3_0_0_18">(<a class="cross-reference" href="#c:integrity">C5</a>) Still, the programmer is not freed from having to consider execution order when it comes to maintaining local state. Consider the initial announcement of already-present peers to an arriving user in figure <a class="cross-reference" href="#fig:Actor-style-chat-room">5</a> (lines 78). Many subtle variations on this code arise from moving the addition of the new user (line 9) elsewhere in the <tt>Connect</tt> handler clause; some omit self-announcement or announce the users appearance twice.</p><p id="x_3_3_0_0_19">(<a class="cross-reference" href="#c:data-to-control">C7</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>) Both models make it impossible to have data flow <em>between</em> agents without associated control flow. As <span class="citation citet"><a class="citation" id="cite-64" href="#bib-Hewitt1973"><span>Hewitt, Bishop and Steiger<span class="parens"> (</span>1973<span class="parens">)</span></span></a></span> write, “control flow and data flow are inseparable” in the actor model. However, control flow <em>within</em> an agent may not coincide with an appropriate flow of data to peers, especially when an exception is raised and crashes an agent. Channel references are not exclusively owned by threads, meaning we cannot generally close channels in case of a crashing thread. Furthermore, most channel-based languages are <em>synchronous</em>, meaning a send blocks if no recipient is ready to receive. If a thread servicing a channel crashes, then the next send to that channel may never complete. In our chat server, a crashed user agent thread can deadlock the whole system: the chatroom thread may get stuck during <tt>callback</tt>s (lines 7 and 17 in figure <a class="cross-reference" href="#fig:Channel-style-chat-room">6</a>). In general, synchronous channel languages preclude local reasoning about potential deadlocks; interaction with some party can lead to deadlock via a long chain of dependencies. Global, synchronous thinking has to be brought to bear in protocol design for such languages: the programmer must consider<em> scheduling</em> in addition to data flow. Actors can do better. Sends are asynchronous, introducing latency and buffering but avoiding deadlock, and mailboxes are owned by exactly one actor. If that actor crashes, further communication to or from that actor is hopeless. Indeed, Erlang offers <em>monitors</em> and <em>exit signals</em>, i.e., an actor may subscribe to a peers lifecycle events (line 6 in figure <a class="cross-reference" href="#fig:Actor-style-chat-room">5</a>). Such subscriptions allow the chat room to combine error handling with normal disconnection. No matter whether a user agent actor terminates normally or abnormally, the <tt>EXIT_SIGNAL</tt> handler (lines 1214) runs, announcing the departure to the remaining peers. The E language allows references to remote objects to <em>break</em> when the associated remote vat exits, crashes, or disconnects, providing a hybrid of channel-style demultiplexing with Erlang-style exit signaling.</p><p id="x_3_3_0_0_20">(<a class="cross-reference" href="#c:consistency">C6</a>) Where many replicas of a piece of state exist alongside communications delays, the problem of maintaining consistency among replicas arises. Neither channels nor actors have any support to offer here. Channels, and synchronous communication in general, seem to prioritize (without guaranteeing) consistency at the expense of deadlock-proneness; asynchronous communication avoids deadlock, but risks inconsistency through the introduction of latency.</p><p id="x_3_3_0_0_21">(<a class="cross-reference" href="#c:resources">C9</a>) Exit signals are a step toward automatically managing resource deallocation. While actors must manually allocate resources, the exit signal mechanism may be used to tie the lifetime of a resource, such as a TCP socket, to the lifetime of an actor. If fine-grained control is needed, it must be programmed manually. Additionally, in asynchronous (buffered) communication, problems with resource control arise in a different way: it is easy to overload a component, causing its input buffer or mailbox to grow potentially without bound.</p><p id="x_3_3_0_0_22">(<a class="cross-reference" href="#c:debuggability">C10</a>) Enforced isolation between components, and forcing all communication to occur via message-passing, makes the provision of tooling for visualizing execution traces possible. Languages such as Erlang include debug trace facilities in the core runtime, and make good use of them for lightweight capturing of traces even in production. However, the possibility of message races complicates reasoning and debugging; programmers are often left to analyze the live behavior of their programs, if tooling is unavailable or inadequate. Modification of programs to capture ad-hoc trace information frequently causes problematic races to disappear, further complicating such analysis.</p><p id="x_3_3_0_0_23">(<a class="cross-reference" href="#c:evolvability">C11</a>) As figure <a class="cross-reference" href="#fig:Demux-channels-actors">7</a> makes clear, modifying a component to engage in multiple simultaneous conversations can be straightforward, if <em>all</em> I/O goes through a single syntactic location. However, if communication is hidden away in calls to library routines, such modifications demand non-local program transformations. Similarly, adding a new participant to an existing conversation can require non-local changes. In instances where a two-party conversation must now include three or more participants, this often results in reification of the communications medium into a program component in its own right.</p><p id="x_3_3_0_0_24">(<a class="cross-reference" href="#c:durability">C12</a>) Erlang encourages adherence to a “tail-call to next I/O action” convention allowing easy upgrade of running code. Strictly-immutable local data and functional programming combine with this convention to allow a module backing a process to be upgraded across such tail-calls, seamlessly transitioning to a new version of the code. In effect, all actor state is held in accumulator data structures explicitly threaded through actor implementations. Other actor languages without such strong conventions cannot offer such a smooth path to live code upgrade. Channel-based languages could include similar conventions; in practice, I am not aware of any that do so.</p>
<h4 id="x_3_4_0_0_1"><a name="toc_3.4"></a><span class="counter section"><span>3.4</span></span><span class="heading-text section">Tuplespaces and databases</span></h4><p id="x_3_4_0_0_2">Finally, <em>hybrid</em> models exist, where a shared, mutable store is the medium of communication, but the store itself is accessed and components are synchronized via message passing. These models are database-like in nature. Languages employing such models include <em>tuplespace</em>-based languages such as Linda <span class="citation citep">(<a class="citation" id="cite-65" href="#bib-Gelernter1985">Gelernter 1985</a>; <a class="citation" id="cite-66" href="#bib-Carriero1994">Carriero et al. 1994</a>)</span>, <span class="small-caps"><span class="small-caps">Lime</span></span> <span class="citation citep">(<a class="citation" id="cite-67" href="#bib-Murphy2006">Murphy, Picco and Roman 2006</a>)</span>, and TOTAM <span class="citation citep">(<a class="citation" id="cite-68" href="#bib-Scholliers2009">Scholliers, González Boix and De Meuter 2009</a>; <a class="citation" id="cite-69" href="#bib-Scholliers2010">Scholliers et al. 2010</a>; <a class="citation" id="cite-70" href="#bib-GonzalezBoix2012">González Boix 2012</a>; <a class="citation" id="cite-71" href="#bib-GonzalezBoix2014">González Boix et al. 2014</a>)</span>, as well as languages that depend solely on an external DBMS for inter-agent communication, such as PHP <span class="citation citep">(<a class="citation" id="cite-72" href="#bib-Tatroe2013">Tatroe, MacIntyre and Lerdorf 2013</a>)</span>.</p>
<div class="footnote" id="fn_3_23"><span class="counter footnote-counter"><span>23</span></span>Compare to shared-memory or message-passing communications media, where items are retrieved either in queue order or by memory location.<span class="plain-layout-boundary"></span></div><p id="x_3_4_0_0_3">Tuplespace languages have in common the notion of a “blackboard” data structure, a <em>tuplespace</em>, shared among a group of agents. Data items, called <em>tuples</em>, are written to the shared area and retrieved by pattern matching.<label class="footnote-number" for="fn_3_23">23</label> Once published to the space, tuples take on independent existence. Similarly, reading a tuple from the space may <em>move</em> it from the shared area to an agents private store.</p><p id="x_3_4_0_0_4">The original tuplespace model provided three essential primitives: <tt>out</tt>, <tt>in</tt>, and <tt>rd</tt>. The first <em>writes</em> tuples to the store; the other two <em>move</em> and <em>copy</em> tuples from the store to an agent, respectively. Both <tt>in</tt> and <tt>rd</tt> are blocking operations; if multiple tuples match an operations pattern, an arbitrary single matching tuple is moved or copied. Later work extended this austere model with, for example, <tt>copy-collect</tt> <span class="citation citep">(<a class="citation" id="cite-73" href="#bib-Rowstron1996a">Rowstron and Wood 1996</a>)</span>, which allows copying of <em>all</em> matching tuples rather than the arbitrary single match yielded by <tt>rd</tt>. Such extensions add essential expressiveness to the system <span class="citation citep">(<a class="citation" id="cite-74" href="#bib-Busi2001">Busi and Zavattaro 2001</a>; <a class="citation" id="cite-75" href="#bib-Felleisen1991">Felleisen 1991</a>)</span>. <span class="small-caps"><span class="small-caps">Lime</span></span> goes further yet, offering not only non-blocking operations <tt>inp</tt> and <tt>rdp</tt>, but also <em>reactions</em>, which are effectively callbacks, executed once per matching tuple. Upon creation of a reaction, existing tuples trigger execution of the callback. When subsequent tuples are inserted, any matches to the reactions pattern cause additional callback invocations. This moves tuplespace programming toward programming with publish/subscribe middleware <span class="citation citep">(<a class="citation" id="cite-76" href="#bib-Eugster2003">Eugster et al. 2003</a>)</span>. TOTAM takes <span class="small-caps">Lime</span>'s reactions even further, allowing reaction to <em>removal</em> of a previously-seen tuple.</p><p id="x_3_4_0_0_5">External DBMS systems share many characteristics with tuplespaces: they allow storage of relations; stored items are persistent; retrieval by pattern-matching is common; and many modern systems can be extended with <em>triggers</em>, code to be executed upon insertion, update, or removal of matching data. One difference is the notion of <em>transactionality</em>, standard in DBMS settings but far from settled in tuplespaces <span class="citation citep">(<a class="citation" id="cite-77" href="#bib-Bakken1995">Bakken and Schlichting 1995</a>; <a class="citation" id="cite-78" href="#bib-Papadopoulos1998">Papadopoulos and Arbab 1998</a>)</span>. Another is the decoupling of notions of process from the DBMS itself, where tuplespace systems integrate process control with other aspects of the coordination mechanism.</p>
<figure id="x_3_4_0_0_7"><a name="fig:Tuplespace-style-chat-room"></a>
<pre class="listing" id="x_3_4_0_0_6"><code>class UserAgent
public run(name, socket)
new Reaction(Present(_), fn(who) { socket.println(who + " arrived") })
new Reaction(Absent(_), fn(who) { socket.println(who + " left") })
new Reaction(Message(_,_), fn(who, what) { socket.println(who + ": " + what) })
previousLine = null
try
inp(Absent(name))
out(Present(name))
while (line = socket.readLine()) != null
if previousLine != null: in(Message(name, previousLine))
out(Message(name, line))
previousLine = line
finally
if previousLine != null: in(Message(name, previousLine))
in(Present(name))
out(Absent(name))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>8</span></span><span class="figcaption-text"><span class="lyx-argument">Tuplespace-style chat room user agent<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Tuplespace-style-chat-room"></a>Tuplespace-style chat room user agent, modeled on <tt>LChat.java</tt> from the <span class="small-caps">Lime</span> 1.06 distribution.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_3_24"><span class="counter footnote-counter"><span>24</span></span>Our chat server problem is challenging to solve using the original Linda primitives alone. The introduction of <tt>copy-collect</tt> and reactions removes these obstacles.<span class="plain-layout-boundary"></span></div><p id="x_3_4_0_0_8">Figure <a class="cross-reference" href="#fig:Tuplespace-style-chat-room">8</a> presents a pseudo-code tuplespace implementation of a user agent, combining Java-like constructs with <span class="small-caps"><span class="small-caps">Lime</span></span>-like reactions. Previous sketches have concentrated on appropriate implementation of the shared medium connecting user agents; here, we concentrate on the agents themselves, because tuplespaces are already sufficiently expressive to support broadcasting.<label class="footnote-number" for="fn_3_24">24</label></p>
<div class="footnote" id="fn_3_25"><span class="counter footnote-counter"><span>25</span></span>Systems like TOTAM introduce rule-based visibility constraints for tuples.<span class="plain-layout-boundary"></span></div><p id="x_3_4_0_0_9">(<a class="cross-reference" href="#c:conversation-size">C1</a>; <a class="cross-reference" href="#c:demux">C2</a>; <a class="cross-reference" href="#c:integration">C3</a>) Tuplespaces naturally yield multi-party communication. All communication happens indirectly through manipulation of shared state. Inserted tuples are visible to all participants.<label class="footnote-number" for="fn_3_25">25</label> With reactions, programmers may directly express the relationship between appearance of tuples matching a pattern and execution of a code fragment, allowing a richer kind of demultiplexing of conversations than channel-based models. For example, the reactions in figure <a class="cross-reference" href="#fig:Tuplespace-style-chat-room">8</a> (lines 35) manifestly associate conversations about presence, absence and utterances with specific responses, respectively; the tuplespace automatically selects the correct code to execute as events are received. By contrast, in tuplespace languages without reactions, the blocking natures of <tt>in</tt> and <tt>rd</tt> lead to multiplexing problems similar to those seen with shared memory and monitors.</p><p id="x_3_4_0_0_10">(<a class="cross-reference" href="#c:conversation-size">C1</a>) Tuples are persistent, hence the need to retract each message before inserting the next (line 11). An unfortunate side effect is that if a new participant joins mid-conversation, it receives the most recent utterance from each existing peer, even though that utterance may have been made a long time ago.</p><p id="x_3_4_0_0_11">(<a class="cross-reference" href="#c:data-to-control">C7</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>; <a class="cross-reference" href="#c:signalling">C4</a>; <a class="cross-reference" href="#c:integrity">C5</a>) Data flow usually occurs concomitantly with control flow in a tuplespace; <tt>in</tt> and <tt>rd</tt> are blocking operations, and reactions trigger code execution in response to a received event. Control flow, however, does not always trigger associated data flow. Because manipulation of the tuplespace is imperative, no mechanism exists within the core tuplespace model to connect the lifetime of tuples in the space with the lifetime of the agent responsible for them. This can lead to difficulty maintaining application-level invariants, even though the system ensures data-structure-level integrity of the tuplespace itself. For an example, see the explicit clean-up action as the process prepares to exit (lines 1517). In addition, the effect of exceptions inside reactions remains unclear in all tuplespace languages. Turning to external DBMS, we see that the situation is worse. There, setting aside the possibility of abusing triggers for the purpose, changes in state do not directly have an effect on the flow of control in the system. Connections between programs and the DBMS are viewed as entirely transient and records inserted are viewed as sacrosanct once committed.</p><p id="x_3_4_0_0_12">(<a class="cross-reference" href="#c:control-to-data">C8</a>) Tuplespaces take a wide variety of approaches to failure-handling <span class="citation citep">(<a class="citation" id="cite-79" href="#bib-Bakken1995">Bakken and Schlichting 1995</a>; <a class="citation" id="cite-80" href="#bib-Rowstron2000">Rowstron 2000</a>)</span>. In <span class="small-caps">Lime</span>, in particular, tuples are localized to tuplespace <em>fragments</em> associated with individual agents. These fragments automatically combine when agents find themselves in a common context. Agent failure or disconnection removes its tuplespace fragment from the aggregate whole. While <span class="small-caps">Lime</span> does not offer the ability to react to removal of individual tuples, it can be configured to insert <tt>_host_gone</tt> tuples into the space when it detects a disconnection. By reacting to <em>appearance</em> of <tt>_host_gone</tt> tuples, applications can perform coarse-grained cleaning of the knowledgebase after disconnection or failure. Separately, TOTAM's per-tuple <em>leases</em> <span class="citation citep">(<a class="citation" id="cite-81" href="#bib-GonzalezBoix2014">González Boix et al. 2014</a>)</span> give an upper bound on tuple lifetime. Our example chat room is written in an imaginary tuplespace dialect lacking fine-grained reactions to tuple withdrawal, and thus inserts <tt>Absent</tt> records upon termination (lines 4, 8, and 17 in figure <a class="cross-reference" href="#fig:Tuplespace-style-chat-room">8</a>) to maintain its invariants.</p><p id="x_3_4_0_0_13">(<a class="cross-reference" href="#c:consistency">C6</a>) Reactions and <tt>copy-collect</tt> allow maintenance of eventually-consistent views and production of consistent snapshots of the contents of a tuplespace, respectively. However, operations like <tt>rd</tt> are not only non-deterministic but non-atomic in the sense that by the time the existence of a particular tuple is signaled, that tuple may have been removed by a third party. Tuplespaces, then, offer some mechanisms by which the consistency of the various local replicas of tuplespace contents may be maintained and reasoned about. In contrast, most DBMS systems do not offer such mechanisms for reasoning about and maintaining a clients local copy of data authoritatively stored at a server. Instead, a common approach is to use transactions to atomically query and then alter information. The effect of this is to bound the lifetime of local views on global state, ensuring that while they exist, they fit in to the transactional framework on offer, and that after their containing transaction is over, they cannot escape to directly influence further computation.</p><p id="x_3_4_0_0_14">(<a class="cross-reference" href="#c:resources">C9</a>) Detection of demand for some resource can be done using tuples indicating demand and corresponding reactions. The associated callback can allocate and offer access to the demanded resource. In systems like TOTAM, retraction of a demand tuple can be interpreted as the end of the need for the resource it describes; in less advanced tuplespaces, release of resources must be arranged by other means.</p><p id="x_3_4_0_0_15">(<a class="cross-reference" href="#c:debuggability">C10</a>) Both tuplespaces and external databases give excellent visibility into application state, on the condition that the tuplespace or database is the <em>sole</em> locus of such state. In cases where this assumption holds, the entirety of the state of the group is visible as the current contents of the shared store. This unlocks the possibility of rich tooling for querying and modifying this state. Such tooling is a well-integrated part of existing DBMS ecosystems. In principle, recording and display of traces of interactions with the shared store could also be produced and used in visualization or debugging.</p><p id="x_3_4_0_0_16">(<a class="cross-reference" href="#c:evolvability">C11</a>) The original tuplespace model of Linda lacked non-blocking operations, leading it to suffer from usability flaws well-known from the context of synchronous IPC. As Elphinstone and Heiser write,</p>
<blockquote id="x_3_4_0_0_18">
<p id="x_3_4_0_0_17">While certainly minimal, and simple conceptually and in implementation, experience taught us significant drawbacks of [the model of synchronous IPC as the only mechanism]: it forces a multi-threaded design onto otherwise simple systems, with the resulting synchronisation complexities. <span class="citation citep">(<a class="citation" id="cite-82" href="#bib-Elphinstone2013">Elphinstone and Heiser 2013</a>)</span></p></blockquote><p id="x_3_4_0_0_19">These problems are significantly mitigated by the addition of <span class="small-caps">Lime</span>'s reactions and the later developments of TOTAM's context-aware tuplespace programming. Generally speaking, tuplespace-based designs have moved from synchronous early approaches toward asynchronous operations, and this has had benefits for extending the interactions of a given component as well as extending the scope of a given conversation. External DBMS systems are generally neutral when it comes to programming APIs, but many popular client libraries offer synchronous query facilities only, lack support for asynchronous operations, and offer only limited support for triggers.</p><p id="x_3_4_0_0_20">(<a class="cross-reference" href="#c:durability">C12</a>) External DBMS systems offer outstanding support for long-lived application state, making partial restarts and partial code upgrades a normal part of life with a DBMS application. Transactionality helps ensure that application restarts do not corrupt shared state. Tuplespaces in principle offer similarly good support.</p><p id="x_3_4_0_0_21">Finally, the two models, viewed abstractly, suffer from a lack of proper integration with host languages. The original presentation of tuplespaces positions the idea as a complete, independent language design; in reality, tuplespaces tend to show up as libraries for existing languages. Databases are also almost always accessed via a library. As a result, developers must often follow design patterns to close the gap between the linguistic capabilities of the language and their programming needs. Worse, they also have to deploy several different coordination mechanisms, without support from their chosen language and without a clear way of resolving any incompatibilities.</p>
<h4 id="x_3_5_0_0_1"><a name="toc_3.5"></a><span class="counter section"><span>3.5</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:The-fact-space-model"></a><a name="sec:The-fact-space-model"></a>The fact space model</span></h4><p id="x_3_5_0_0_2">The <em>fact space model</em> <span class="citation citep">(<a class="citation" id="cite-83" href="#bib-Mostinckx2007">Mostinckx et al. 2007</a>)</span> synthesizes rule-based systems and a rich tuplespace model with actor-based programming in a mobile, ad-hoc networking setting to yield a powerful form of context-aware programming. The initial implementation of the model, dubbed <span class="small-caps">Crime</span>, integrates a RETE-based rule engine <span class="citation citep">(<a class="citation" id="cite-84" href="#bib-Forgy1982">Forgy 1982</a>)</span> with the TOTAM tuplespace and a functional reactive programming (FRP) library <span class="citation citep">(<a class="citation" id="cite-85" href="#bib-Elliott1997">Elliott and Hudak 1997</a>; <a class="citation" id="cite-86" href="#bib-Bainomugisha2013">Bainomugisha et al. 2013</a>)</span> atop AmbientTalk, an object-oriented actor language in the style of E <span class="citation citep">(<a class="citation" id="cite-87" href="#bib-VanCutsem2014">Van Cutsem et al. 2014</a>)</span>. AmbientTalk is unusual among actor languages for its consideration of multicast communication and coordination. In its role as “language laboratory”, it has incorporated ideas from many other programming paradigms. AmbientTalk adds distributed service discovery, error handling, anycast and multicast to an actor-style core language intended for a mobile, ad-hoc network context; TOTAM supplements this with a distributed database, and the rule engine brings logic programming to the table.</p><p id="x_3_5_0_0_3">In the words of Mostinckx et al.,</p>
<blockquote id="x_3_5_0_0_5">
<p id="x_3_5_0_0_4">The Fact Space model is a coordination model which provides applications with a federated fact space: a distributed knowledge base containing logic facts which are implicitly made available for all devices within reach. [...] [T]he Fact Space model combines the notion of a federated fact space with a logic coordination language. <span class="citation citep">(<a class="citation" id="cite-88" href="#bib-Mostinckx2008a">Mostinckx, Lombide Carreton and De Meuter 2008</a>)</span></p></blockquote>
<div class="footnote" id="fn_3_26"><span class="counter footnote-counter"><span>26</span></span>When facts in the space are chosen to correspond to observable aspects of a program's context, this yields <em>context-aware programming</em>: programs react to relevant changes in their environment.<span class="plain-layout-boundary"></span></div><p id="x_3_5_0_0_6">Tuples placed within the TOTAM tuplespace are interpreted as ground facts in the Prolog logic-programming sense. Insertions correspond to Prolog's <tt>assert</tt>; removals to <tt>retract</tt>. TOTAM's reactions, which unlike <span class="small-caps">Lime</span> may be triggered on either insertion or removal of tuples, allow connection of changes in the tuplespace to the inputs to the RETE-based rule engine, yielding forward-chaining logic programming driven by activity in the common space.<label class="footnote-number" for="fn_3_26">26</label></p>
<figure id="x_3_5_0_0_8"><a name="fig:Factspace-style-chat-room"></a>
<pre class="listing" id="x_3_5_0_0_7"><code>def userAgent(name, socket)
whenever: [Present, ?who] read: { socket.println(who + " arrived") }
outOfContext: { socket.println(who + " left") }
whenever: [Message, ?who, ?what] read: { socket.println(who + ": " + what) }
publish: [Present, name]
previousLine = nil
while (line = socket.readLine()) != nil
if previousLine != nil: inp([Message, name, previousLine])
publish: [Message, name, line]
previousLine = line
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>9</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Factspace-style-chat-room"></a>Fact space style chat room user agent<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_5_0_0_9">Figure <a class="cross-reference" href="#fig:Factspace-style-chat-room">9</a> sketches a pseudo-code user agent program. An actor running <tt>userAgent</tt> is created for each connecting user. As it starts up, it registers two reactions. The first (lines 23) reacts to appearance <em>and disappearance</em> of <tt>Present</tt> tuples. The second (line 4) reacts to each <tt>Message</tt> tuple appearing in the space. Line 5 places a <tt>Present</tt> tuple representing the current user in the tuplespace, where it will be detected by peers. Lines 610 enter a loop, waiting for user input and replacing the user's previous <tt>Message</tt>, if any, with a new one.</p><p id="x_3_5_0_0_10">(<a class="cross-reference" href="#c:conversation-size">C1</a>; <a class="cross-reference" href="#c:demux">C2</a>; <a class="cross-reference" href="#c:data-to-control">C7</a>) The TOTAM tuplespace offers multi-party communication, and the rule engine allows installation of pattern-based reactions to events, resulting in automatic demultiplexing and making for a natural connection from data flow to associated control flow. Where an interaction serves to open a conversational frame for a sub-conversation, additional reactions may be installed; however, there is no linguistic representation of such conversational frames, meaning that any logical association between conversations must be manually expressed and maintained.</p><p id="x_3_5_0_0_11">(<a class="cross-reference" href="#c:integration">C3</a>; <a class="cross-reference" href="#c:signalling">C4</a>) AmbientTalk's <em>reactive context-aware collections</em> <span class="citation citep">(<a class="citation" id="cite-89" href="#bib-Mostinckx2008a">Mostinckx, Lombide Carreton and De Meuter 2008</a>)</span> allow automatic integration of conclusions drawn by the rule engine with collection objects such as sets and hash tables. Each collection object is manifested as a <em>behavior</em> in FRP terminology, meaning that changes to the collection can in turn trigger downstream reactions depending on the collection's value. However, achieving the effect of propagating changes in local variables as changes to tuples in the shared space is left to programmers.</p><p id="x_3_5_0_0_12">(<a class="cross-reference" href="#c:integrity">C5</a>; <a class="cross-reference" href="#c:consistency">C6</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>) The Fact Space model removes tuples upon component failure. Conclusions drawn from rules depending on removed facts are withdrawn in turn. Programs thereby enjoy logical consistency after partial failure. However, automatic retraction of tuples is performed <em>only</em> in cases of disconnection. When a running component is engaged in multiple conversations, and one of them comes to a close, there is no mechanism provided by which facts relating to the terminated conversation may be automatically cleaned up. Programmers manually delete obsolescent facts or turn to a strategy borrowed from the E language, namely creation of a separate actor for each sub-conversation. If they choose this option, however, the interactions among the resulting plethora of actors may increase overall system complexity.</p>
<figure id="x_3_5_0_0_15"><a name="fig:Aggregating-distinct-facts"></a>
<p class="align-center" id="x_3_5_0_0_14">
<pre class="listing" id="x_3_5_0_0_13"><code>def userAgent(name, socket)
presentUsers = set()
whenever: [Present, ?who, ?status]
read: {
if who not in presentUsers
presentUsers.add(who)
socket.println(who + " arrived")
socket.println(who + " status: " + status)
}
outOfContext: {
if rd([Present, who, ?anyStatus]) == nil
presentUsers.remove(who)
socket.println(who + " left")
}
...
</code></pre></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>10</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Aggregating-distinct-facts"></a>Aggregating distinct facts<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_3_27"><span class="counter footnote-counter"><span>27</span></span><a href="https://soft.vub.ac.be/amop/crime/download">https://soft.vub.ac.be/amop/crime/download</a><span class="plain-layout-boundary"></span></div><p id="x_3_5_0_0_16">(<a class="cross-reference" href="#c:resources">C9</a>) The ability to react to removal as well as insertion of tuples allows programs to match supply of some service to demand, by interpreting particular assertions as demand for some resource. This can, in principle, allow automatic resource management; however, this is only true if all allocation of and interaction with such resources is done via the tuple space. For example, if the actor sketched in figure <a class="cross-reference" href="#fig:Factspace-style-chat-room">9</a> were to crash, then absent explicit exception-handling code, the connected <tt>socket</tt> would leak, remaining open.<label class="footnote-number" for="fn_3_27">27</label> Additionally, in situations where tuples may be interpreted simultaneously at a coarse-grained and fine-grained level, some care must be taken in interpreting tuple arrival and departure events. For example, imagine a slight enhancement of our example program, where we include a user-chosen <em>status</em> message in our <tt>Present</tt> tuples. In order to react both to appearance and disappearance of a user as well as a change in a user's status, we must interpret <tt>Present</tt> tuples as sketched in figure <a class="cross-reference" href="#fig:Aggregating-distinct-facts">10</a>. There, <tt>Present</tt> tuples are aggregated by their <tt>who</tt> fields, ignoring their <tt>status</tt> fields, in addition to being interpreted entire. The <tt>presentUsers</tt> collection serves as intermediate state for a kind of <tt>SELECT DISTINCT</tt> operation, indicating whether any <tt>Present</tt> tuples for a particular user exist at all in the tuplespace. In the retraction handler (lines 1014) we explicitly check whether any <tt>Present</tt> tuples for the user concerned remain in the space, only updating <tt>presentUsers</tt> if none are left. This avoids incorrectly claiming that a user has left the chat room when they have merely altered their status message.</p><p id="x_3_5_0_0_17">An alternative approach to the problem is to make use of a feature of <span class="small-caps">Crime</span> not yet described. The <span class="small-caps">Crime</span> implementation of the fact space model exposes the surface syntax of the included rule engine to the programmer, allowing logic program fragments to be written using a Prolog-like syntax and integrated with a main program written in AmbientTalk. This could allow a small program</p><p id="x_3_5_0_0_19">
<p class="align-center" id="x_3_5_0_0_18"><tt>UserPresent(?who) :- Present(?who,?status).</tt></p></p><p id="x_3_5_0_0_20">to augment the tuplespace with <tt>UserPresent</tt> tuples whenever any <tt>Present</tt> tuple for a given user exists at all. On the AmbientTalk side, programs would then react separately to appearance and disappearance of <tt>UserPresent</tt> and <tt>Present</tt> tuples.</p><p id="x_3_5_0_0_21">(<a class="cross-reference" href="#c:debuggability">C10</a>) Like tuplespaces generally, the fact space model has great potential for tool support and system state visualization. However, only those aspects of a program communicating via the underlying tuplespace benefit from its invariants. In the case of the <span class="small-caps">Crime</span> implementation based on AmbientTalk, only selected inter-component interactions travel via the tuplespace and rule engine, leaving other interactions out of reach of potential fact-space-based tools. Programmers must carefully combine reasoning based on the invariants of the fact space model with the properties of the other mechanisms available for programmer use, such as AmbientTalk's own inter-actor message delivery, service discovery and broadcast facilities.</p><p id="x_3_5_0_0_22">(<a class="cross-reference" href="#c:evolvability">C11</a>) Extending a conversation to new components and introducing an existing component to an additional conversation are both readily supported by the fact space model as implemented in <span class="small-caps">Crime</span>. However, because no automatic support for release of conversation-associated state exists (other than outright termination of an entire actor), programmers must carefully consider the interactions among individual components. When one of an actor's conversations comes to a close but other conversations remain active, the programmer must make sure to release local conversational state and remove associated shared tuples, but only when they are provably inaccessible to the remaining conversations.</p><p id="x_3_5_0_0_23">(<a class="cross-reference" href="#c:durability">C12</a>) <span class="small-caps">Crime</span>'s AmbientTalk foundation is inspired by E, and can benefit directly from research done on persistence and object upgrade in E-like settings <span class="citation citep">(<a class="citation" id="cite-90" href="#bib-Yoo2012">Yoo et al. 2012</a>; <a class="citation" id="cite-91" href="#bib-Miller2013">Miller, Van Cutsem and Tulloh 2013</a>)</span>.</p>
<h4 id="x_3_6_0_0_1"><a name="toc_3.6"></a><span class="counter section"><span>3.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Surveying-the-landscape"></a><a name="sec:Surveying-the-landscape"></a>Surveying the landscape</span></h4>
<figure class="fullwidth" id="x_3_6_0_0_5"><a name="fig:Surveying-the-landscape"></a>
<div class="frameless-box" id="x_3_6_0_0_4">
<div class="frameless-box" id="x_3_6_0_0_3">
<div class="tabular" id="x_3_6_0_0_2"><table class="tabular"><tr><td class="alignment-left valignment-top alignment-left valignment-top bottomline-true usebox-none"><a class="cross-reference" href="#Q-mechanism">K3bis</a> Mechanism<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Shared memory<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Message-passing<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Tuplespaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Fact spaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Ideal<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:conversation-size">C1</a> Conversation group size<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">arbitrary<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">point-to-point<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">arbitrary<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">arbitrary<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">arbitrary<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:demux">C2</a> Correlation/demultiplexing<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:integration">C3</a> Integration of state change<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:signalling">C4</a> Signaling of state change<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top bottomline-true usebox-none"><a class="cross-reference" href="#Q-robust-sharing">K4</a> Robustness<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Shared memory<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Message-passing<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Tuplespaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Fact spaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Ideal<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:integrity">C5</a> Maintain state integrity<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:consistency">C6</a> Ensure replica consistency<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">trivial<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">semi-automatic<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">automatic<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:data-to-control">C7</a> Data <span class="lyx-mathjax mathjax-inline">$\implies$</span> control flow<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">no<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">yes<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">yes<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">yes<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">yes<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:control-to-data">C8</a> Control <span class="lyx-mathjax mathjax-inline">$\implies$</span> data flow<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">no<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">partial<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">no<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">coarse-grained<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">fine-grained<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:resources">C9</a> Resource management<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">manual<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">coarse-grained<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">fine-grained<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top bottomline-true usebox-none"><a class="cross-reference" href="#Q-robust-goal-change">K6</a> Operability<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Shared memory<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Message-passing<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Tuplespaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Fact spaces<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top bottomline-true usebox-none">Ideal<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:debuggability">C10</a> Debuggability/visualizability<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">poor<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">wide range<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">potentially good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">potentially good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:evolvability">C11</a> Evolvability<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">poor<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">moderate<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">moderate<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-left valignment-top usebox-none">&emsp;<a class="cross-reference" href="#c:durability">C12</a> Durability<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">poor<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">moderate/good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none">good<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td></tr></table></div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>11</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Surveying-the-landscape"></a>Surveying the landscape<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_3_6_0_0_6">Figure <a class="cross-reference" href="#fig:Surveying-the-landscape">11</a> summarizes this chapter's analysis. Each of the first four columns in the table shows, from the programmer's point of view, the support they can expect from a programming language taking the corresponding approach to concurrency. Each row corresponds to one of the properties of concurrency models introduced in figure <a class="cross-reference" href="#fig:Characteristics-of-approaches-to-concurrency">3</a>. A few terms used in the table require explanation. An entry of “manual” indicates that the programmer is offered no special support for the property. An entry of “semi-automatic” indicates that some form of support for the property is available, at least for specialized cases, but that general support is again left to the programmer. For example, channel-based languages can automatically demultiplex conversations, but only so long as channels correspond one-to-one to conversations, and the fact space model automatically preserves integrity of conversational state, but only where the end of an actor's participation in a conversation is marked by disconnection from the shared space. Finally, an entry of “automatic” indicates that an approach to concurrency offers strong, general support for the property. An example is the fact space model's ability to integrate changes in the shared space with local variables via its reactive context-aware collections.</p><p id="x_3_6_0_0_7">While the first four columns address the properties of existing models of concurrency, the final column of the table identifies an “ideal” point in design space for us to aim towards in the design of new models.</p><p id="x_3_6_0_0_8">(<a class="cross-reference" href="#c:conversation-size">C1</a>; <a class="cross-reference" href="#c:demux">C2</a>; <a class="cross-reference" href="#c:integration">C3</a>; <a class="cross-reference" href="#c:signalling">C4</a>) We would like a flexible communications mechanism accommodating many-to-many as well as one-to-one conversations. A component should be able to engage in multiple conversations, without having to jump through hoops to do so. Events should map to event handlers directly in terms of their domain-level meaning. Since conversations come with conversational frames, and conversational frames scope state and behavior, such frames and their interrelationships should be explicit in program code. As conversations proceed, the associated conversational state evolves. Changes to that state should automatically be integrated with local views on it, and changes in local state should be able to be straightforwardly shared with peers. Agents should be offered the opportunity to react to all kinds of state changes.</p><p id="x_3_6_0_0_9">(<a class="cross-reference" href="#c:integrity">C5</a>; <a class="cross-reference" href="#c:consistency">C6</a>) We would like to automatically enforce application-level invariants regarding shared, conversational state. In case of partial failure, we should be able to identify and discard damaged portions of conversational state. Where replicas of a piece of conversational state exist, we would like to be able to reason about their mutual consistency. (<a class="cross-reference" href="#c:data-to-control">C7</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>) Hewitts criterion that “control and data flow are inseparable” should hold as far as possible, both in terms of control flow being manifestly influenced by data flow and in terms of translation of control effects such as exceptions into visible changes in the common conversational context. (<a class="cross-reference" href="#c:resources">C9</a>) Since conversations often involve associated resources, we would like to be able to connect allocation and release of resources with the lifecycles of conversational frames.</p><p id="x_3_6_0_0_10">(<a class="cross-reference" href="#c:debuggability">C10</a>; <a class="cross-reference" href="#c:evolvability">C11</a>; <a class="cross-reference" href="#c:durability">C12</a>) Given the complexity of concurrent programming, we would like the ability to build tools to gain insight into system state and to visualize both correct and abnormal behavior for debugging and development purposes. Modification of our programs should easily accommodate changes in the scope of a given conversation among components, as well as changes to the set of interactions a given component is engaged in. Finally, robustness involves tolerance of partial failure and partial restarts; where long-lived application state exists, support for code upgrades should also be offered.</p></p>
<h2 id="x_3_0_0_0_1"><a name="toc_II"></a><span class="counter part"><span>II</span></span><span class="heading-text part">Theory</span></h2>
<h3 class="unnumbered" id="x_3_0_0_0_2"><a name="toc_3"></a><span class="heading-text chapter">Overview</span></h3><p id="x_3_0_0_0_3"><span class="small-caps">Syndicate</span> is a design in two parts. The first part is called the <em>dataspace model</em>. This model offers a mechanism for communication and coordination within groups of concurrent components, plus a mechanism for organizing such groups and relating them to each other in hierarchical assemblies. The second part is called the <em>facet model</em>. This model introduces new language features to address the challenges of describing an actor's participation in multiple simultaneous conversations.</p><p id="x_3_0_0_0_4">Chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> fleshes out the informal description of the dataspace model of section <a class="cross-reference" href="#sec:Syndicate's-approach-to-concurrency">2.5</a> with a formal semantics. The semantics describes a hierarchical structure of components in the shape of a tree. Intermediate nodes in the tree are called <em>dataspaces</em>. From the perspective of the dataspace model, leaf nodes in the tree are modeled as (pure) event-transducer functions; their internal structure is abstracted away.</p><p id="x_3_0_0_0_5">Chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> describes the facet model part of the <span class="small-caps">Syndicate</span> design, addressing the internal structure of the leaf actors of the dataspace model. Several possible means of interfacing a programming language to a dataspace exist. The simplest approach is to directly encode the primitives of the model in the language of choice, but this forces the programmer to attend to much detail that can be handled automatically by a suitable set of linguistic constructs. The chapter proposes such constructs, augments a generic imperative language model with them, and gives a formal semantics for the result. Together, the dataspace and facet models form a complete design for extending a non-concurrent host language with concurrency.</p>
<div class="lyx-mathjax mathjax-definitions" id="x_4_2_0_0_45">\(\newcommand{\Rnew}{R_{\mathit{new}}}
\newcommand{\Rold}{\rlap{R_{\mathit{old}}}\phantom{\Rnew}}{R_{\mathit{old}}}
\newcommand{\ROUTESnew}{\ROUTES_{\mathit{new}}}
\newcommand{\ROUTESold}{\rlap{\ROUTES_{\mathit{old}}}\phantom{\ROUTESnew}}{\ROUTES_{\mathit{old}}}
\)</div><p id="x_4_8_0_0_18">
<h3 id="x_4_0_0_0_1"><a name="toc_4"></a><span class="counter chapter"><span>4</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES"></a><a name="CHAP:COMPUTATIONAL-MODEL-I:DATASPACES"></a>Computational Model I: The Dataspace Model</span></h3><p id="x_4_0_0_0_2">This chapter describes the dataspace model using mathematical syntax and semantics, including theorems about the model's key properties. The goal of the model presented here is to articulate a language design idea. We wish to show how to construct a concurrent language from a generic base language via the addition of a fixed communication layer. The details of the base language are not important, and are thus largely abstracted away. We demand that the language be able to interpret dataspace events, encode dataspace actions, map between its internal data representations and the assertion values of the dataspace model, and confine its computational behavior to that expressible with a total mathematical function. We make the state of each actor programmed in the (extended) base language explicit, require that its behavior be specified as a state-transition function, and demand that it interacts with its peers exclusively via the exchange of immutable messages—not by way of effects. This strict enforcement of message-passing discipline does not prevent us from using an imperative base language, as long as its effects do not leak. In other words, the base could be a purely functional language such as Haskell, a higher-order imperative language such as Racket, or an object-oriented language such as JavaScript.</p><p id="x_4_0_0_0_3">The dataspace model began life under the moniker “Network Calculus” (NC) <span class="citation citep">(<a class="citation" id="cite-92" href="#bib-Garnock-Jones2014">Garnock-Jones, Tobin-Hochstadt and Felleisen 2014</a>)</span>, a formal model of publish-subscribe networking incorporating elements of <em>presence</em> as such, rather than the more general state-replication system described in the follow-up paper <span class="citation citep">(<a class="citation" id="cite-93" href="#bib-Garnock-Jones2016a">Garnock-Jones and Felleisen 2016</a>)</span> and refined in this dissertation. The presentation in this chapter draws heavily on that of the latter paper, amending it in certain areas to address issues that were not evident at the time.</p>
<h4 id="x_4_1_0_0_1"><a name="toc_4.1"></a><span class="counter section"><span>4.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Informal-DS-semantics"></a><a name="sec:Informal-DS-semantics"></a>Abstract dataspace model syntax and informal semantics</span></h4>
<figure class="fullwidth" id="x_4_1_0_0_3"><a name="fig:DS-program-syntax"></a>
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_2">\begin{align*}
\textrm{Programs }P\in\TProg &amp; ::=\AActor{\CBoot}{\ROUTES}\;|\;\ADS{\VECOF P}\\
\textrm{Events }e\in\TEvt &amp; ::=\AMsg c\;|\;\ROUTES\\
\textrm{Actions }a\in\TAct &amp; ::=\AMsg c\;|\;\ROUTES\;|\:P\\
\\
\textrm{Boot functions }\CBoot\in\TBoot &amp; =\T 1\rightarrow\INIT{\VECOF{\TAct}\times\TBehPack{\tau}}+\EXIT{\VECOF{\TAct}}\\
\textrm{Behavior functions }\CBehF\in\TBehF{\tau} &amp; =\TEvt\times\tau\rightarrow\CONTINUE{\VECOF{\TAct}\times\tau}+\EXIT{\VECOF{\TAct}}\\
\\
\textrm{Assertion/Message values }v,c\in\TVal &amp; ::=b\;|\;(c,\dots)\\
\textrm{Assertion sets }\ROUTES\in\TASet &amp; =\SETOF{\TVal}\\
\textrm{Base values }b\in\TBVal &amp; =\textrm{Atoms, incl. strings, symbols, numbers, etc.}\\
\\
\Obs c &amp; \triangleq(\mathtt{observe},c)\\
\Out c &amp; \triangleq(\mathtt{outbound},c)\\
\In c &amp; \triangleq(\mathtt{inbound},c)
\end{align*}
</div><figcaption><span class="counter figure"><span>12</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:DS-program-syntax"></a>Syntax of dataspace model programs<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_4_28"><span class="counter footnote-counter"><span>28</span></span>Design note: An alternative, roughly equivalent design omits <span class="lyx-mathjax mathjax-inline">$\TBoot$</span> in favor of <span class="lyx-mathjax mathjax-inline">$\AActorName$</span> carrying some <span class="lyx-mathjax mathjax-inline">$\tau$</span>, <span class="lyx-mathjax mathjax-inline">$\CBehF\in\TBehF{\tau}$</span>, and <span class="lyx-mathjax mathjax-inline">$u\in\tau$</span> directly, with that <span class="lyx-mathjax mathjax-inline">$\CBehF$</span> receiving a distinct, one-time <em>startup</em> event. Yet another option is to define <span class="lyx-mathjax mathjax-inline">$\TBehF{\tau}$</span> to yield <span class="lyx-mathjax mathjax-inline">$\CONTINUE{\VECOF{\TAct}\times\TBehPack{\tau}}$</span>, giving a “become”-like semantics <span class="citation citep">(<a class="citation" id="cite-94" href="#bib-Agha1997">Agha et al. 1997</a>)</span>. Neither variation simplifies the presentation. I have chosen the variation described because it seems to me to capture the idea of a one-time, staged startup computation without sacrificing a fixed behavior function or introducing a startup pseudo-event.<span class="plain-layout-boundary"></span></div><p id="x_4_1_0_0_4">Figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a> displays the syntax of dataspace model programs. Each program <span class="lyx-mathjax mathjax-inline">$P$</span> is an instruction to create a single actor: either a <em>leaf actor</em> or a <em>dataspace actor</em>. A leaf actor has the shape <span class="lyx-mathjax mathjax-inline">$\AActor{\CBoot}{\ROUTES}$</span>. Its initial assertions are described by the set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>, while its boot function <span class="lyx-mathjax mathjax-inline">$\CBoot$</span> embodies the first few computations the actor will perform. The boot function usually yields an <span class="lyx-mathjax mathjax-inline">$\INIT{\cdot}$</span> record specifying a sequence of initial actions <span class="lyx-mathjax mathjax-inline">$\VECOF a\in\VECOF{\TAct}$</span> along with an existentially-quantified package <span class="lyx-mathjax mathjax-inline">$\CBehPack{\tau}{\CBehF}u$</span>. This latter specifies the type <span class="lyx-mathjax mathjax-inline">$\tau$</span> of the actor's private state, the initial private state value <span class="lyx-mathjax mathjax-inline">$u\in\tau$</span>, and the actor's permanent event-transducing behavior function <span class="lyx-mathjax mathjax-inline">$\CBehF\in\TBehF{\tau}$</span>. Alternatively, the boot function may decide that the actor should immediately terminate, in which case it yields an <span class="lyx-mathjax mathjax-inline">$\EXIT{\cdot}$</span> record bearing a sequence of <em>final </em>actions <span class="lyx-mathjax mathjax-inline">$\VECOF a\in\VECOF{\TAct}$</span> for the short-lived actor to perform before it becomes permanently inert.<label class="footnote-number" for="fn_4_28">28</label> A dataspace actor has the shape <span class="lyx-mathjax mathjax-inline">$\ADS{\VECOF P}$</span> and creates a group of communicating actors sharing a new assertion store. Each <span class="lyx-mathjax mathjax-inline">$P$</span> in the sequence of programs contained in the definition of a dataspace actor will form one of the initial actors placed in the group as it starts its existence.</p><p id="x_4_1_0_0_5">Each leaf actor behavior function consumes an event plus its actor's current state. The function computes either a <span class="lyx-mathjax mathjax-inline">$\CONTINUE{\cdot}$</span> record, namely a sequence of desired actions plus an updated state value, or an <span class="lyx-mathjax mathjax-inline">$\EXIT{\cdot}$</span> record carrying a sequence of desired <em>final</em> actions alone in case the actor decides to request its own termination. We require that such behavior functions be total. If the base language supports exceptions, any uncaught exceptions or similar must be translated into an explicit termination request. If this happens, we say that the actor has crashed, even though it returned a valid termination request in an orderly way.</p><p id="x_4_1_0_0_6">In the <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus, a program is usually a combination of an inert part—a function value—and an input value. In the dataspace model, delivering an event to an actor is analogous to such an application. However, the pure <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus has no analogue of the actions produced by dataspace model actors.</p><p id="x_4_1_0_0_7">A dataspace model actor may produce actions like those in the traditional actor model, namely sending messages <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span> and spawning new actors <span class="lyx-mathjax mathjax-inline">$P$</span>, but it may also produce <em>state change notifications (SCNs)</em> <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>. These convey sets of assertions an actor wishes to publish to its containing dataspace.</p><p id="x_4_1_0_0_8">As a dataspace interprets an SCN action, it updates its assertion store. It tracks every assertion made by each contained actor. It not only maps each actor to its current assertions, but each active assertion to the set of actors asserting it. The assertions of each actor, when combined with the assertions of its peers, form the overall set of assertions present in the dataspace.</p><p id="x_4_1_0_0_9">When an actor issues an SCN action, the new assertion set completely replaces all previous assertions made by that actor. To retract an assertion, the actor issues a state change notification action lacking the assertion concerned. For example, imagine an actor whose most-recently-issued SCN action conveyed the assertion set <span class="lyx-mathjax mathjax-inline">$\{a,b,c\}$</span>. By issuing an SCN action <span class="lyx-mathjax mathjax-inline">$\{a,b\}$</span>, the actor would achieve the effect of retracting the assertion <span class="lyx-mathjax mathjax-inline">$c$</span>. Alternatively, issuing an SCN <span class="lyx-mathjax mathjax-inline">$\{a,b,c,d\}$</span> would augment the actor's assertion set in the assertion store with a new assertion <span class="lyx-mathjax mathjax-inline">$d$</span>. Finally, the SCN <span class="lyx-mathjax mathjax-inline">$\{a,b,d\}$</span> describes assertion of <span class="lyx-mathjax mathjax-inline">$d$</span> simultaneous with retraction of <span class="lyx-mathjax mathjax-inline">$c$</span>.</p>
<div class="footnote" id="fn_4_29"><span class="counter footnote-counter"><span>29</span></span>Clearly, implementers must take pains to keep representations of sets specified in this manner tractable. We discuss this issue in more detail in section <a class="cross-reference" href="#sec:Representing-Assertion-Sets">7.1</a>.<span class="plain-layout-boundary"></span></div><p id="x_4_1_0_0_10">We take the liberty of using wildcard <span class="lyx-mathjax mathjax-inline">$\star$</span> as a form of assertion set comprehension. For now, when we write expressions such as <span class="lyx-mathjax mathjax-inline">$\{(\mathtt{a},\star)\}$</span>, we mean the set of all pairs having the atom <span class="lyx-mathjax mathjax-inline">$\mathtt{a}$</span> on the left. In addition, we use three syntactic shorthands as constructors for commonly-used structures: <span class="lyx-mathjax mathjax-inline">$\Obs c$</span>, <span class="lyx-mathjax mathjax-inline">$\Out c$</span> and <span class="lyx-mathjax mathjax-inline">$\In c$</span> are abbreviations for tuples of the atoms <tt>observe</tt>, <tt>outbound</tt> and <tt>inbound</tt>, respectively, with the value <span class="lyx-mathjax mathjax-inline">$c$</span>. Thus, <span class="lyx-mathjax mathjax-inline">$\{\Obs{\star}\}$</span> means <span class="lyx-mathjax mathjax-inline">$\{\Obs c\,|\,c\in\TVal\}$</span>.<label class="footnote-number" for="fn_4_29">29</label></p><p id="x_4_1_0_0_11">When an actor issues an assertion of shape <span class="lyx-mathjax mathjax-inline">$\Obs c$</span>, it expresses an interest in being informed of all assertions <span class="lyx-mathjax mathjax-inline">$c$</span>. In other words, an assertion <span class="lyx-mathjax mathjax-inline">$\Obs c$</span> acts as a subscription to <span class="lyx-mathjax mathjax-inline">$c$</span>. Similarly, <span class="lyx-mathjax mathjax-inline">$\Obs{\Obs c}$</span> specifies interest in being informed about assertions of shape <span class="lyx-mathjax mathjax-inline">$\Obs c$</span>, and so on. The dataspace sends a state change notification <em>event</em> to an actor each time the set of assertions matching the actor's interests changes.</p>
<div class="footnote" id="fn_4_30"><span class="counter footnote-counter"><span>30</span></span>However, unlike most other assertions, they directly represent epistemic knowledge.<span class="plain-layout-boundary"></span></div><p id="x_4_1_0_0_12">An actor's subscriptions are assertions like any other.<label class="footnote-number" for="fn_4_30">30</label> State change notifications thus give an actor control over its subscriptions as well as over any other information it wishes to make available to its peers or acquire from them.</p>
<h6 class="unnumbered" id="x_4_1_0_0_13"><a name="toc_4.1"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Dataspace-ISWIM"></a><a name="par:Dataspace-ISWIM"></a>Dataspace “ISWIM”.</span></h6><p id="x_4_1_0_0_14">The examples in this chapter use a mathematical notation to highlight the essential aspects of the coordination abilities of the dataspace model without dwelling on base language details. While the notation used is not a real language (if you see what I mean <span class="citation citep">(<a class="citation" id="cite-95" href="#bib-Landin1966">Landin 1966</a>)</span>), it does have implemented counterparts in the prototypes of the dataspace model that incorporate Racket and JavaScript as base languages. These implementations were used to write programs which in turn helped build intuition and serve as a foundation for the full <span class="small-caps">Syndicate</span> design.</p><p id="x_4_1_0_0_15">We use <span class="lyx-mathjax mathjax-inline">$\mathit{italic}$</span> text to denote Dataspace ISWIM variables and <span class="lyx-mathjax mathjax-inline">$\mathtt{monospace}$</span> to denote literal atoms and strings. In places where the model demands a sequence of values, for example the actions returned from a behavior function, our language supplies a single list value <span class="lyx-mathjax mathjax-inline">$[a_{1},...,a_{n}]$</span>. We include list comprehensions <span class="lyx-mathjax mathjax-inline">$[a\,|\,a\in\TAct,P(a),...]$</span> because actors frequently need to construct, filter, and transform sequences of values. Similarly, we add syntax for sets <span class="lyx-mathjax mathjax-inline">$\{c_{1},...,c_{n}\}$</span>, including set comprehensions <span class="lyx-mathjax mathjax-inline">$\{c\,|\,c\in\TVal,P(c),...\}$</span>, and for tuples <span class="lyx-mathjax mathjax-inline">$(v_{1},...,v_{n})$</span>, to represent the sets and tuples needed by the model.</p><p id="x_4_1_0_0_17">We define functions using patterns over the language's values. For example, the leaf behavior function definition
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_16">\[
\mathit{box}\;(\AMsg{(\mathtt{set},\mathit{id},v_{c})},v_{o})\;=\CONTINUE{[\{\Obs{(\mathtt{set},\mathit{id},\star)},(\mathtt{value},\mathit{id},v_{c})\}],v_{c}}
\]
</div>introduces a function <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> that expects two arguments: a message and an arbitrary value. The <span class="lyx-mathjax mathjax-inline">$\AMsg{(\mathtt{set},\mathit{id},v_{c})}$</span> pattern for the former says it must consist of a triple with the atom <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span> on the left and arbitrary values in the center and right field. The function yields a <span class="lyx-mathjax mathjax-inline">$\CONTINUE{\cdot}$</span> record—it wishes to continue running—containing a pair whose left field is a sequence of actions and whose right field is the actor's new state value <span class="lyx-mathjax mathjax-inline">$v_{c}$</span>. The sequence of actions consists of only one element: a state change notification action bearing an assertion set. The assertion set is written in part using a wildcard denoting an infinite set, and in part using a simple value. The resulting assertion set thus contains not only the triple <span class="lyx-mathjax mathjax-inline">$(\mathtt{value},\mathit{id},v_{c})$</span> but also the infinite set of all <span class="lyx-mathjax mathjax-inline">$?$</span>-labeled triples with <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span> on the left and with <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> in the middle.</p>
<div class="theorem-like numbered example" id="x_4_1_0_0_26">
<div class="lyx-mathjax mathjax-definitions" id="x_4_1_0_0_18">\(\newcommand{\PRICEMILK}[1]{(\mathtt{price},\mathtt{milk},#1)}
\)</div>
<p id="x_4_1_0_0_21"><span class="counter numbered example"><span>4.1</span></span><a class="label-anchor" href="#example:price-milk"></a><a name="example:price-milk"></a>Suppose we wish to create an actor X with an interest in the price of milk. Here is how it might be written:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_19">\[
\AActor{f_{\mathit{bootX}}}{\{\Obs{\PRICEMILK{\star}}\}}
\]
</div>The comprehension defining its initial assertion set is interpreted to denote the set
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_20">\[
\{\Obs{\PRICEMILK c}\;|\;c\in\TVal\}
\]
</div></p>
<p id="x_4_1_0_0_22">If some peer Y previously asserted <span class="lyx-mathjax mathjax-inline">$\PRICEMILK{1.17}$</span>, this assertion is immediately delivered to X in a state change notification event. Infinite sets of interests thus act as <em>query patterns</em> over the shared dataspace.</p>
<p id="x_4_1_0_0_23">Redundant assertions do not cause change notifications. If actor Z subsequently also asserts <span class="lyx-mathjax mathjax-inline">$\PRICEMILK{1.17}$</span>, no notification is sent to X, since X has already been informed that <span class="lyx-mathjax mathjax-inline">$\PRICEMILK{1.17}$</span> has been asserted. However, if Z instead asserts <span class="lyx-mathjax mathjax-inline">$\PRICEMILK{9.25}$</span>, then a change notification is sent to X containing <em>both</em> asserted prices.</p>
<p id="x_4_1_0_0_24">Symmetrically, it is not until the last assertion of shape <span class="lyx-mathjax mathjax-inline">$\PRICEMILK p$</span> for some particular <span class="lyx-mathjax mathjax-inline">$p$</span> is retracted from the dataspace that X is sent a notification about the lack of assertions of shape <span class="lyx-mathjax mathjax-inline">$\PRICEMILK p$</span>.</p>
<p id="x_4_1_0_0_25">When an actor crashes, all its assertions are automatically retracted. By implication, if no other actor is making the same assertions at the time, then peers interested in the crashing actor's assertions are sent a state change notification event informing them of the retraction(s).</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_4_1_0_0_34">
<p id="x_4_1_0_0_28"><span class="counter numbered example"><span>4.2</span></span><a class="label-anchor" href="#example:reference-cell"></a><a name="example:reference-cell"></a>For a different example, consider an actor representing a shared mutable reference cell. A new box (initially containing <span class="lyx-mathjax mathjax-inline">$0$</span>) is created by choosing a name <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> and launching the actor
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_27">\[
\AActor{(\lambda().\INIT{[],\CBehPack{\TVal}{\mathit{box}}0})}{\{\Obs{(\mathtt{set},\mathit{id},\star)},(\mathtt{value},\mathit{id},0)\}}
\]
</div>The new actor's initial assertion set includes assertions of interest in <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span> messages labeled with <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> as well as of the fact that the <span class="lyx-mathjax mathjax-inline">$\mathtt{value}$</span> of box <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> is currently <span class="lyx-mathjax mathjax-inline">$0$</span>. Its behavior is given by the function <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> whose definition we saw earlier, its initial actions by the empty sequence, and its initial state is just <span class="lyx-mathjax mathjax-inline">$0$</span>. Upon receipt of a <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span> message bearing a new value <span class="lyx-mathjax mathjax-inline">$v_{c}$</span>, we may read off its response by consulting the definition of <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> above. The actor replaces its private state value with <span class="lyx-mathjax mathjax-inline">$v_{c}$</span> and constructs a single action specifying the new set of facts the actor wants to assert. This new set of facts includes the unchanged <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span>-message subscription as well as a new <span class="lyx-mathjax mathjax-inline">$\mathtt{value}$</span> fact, thereby replacing <span class="lyx-mathjax mathjax-inline">$v_{o}$</span> with <span class="lyx-mathjax mathjax-inline">$v_{c}$</span> in the shared dataspace.</p>
<p id="x_4_1_0_0_30">To read the value of the box, clients either include an appropriate assertion in their initially declared interests or issue it later:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_29">\[
\AActor{\left(\lambda().\INIT{[],\CBehPack{\T1}{\mathit{boxClient}}{()}}\right)}{\{\Obs{(\mathtt{value},\mathit{id},\star)}\}}
\]
</div>As corresponding facts come and go in response to actions taken by the box actor they are forwarded to interested parties. For example, the <span class="lyx-mathjax mathjax-inline">$\mathit{boxClient}$</span> behavior function responds to notification of a change in the contents of the box by issuing an instruction to update the box:</p>
<p id="x_4_1_0_0_32">
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_31">\[
\mathit{boxClient}\;(\{(\mathtt{value},\mathit{id},v)\},())\;=\CONTINUE{[\AMsg{(\mathtt{set},\mathit{id},v+1)}],()}
\]
</div></p>
<p id="x_4_1_0_0_33">The behavior of the <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> and <span class="lyx-mathjax mathjax-inline">$\mathit{boxClient}$</span> actors, when run together in a dataspace, is to repeatedly increment the number held in the <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_4_1_0_0_40">
<p id="x_4_1_0_0_35"><span class="counter numbered example"><span>4.3</span></span><a class="label-anchor" href="#example:demand-matcher"></a><a name="example:demand-matcher"></a>Our next example demonstrates <em>demand matching</em>. The need to measure demand for some service and allocate resources in response appears in different guises in a wide variety of concurrent systems. Here, we imagine a client, <span class="lyx-mathjax mathjax-inline">$\mathtt{A}$</span>, beginning a conversation with some service by adding <span class="lyx-mathjax mathjax-inline">$(\mathtt{hello},\mathtt{A})$</span> to the shared dataspace. In response, the service should create a worker actor to talk to <span class="lyx-mathjax mathjax-inline">$\mathtt{A}$</span>.</p>
<div class="footnote" id="fn_4_31"><span class="counter footnote-counter"><span>31</span></span>Implementations of the dataspace model to date internalize assertion sets as <em>tries</em> (section <a class="cross-reference" href="#sec:Representing-Assertion-Sets">7.1</a>)<span class="plain-layout-boundary"></span></div>
<p id="x_4_1_0_0_39">The “listening” part of the service is spawned as follows:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_36">\[
\AActor{\left(\lambda().\INIT{[],\CBehPack{\TASet}{\mathit{demandMatcher}}{\emptyset}}\right)}{\{\Obs{(\mathtt{hello},\star)}\}}
\]
</div>Its behavior function is defined as follows:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_37">\[
\mathit{demandMatcher}\;(\ROUTES_{\mathit{new}},\ROUTES_{\mathit{old}})\;=\CONTINUE{[\mathit{mkWorker}\,x\;|\;(\mathtt{hello},x)\in\ROUTES_{\mathit{new}}-\ROUTES_{\mathit{old}}],\ROUTES_{\mathit{new}}}
\]
</div>The actor-private state of <span class="lyx-mathjax mathjax-inline">$\mathit{demandMatcher}$</span>, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{\mathit{old}}$</span>, is the (initially empty) set of currently-asserted <span class="lyx-mathjax mathjax-inline">$\mathtt{hello}$</span> tuples.<label class="footnote-number" for="fn_4_31">31</label> The incoming event, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{\mathit{new}}$</span>, is the newest version of that set from the environment. The demand matcher performs set subtraction to determine newly-appeared requests and calls a helper function <span class="lyx-mathjax mathjax-inline">$\mathit{mkWorker}$</span> to produce a matching service actor for each:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_38">\begin{align*}
\mathit{mkWorker}\,x &amp; =\AActor{\left(\lambda().\INIT{\mathit{initialActionsFor}\,x,\CBehPack{\tau}{\mathit{worker}}s}\right)}{\emptyset}\\
&amp; \phantom{\;=\;}\textrm{where }s=\mathit{initialStateFor}\,x\in\tau\textrm{ and }\mathit{worker}\in\TBehF{\tau}
\end{align*}
</div>Thus, when <span class="lyx-mathjax mathjax-inline">$(\mathtt{hello},\mathtt{A})$</span> first appears as a member of <span class="lyx-mathjax mathjax-inline">$\ROUTES_{\mathit{new}}$</span>, the demand matcher invokes <span class="lyx-mathjax mathjax-inline">$\mathit{mkWorker}$</span> with <span class="lyx-mathjax mathjax-inline">$\mathtt{A}$</span> as an argument, which yields a request to create a new worker actor that talks to client <span class="lyx-mathjax mathjax-inline">$\mathtt{A}$</span>. The conversation between <span class="lyx-mathjax mathjax-inline">$\mathtt{A}$</span> and the new worker proceeds from there. A more sophisticated implementation of demand matching might maintain a pool of workers, allocating incoming conversation requests as necessary.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_4_1_0_0_53">
<figure id="x_4_1_0_0_43"><a name="fig:file-server-architecture"></a>
<p class="align-center" id="x_4_1_0_0_42"><img id="x_4_1_0_0_41" src="Figures/file-server.svg" style="width: auto; height: 8cm;"/> </p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>13</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:file-server-architecture"></a>Layered File Server / Word Processor architecture<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p id="x_4_1_0_0_44"><span class="counter numbered example"><span>4.4</span></span><a class="label-anchor" href="#example:file-system"></a><a name="example:file-system"></a>Our final example demonstrates an architectural pattern seen in operating systems, web browsers, and cloud computing. Figure <a class="cross-reference" href="#fig:file-server-architecture">13</a> sketches the architecture of a program implementing a word processing application with multiple open documents, alongside other applications and a <em>file server</em> actor. The “Kernel” dataspace is at the bottom of this tree-like representation of containment.</p>
<p id="x_4_1_0_0_45">The hierarchical nature of the dataspace model means that each dataspace has a containing dataspace in turn. Actors may interrogate and augment assertions held in containing dataspaces by prefixing assertions relating to the <span class="lyx-mathjax mathjax-inline">$n$</span>th relative dataspace layer with <span class="lyx-mathjax mathjax-inline">$n$</span> “<tt>outbound</tt>” markers <span class="lyx-mathjax mathjax-inline">$\Out{}$</span>. Dataspaces relay <span class="lyx-mathjax mathjax-inline">$\Out{}$</span>-labeled assertions outward. Some of these assertions may describe interest in assertions existing at an outer layer. Any assertions matching such interests are relayed back in by the dataspace, which prefixes them with an “<tt>inbound</tt>” marker <span class="lyx-mathjax mathjax-inline">$\In{}$</span> to distinguish them from local assertions.</p>
<p id="x_4_1_0_0_48">In this example, actors representing open documents communicate directly with each other via a local dataspace scoped to the word processor, but only indirectly with other actors in the system. When the actor for a document decides that it is time to save its content to the file system, it issues a message such as
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_46">\[
\AMsg{\Out{(\mathtt{save},\texttt{"novel.txt"},\texttt{"Call me Ishmael."})}}
\]
</div>into its local dataspace. The harpoon (<span class="lyx-mathjax mathjax-inline">$\Out{}$</span>) signals that, like a system call in regular software applications, the message is intended to be relayed to the <em>next outermost</em> dataspace—the medium connecting the word processing application as a whole to its peers. Once the message is relayed, the message
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_47">\[
\AMsg{(\mathtt{save},\texttt{"novel.txt"},\texttt{"Call me Ishmael."})}
\]
</div>is issued into the outer dataspace, where it may be processed by the file server. The harpoon is removed as part of the relaying operation, and no further harpoons remain, indicating that the message should be processed <em>here</em>, at this dataspace.</p>
<p id="x_4_1_0_0_50">The file server responds to two protocols, one for writing files and one for reading file contents and broadcasting changes to files as they happen. These protocols are articulated as two subscriptions:
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_49">\[
\{\Obs{(\mathtt{save},\star,\star)},\Obs{\Obs{(\mathtt{contents},\star,\star)}}\}
\]
</div>The first indicates interest in <span class="lyx-mathjax mathjax-inline">$\mathtt{save}$</span> messages. When a <span class="lyx-mathjax mathjax-inline">$\mathtt{save}$</span> message is received, the server stores the updated file content.</p>
<p id="x_4_1_0_0_52">The second indicates interest in <em>subscriptions</em> in the shared dataspace, an interest in <em>interest</em> in file contents. This is how the server learns that peers wish to be kept informed of the contents of files under its control. The file server is told each time some peer asserts interest in the contents of a file. In response, it asserts facts of the form
<div class="lyx-mathjax mathjax-display" id="x_4_1_0_0_51">\[
(\mathtt{contents},\texttt{"novel.txt"},\texttt{"Call me Ishmael."})
\]
</div>and keeps them up-to-date as <span class="lyx-mathjax mathjax-inline">$\mathtt{save}$</span> commands are received, finally retracting them when it learns that peers are no longer interested. In this way, the shared dataspace not only acts as a kind of cache for the files maintained on disk, but also doubles as an <tt>inotify</tt>-like mechanism <span class="citation citep">(<a class="citation" id="cite-96" href="#bib-Love2005">Love 2005</a>)</span> for signaling changes in files.</p><span class="halmos"></span></div><p id="x_4_1_0_0_54">Our examples illustrate the key properties of the dataspace model and their unique combination. Firstly, the box and demand-matcher examples show that conversations may naturally involve many parties, generalizing the actor model's point-to-point conversations. At the same time, the file server example shows that conversations are more precisely bounded than those of traditional actors. Each of its dataspaces crisply delimits its contained conversations, each of which may therefore use a task-appropriate language of discourse.</p><p id="x_4_1_0_0_55">Secondly, all three examples demonstrate the shared-dataspace aspect of the model. Assertions made by one actor can influence other actors, but cannot directly alter or remove assertions made by others. The box's content is made visible through an assertion in the dataspace, and any actor that knows <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> can retrieve the assertion. The demand-matcher responds to changes in the dataspace that denote the existence of new conversations. The file server makes file contents available through assertions in the (outer) dataspace, in response to clients placing subscriptions in that dataspace.</p>
<div class="footnote" id="fn_4_32"><span class="counter footnote-counter"><span>32</span></span>This is a concept well-known in the networking community as <em>fate-sharing</em> <span class="citation citep">(<a class="citation" id="cite-97" href="#bib-Clark1988">Clark 1988</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_4_1_0_0_56">Finally, the model places an upper bound on the lifetimes of entries in each shared space. Items may be asserted and retracted by actors at will in response to incoming events, but when an actor crashes, all of its assertions are automatically retracted.<label class="footnote-number" for="fn_4_32">32</label> If the box actor were to crash during a computation, the assertion describing its content would be visibly withdrawn, and peers could take some compensating action. The demand matcher can be enhanced to monitor <em>supply</em> as well as demand and to take corrective action if some worker instance exits unexpectedly. The combination of this temporal bound on assertions with the model's state change notifications gives good failure-signaling and fault-tolerance properties, improving on those seen in Erlang <span class="citation citep">(<a class="citation" id="cite-98" href="#bib-Armstrong2003">Armstrong 2003</a>)</span>.</p>
<h4 id="x_4_2_0_0_1"><a name="toc_4.2"></a><span class="counter section"><span>4.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Formal-DS-semantics"></a><a name="sec:Formal-DS-semantics"></a>Formal semantics of the dataspace model</span></h4>
<figure class="fullwidth" id="x_4_2_0_0_6"><a name="fig:DS-evaluation-syntax"></a>
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_2">\begin{align*}
\textrm{Dataspaces }C\in\TCfg &amp; ::=\CCfg{\VECOF q}R{\VECOF A} &amp; &amp; &amp; C_{I}\in\TCfgI &amp; ::=\CCfg{\cdot}R{\VECOF{A_{I}}}\\
\textrm{Actors }A\in\TActor &amp; ::=\CActor{\ell}{\Sigma} &amp; A_{Q}\in\TActorQ &amp; ::=\CActor{\ell}{\Sigma_{Q}} &amp; A_{I}\in\TActorI &amp; ::=\CActor{\ell}{\Sigma_{I}}\\
\textrm{States }\Sigma\in\TState &amp; ::=\CState{\VECOF e}B{\VECOF a} &amp; \Sigma_{Q}\in\TStateQ &amp; ::=\CState{\VECOF e}B{\cdot} &amp; \Sigma_{I}\in\TStateI &amp; ::=\CState{\cdot}{B_{I}}{\cdot}\\
\textrm{Behaviors }B\in\TBeh &amp; =\TBehPack{\tau}\cup\TCfg &amp; &amp; &amp; B_{I}\in\TBehI &amp; =\TBehPack{\tau}\cup\TCfgI\\
&amp; &amp; &amp; \hspace{-5em}{\underbrace{\hspace{10em}}} &amp; &amp; \hspace{-5em}{\underbrace{\hspace{10em}}}\\
&amp; &amp; &amp; \hspace{-2.3em}\textrm{Quiescent} &amp; &amp; \hspace{-1.1em}\textrm{Inert}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_3">\begin{align*}
\textrm{Queued Actions }q\in\TQAct &amp; ::=\CQAct ka\\
\textrm{Dataspace Contents }R\in\TSpace &amp; =\SETOF{\TID\times\TVal}\\
\textrm{Peer Identifiers }j,k\in\TID &amp; ::=\ell\ |\ \CMeta\\
\textrm{Locations }\ell\in\TLoc &amp; =\mathbb{N}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_4">\begin{align*}
\FBOOT &amp; :\ \TProg\rightarrow\TState\times\TASet\\
\FBOOT\ (\AActor{\CBoot}{\ROUTES)} &amp; =\begin{cases}
(\CState{\cdot}{\CBehPack{\tau}{\CBehF}u}{\VECOF a},\ROUTES) &amp; \textrm{when }\CBoot()=\INIT{\VECOF a,\CBehPack{\tau}{\CBehF}u}\\
(\CState{\cdot}{\CBehPack{\T1}{\FNOOP}{()}}{\emptyset\VECOF a},\ROUTES) &amp; \textrm{when }\CBoot()=\EXIT{\VECOF a}
\end{cases}\\
\FBOOT\ (\ADS{\VECOF P}) &amp; =(\CState{\cdot}{\CCfg{\VECOF{\CQAct{\CMeta}P}}{\emptyset}{\cdot}}{\cdot},\emptyset)
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_5">\begin{align*}
\FNOOP &amp; :\ \TBehF{\T1}\\
\FNOOP\ \left(e,()\right) &amp; =\CONTINUE{\cdot\;,()}
\end{align*}
</div><figcaption><span class="counter figure"><span>14</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:DS-evaluation-syntax"></a>Evaluation Syntax and Inert and Quiescent Terms<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_4_2_0_0_7"> </p><p id="x_4_2_0_0_8">The semantics of the dataspace model is most easily understood via an abstract machine. Figure <a class="cross-reference" href="#fig:DS-evaluation-syntax">14</a> shows the syntax of machine configurations, plus a metafunction <span class="lyx-mathjax mathjax-inline">$\FBOOT$</span>, which loads programs in <span class="lyx-mathjax mathjax-inline">$\TProg$</span> into starting machine states in <span class="lyx-mathjax mathjax-inline">$\TState$</span>, and an inert behavior function <span class="lyx-mathjax mathjax-inline">$\FNOOP$</span>.</p><p id="x_4_2_0_0_9">The reduction relation operates on actor states <span class="lyx-mathjax mathjax-inline">$\Sigma=\CState{\VECOF e}B{\VECOF a}$</span>, which are triples of a queue of events <span class="lyx-mathjax mathjax-inline">$\VECOF e$</span> destined for the actor, the actor's behavior and internal state <span class="lyx-mathjax mathjax-inline">$B$</span>, and a queue of actions <span class="lyx-mathjax mathjax-inline">$\VECOF a$</span> issued by the actor and destined for processing by its containing dataspace. An actor's behavior and state <span class="lyx-mathjax mathjax-inline">$B$</span> can take on one of two forms. For a leaf actor, behavior and state are kept together with the type of the actor's private state value in an existential package <span class="lyx-mathjax mathjax-inline">$B=\CBehPack{\tau}{\CBehF}u\in\TBehPack{\tau}$</span>. For a dataspace actor, behavior is determined by the reduction rules of the model, and its state is a configuration <span class="lyx-mathjax mathjax-inline">$B\in\TCfg$</span>.</p><p id="x_4_2_0_0_10">Dataspace configurations <span class="lyx-mathjax mathjax-inline">$C$</span> comprise three registers: a queue of actions to be performed <span class="lyx-mathjax mathjax-inline">$\VECOF q$</span>, each labeled with some <em>identifier</em> denoting the origin of the action; the current contents of the assertion store <span class="lyx-mathjax mathjax-inline">$R$</span>; and a sequence of actors <span class="lyx-mathjax mathjax-inline">$\VECOF{\CActor{\ell}{\Sigma}}$</span> residing within the configuration. Each actor is assigned a local <em>label</em> <span class="lyx-mathjax mathjax-inline">$\ell$</span>, also called a <em>location</em>, scoped strictly to the configuration and meaningless outside. Labels are required to be locally-unique within a given configuration. They are never made visible to leaf actors: labels are an internal matter, used solely as part of the behavior of dataspace actors. The identifiers marking each queued action in the configuration are either the labels of some contained actor or the special identifier <span class="lyx-mathjax mathjax-inline">$\CMeta$</span> denoting an action resulting from some external force, such as an event arriving from the configuration's containing configuration.</p>
<h6 class="unnumbered" id="x_4_2_0_0_11"><a name="toc_4.2"></a><span class="heading-text paragraph">Reduction relation.</span></h6><p id="x_4_2_0_0_12">The reduction relation drives actors toward <em>quiescent</em> and even <em>inert</em> states. Figure <a class="cross-reference" href="#fig:DS-evaluation-syntax">14</a> defines these syntactic classes, which are roughly analogous to values in the call-by-value <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus. A state <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> is quiescent when its sequence of actions is empty, and it is inert when, besides being quiescent, it has no more events to process and cannot take any further internal reductions.</p>
<figure class="fullwidth" id="x_4_2_0_0_16"><a name="fig:DS-reductions"></a>
<div class="frameless-box" id="x_4_2_0_0_15">
<div class="frameless-box" id="x_4_2_0_0_14">
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_13">\begin{align*}
\CState{\VECOF ee_{0}}{\CBehPack{\tau}{\CBehF}u}{\VECOF a}\longrightarrow\rlap{\CState{\VECOF e}{\CBehPack{\tau}{\CBehF}{u'}}{\VECOF a'\VECOF a}}\phantom{\CState{\VECOF e}{\CBehPack{\T1}{\FNOOP}{()}}{\emptyset\VECOF a'\VECOF a}} &amp; &amp; &amp; \textrm{when }\CBehF(e_{0},u)=\CONTINUE{\VECOF a',u'} &amp; (\RNotifyLeaf)\\
\CState{\VECOF ee_{0}}{\CBehPack{\tau}{\CBehF}u}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CBehPack{\T1}{\FNOOP}{()}}{\emptyset\VECOF a'\VECOF a} &amp; &amp; &amp; \textrm{when }\CBehF(e_{0},u)=\EXIT{\VECOF a'} &amp; (\RQuit)\\
\CState{\VECOF ee_{0}}{\CCfg{\cdot}R{\VECOF{A_{I}}}}{\VECOF a}\longrightarrow\rlap{\CState{\VECOF e}{\CCfg{\CQAct{\CMeta}{\FINP\ e_{0}}}R{\VECOF{A_{I}}}}{\VECOF a}}\phantom{\CState{\VECOF e}{\CBehPack{\T1}{\FNOOP}{()}}{\emptyset\VECOF a'\VECOF a}} &amp; &amp; &amp; &amp; (\RNotifyDS)\\
\\
\CState{\VECOF e}{\CCfg{\phantom{\CQAct{\ell}{a''}}\VECOF q}R{\VECOF{A_{Q}}(\CActor{\ell}{\CState{\VECOF e'}B{\VECOF a'a''}})\VECOF A}}{\VECOF a} &amp; &amp; &amp; &amp; (\RGather)\\
\longrightarrow\CState{\VECOF e}{\CCfg{\CQAct{\ell}{a''}\VECOF q}R{\VECOF{A_{Q}}(\CActor{\ell}{\CState{\VECOF e'}B{\VECOF a'\phantom{a''}}})\VECOF A}}{\VECOF a}\\
\\
\CState{\VECOF e}{\CCfg{\VECOF q(k,\ROUTES)}{\rlap{R}\phantom{R\oplus\CQAct k{\ROUTES}}}{\rlap{\VECOF{A_{Q}}}\phantom{\VECOF{\FBC k{\ROUTES}R{A_{Q}}}}}}{\phantom{(\FOUT k{\ROUTES}R)}\VECOF a} &amp; &amp; &amp; &amp; (\RNewtable)\\
\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\phantom{(k,\ROUTES)}}{R\oplus\CQAct k{\ROUTES}}{\VECOF{\FBC k{\ROUTES}R{A_{Q}}}}}{(\FOUT k{\ROUTES}R)\VECOF a}\\
\\
\CState{\VECOF e}{\CCfg{\VECOF q(k,\AMsg c)}R{\rlap{\VECOF{A_{Q}}}\phantom{\VECOF{\FBC k{\AMsg c}R{A_{Q}}}}}}{\phantom{(\FOUT k{\AMsg c}R)}\VECOF a} &amp; &amp; &amp; &amp; (\RMessage)\\
\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\phantom{(k,\AMsg c)}}R{\VECOF{\FBC k{\AMsg c}R{A_{Q}}}}}{(\FOUT k{\AMsg c}R)\VECOF a}\\
\\
\CState{\VECOF e}{\CCfg{\VECOF q(k,P)}R{\VECOF{A_{Q}}\phantom{(\CActor{\ell}{\Sigma})}}}{\VECOF a} &amp; &amp; &amp; &amp; (\RSpawn)\\
\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\rlap{\CQAct{\ell}{\ROUTES}}\phantom{(k,P)}}R{\VECOF{A_{Q}}(\CActor{\ell}{\Sigma})}}{\VECOF a}\\
&amp; &amp; &amp; \hspace{8em}\llap{\textrm{where \(\ell=1+\mathsf{max}\;\{j\;|\;\left(\CActor j{\Sigma'}\right)\in\VECOF{A_{Q}}\}\) and \((\Sigma,\ROUTES)=\FBOOT\ P\)}}\\
\\
\frac{\Sigma_{Q}\longrightarrow\Sigma'}{\CState{\VECOF e}{\CCfg{\cdot}R{\VECOF{A_{I}}(\CActor{\ell}{\Sigma_{Q}})\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\cdot}R{\VECOF{A_{Q}}\VECOF{A_{I}}(\CActor{\ell}{\Sigma'})}}{\VECOF a}}\hspace{-8em} &amp; &amp; &amp; &amp; (\RSchedule)
\end{align*}
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>15</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:DS-reductions"></a>Reduction semantics of the dataspace model<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_4_2_0_0_17">The reductions of the dataspace model are defined by the following rules. For convenient reference, the rules are also shown together in figure <a class="cross-reference" href="#fig:DS-reductions">15</a>. Rules <span class="lyx-mathjax mathjax-inline">$\RNotifyLeaf$</span> and <span class="lyx-mathjax mathjax-inline">$\RQuit$</span> deliver an event to a leaf actor and update its state based on the results. Rule <span class="lyx-mathjax mathjax-inline">$\RNotifyDS$</span> delivers an event to a <em>dataspace</em> actor. Rule <span class="lyx-mathjax mathjax-inline">$\RGather$</span> collects actions produced by contained actors in a dataspace to a central queue, and rules <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span>, <span class="lyx-mathjax mathjax-inline">$\RMessage$</span>, and <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> interpret previously-gathered actions. Finally, rule <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span> allows contained actors to take a step if they are not already inert. </p>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_20">
<p id="x_4_2_0_0_19"><span class="counter numbered definition"><span>4.5</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RNotifyLeaf$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:notify-leaf"></a><a name="def:rule:notify-leaf"></a>A leaf actor's behavior function, given event <span class="lyx-mathjax mathjax-inline">$e_{0}$</span> and private state value <span class="lyx-mathjax mathjax-inline">$u$</span>, may yield a <span class="lyx-mathjax mathjax-inline">$\CONTINUE{}$</span> instruction, i.e. <span class="lyx-mathjax mathjax-inline">$\CBehF(e_{0},u)=\CONTINUE{\VECOF a',u'}$</span>. In this case, the actor's state is updated in place and newly-produced actions are enqueued for processing:
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_18">\[
\CState{\VECOF ee_{0}}{\CBehPack{\tau}{\CBehF}u}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CBehPack{\tau}{\CBehF}{u'}}{\VECOF a'\VECOF a}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_23">
<div class="footnote" id="fn_4_33"><span class="counter footnote-counter"><span>33</span></span>Terminated actors remain in their configurations indefinitely with the reduction relation as written. In the same way that the CESK machine can be equipped with reduction rules for garbage collection <span class="citation citep">(<a class="citation" id="cite-99" href="#bib-Felleisen2009a">Felleisen, Findler and Flatt 2009</a> <span class="citation-after">ch. 9</span>)</span>, a rule for removing inert actors with no assertions can be added to our reduction relation if we wish.<span class="plain-layout-boundary"></span></div>
<p id="x_4_2_0_0_22"><span class="counter numbered definition"><span>4.6</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RQuit$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:quit"></a><a name="def:rule:quit"></a>Alternatively, a leaf actor's behavior function may yield an <span class="lyx-mathjax mathjax-inline">$\EXIT{}$</span> instruction in response to event <span class="lyx-mathjax mathjax-inline">$e_{0}$</span>, i.e. <span class="lyx-mathjax mathjax-inline">$\CBehF(e_{0},u)=\EXIT{\VECOF a'}$</span>. In this case, the terminating actor is replaced with a <span class="lyx-mathjax mathjax-inline">$\FNOOP$</span> behavior and its final few actions are enqueued:
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_21">\[
\CState{\VECOF ee_{0}}{\CBehPack{\tau}{\CBehF}u}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CBehPack{\T1}{\FNOOP}{()}}{\emptyset\VECOF a'\VECOF a}
\]
</div>Finally, a synthesized SCN action <span class="lyx-mathjax mathjax-inline">$\emptyset$</span> is enqueued. The result is the permanent retraction of the actor's remaining assertions. This rule covers both deliberate and exceptional termination.<label class="footnote-number" for="fn_4_33">33</label></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_26">
<p id="x_4_2_0_0_25"><span class="counter numbered definition"><span>4.7</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RNotifyDS$</span><span class="plain-layout-boundary"></span></span>When an event <span class="lyx-mathjax mathjax-inline">$e_{0}$</span> arrives for a dataspace, it is labeled with the special location <span class="lyx-mathjax mathjax-inline">$\CMeta$</span> and enqueued for subsequent interpretation.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_24">\[
\CState{\VECOF ee_{0}}{\CCfg{\cdot}R{\VECOF{A_{I}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\CQAct{\CMeta}{\FINP\ e_{0}}}R{\VECOF{A_{I}}}}{\VECOF a}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_29">
<p id="x_4_2_0_0_28"><span class="counter numbered definition"><span>4.8</span></span><span class="lyx-argument">Inbound event transformation<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:inp-monolithic"></a><a name="def:mf:inp-monolithic"></a>The metafunction <span class="lyx-mathjax mathjax-inline">$\FINP$</span> transforms each such incoming event by prepending an “<tt>inbound</tt>” marker <span class="lyx-mathjax mathjax-inline">$\In{}$</span> to each assertion contained in the event. This marks the assertions as pertaining to the next outermost dataspace, rather than to the local dataspace.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_27">\begin{align*}
\FINP &amp; :\TEvt\rightarrow\TAct\\
\FINP\ \ROUTES &amp; =\{\In c\;|\;c\in\ROUTES\}\\
\FINP\ \AMsg c &amp; =\AMsg{\In c}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_32">
<p id="x_4_2_0_0_31"><span class="counter numbered definition"><span>4.9</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RGather$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:gather"></a><a name="def:rule:gather"></a>The <span class="lyx-mathjax mathjax-inline">$\RGather$</span> rule reads from the queue of actions produced by a particular actor for interpretation by its dataspace. It marks each action with the label of the actor before enqueueing it in the dataspace's pending action queue for processing.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_30">\[
\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF{A_{Q}}(\CActor{\ell}{\CState{\VECOF e'}B{\VECOF a'a''}})\VECOF A}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\CQAct{\ell}{a''}\VECOF q}R{\VECOF{A_{Q}}(\CActor{\ell}{\CState{\VECOF e'}B{\VECOF a'}})\VECOF A}}{\VECOF a}
\]
</div></p><span class="halmos"></span></div><p id="x_4_2_0_0_33">Now that we have considered event delivery and action production and collection, we may turn to action <em>interpretation</em>. The <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> and <span class="lyx-mathjax mathjax-inline">$\RMessage$</span> rules are central. They both depend on metafunctions <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> (short for “broadcast”) and <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> to transform queued actions into pending events for local actors and the containing dataspace, respectively. Before we examine the supporting metafunctions, we will examine the two rules themselves.</p>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_36">
<p id="x_4_2_0_0_35"><span class="counter numbered definition"><span>4.10</span></span><span class="lyx-argument">Dataspace update<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:oplus-monolithic"></a><a name="def:mf:oplus-monolithic"></a>The assertions of a party labeled <span class="lyx-mathjax mathjax-inline">$k$</span> are replaced in a dataspace's contents <span class="lyx-mathjax mathjax-inline">$R$</span> by an assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> using the <span class="lyx-mathjax mathjax-inline">$\oplus$</span> operator:
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_34">\[
R\oplus\CQAct k{\ROUTES}=\{\CQAct jc\;|\;\CQAct jc\in R,j\not=k\}\cup\{\CQAct kc\;|\;c\in\ROUTES\}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_39">
<p id="x_4_2_0_0_38"><span class="counter numbered definition"><span>4.11</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:newtable"></a><a name="def:rule:newtable"></a>A queued state change notification action <span class="lyx-mathjax mathjax-inline">$\CQAct k{\ROUTES}$</span> not only completely replaces the assertions associated with <span class="lyx-mathjax mathjax-inline">$k$</span> in the shared dataspace but also inserts a state change notification <em>event</em> into the event queues of interested local actors via <span class="lyx-mathjax mathjax-inline">$\FBCName$</span>. Because <span class="lyx-mathjax mathjax-inline">$k$</span> may have made “<tt>outbound</tt>” assertions labeled with <span class="lyx-mathjax mathjax-inline">$\Out{}$</span>, <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> also prepares a state change notification for the wider environment, using <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span>.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_37">\[
\CState{\VECOF e}{\CCfg{\VECOF q(k,\ROUTES)}R{\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q}{R\oplus\CQAct k{\ROUTES}}{\VECOF{\FBC k{\ROUTES}R{A_{Q}}}}}{(\FOUT k{\ROUTES}R)\VECOF a}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered remark" id="x_4_2_0_0_41">
<p id="x_4_2_0_0_40"><span class="counter unnumbered remark"><span>4.11</span></span>This is the only rule to update a dataspace's <span class="lyx-mathjax mathjax-inline">$R$</span>. In addition, because <span class="lyx-mathjax mathjax-inline">$k$</span>'s assertion set is completely replaced, it is here that <em>retraction</em> of previously-asserted items takes effect.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_44">
<p id="x_4_2_0_0_43"><span class="counter numbered definition"><span>4.12</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RMessage$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:message"></a><a name="def:rule:message"></a>The <span class="lyx-mathjax mathjax-inline">$\RMessage$</span> rule interprets send-message actions <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span>. The <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> metafunction is again used to deliver the message to interested peers, and <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> relays the message on to the containing dataspace if it happens to be “<tt>outbound</tt>”-labeled with <span class="lyx-mathjax mathjax-inline">$\Out{}$</span>.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_42">\[
\CState{\VECOF e}{\CCfg{\VECOF q(k,\AMsg c)}R{\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF{\FBC k{\AMsg c}R{A_{Q}}}}}{(\FOUT k{\AMsg c}R)\VECOF a}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_48">
<p id="x_4_2_0_0_47"><span class="counter numbered definition"><span>4.13</span></span><span class="lyx-argument">Event broadcast<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:bc"></a><a name="def:mf:bc"></a>The <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> metafunction computes the consequences for an actor labeled <span class="lyx-mathjax mathjax-inline">$\ell$</span> of an action performed by another party labeled <span class="lyx-mathjax mathjax-inline">$k$</span>. When it deals with a state change notification action <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>, the entire aggregate shared dataspace is projected according to the asserted interests of <span class="lyx-mathjax mathjax-inline">$\ell$</span>. The results of the projection are assembled into a state change notification event, but are enqueued only if the event would convey new information to <span class="lyx-mathjax mathjax-inline">$\ell$</span>. When <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> deals with a message action <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span>, a corresponding message event is enqueued for <span class="lyx-mathjax mathjax-inline">$\ell$</span> only if <span class="lyx-mathjax mathjax-inline">$\ell$</span> has previously asserted interest in <span class="lyx-mathjax mathjax-inline">$c$</span>.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_46">\begin{align*}
\FBCName &amp; :\TID\times\TEvt\times\TSpace\times\TActorQ\rightarrow\TActor\\
\FBC k{\ROUTES}{\Rold}{(\CActor{\ell}{\CState{\VECOF e}B{\cdot}})} &amp; =\begin{cases}
\CActor{\ell}{\CState{\ROUTESnew\VECOF e}B{\cdot}} &amp; \textrm{when }\ROUTESnew\not=\ROUTESold\\
\CActor{\ell}{\CState{\phantom{\ROUTESnew}\VECOF e}B{\cdot}} &amp; \textrm{when }\ROUTESnew=\ROUTESold
\end{cases}\\
\textrm{where } &amp; \Rnew=\Rold\oplus(k,\ROUTES)\\
&amp; \ROUTESnew=\{c\;|\;(j,c)\in\Rnew,(\ell,\Obs c)\in\Rnew\}\\
&amp; \ROUTESold=\{c\;|\;(j,c)\in\Rold,(\ell,\Obs c)\in\Rold\}\\
\FBC k{\AMsg c}{\Rold}{(\CActor{\ell}{\CState{\VECOF e}B{\cdot}})} &amp; =\begin{cases}
\CActor{\ell}{\CState{\AMsg c\VECOF e}B{\cdot}} &amp; \textrm{when \((\ell,\Obs c)\in\Rold\)}\\
\CActor{\ell}{\CState{\phantom{\AMsg c}\VECOF e}B{\cdot}} &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_51">
<p id="x_4_2_0_0_50"><span class="counter numbered definition"><span>4.14</span></span><span class="lyx-argument">Outbound action transformation<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:out-monolithic"></a><a name="def:mf:out-monolithic"></a>The metafunction <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> is analogous to <span class="lyx-mathjax mathjax-inline">$\FBCName$</span>, but for determining information to be relayed to a containing dataspace as a consequence of a local action.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_49">\begin{align*}
\FOUTName &amp; :\TID\times\TEvt\times\TSpace\rightarrow\VECOF{\TAct}\\
\FOUT{\CMeta}eR &amp; =\cdot\qquad\qquad\textrm{(empty sequence of actions)}\\
\FOUT{\ell}{\ROUTES}R &amp; =\{c\;|\;(j,\Out c)\in R\oplus(\ell,\ROUTES)\}\cup\{\Obs c\;|\;(j,\Obs{\In c})\in R\oplus(\ell,\ROUTES)\}\\
\FOUT{\ell}{\AMsg c}R &amp; =\begin{cases}
\AMsg d &amp; \textrm{when }c=\Out d\\
\cdot &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div>The first clause ensures that the <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> metafunction never produces an action for transmission to the outer dataspace when the cause of the call to <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> is an action from the outer dataspace. Without this rule, configurations would never become inert.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_54">
<div class="footnote" id="fn_4_34"><span class="counter footnote-counter"><span>34</span></span>Non-deterministic allocation strategies affect theorem <a class="cross-reference" href="#thm:determinism">4.20</a> but are otherwise harmless, so long as they preserve local uniqueness of labels.<span class="plain-layout-boundary"></span></div>
<p id="x_4_2_0_0_53"><span class="counter numbered definition"><span>4.15</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:spawn"></a><a name="def:rule:spawn"></a>The <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> rule allocates a fresh label <span class="lyx-mathjax mathjax-inline">$\ell$</span> and places a newly-spawned actor into the collection of local actors, alongside its siblings. The new label <span class="lyx-mathjax mathjax-inline">$\ell$</span> is chosen to be distinct from <span class="lyx-mathjax mathjax-inline">$k$</span>, from every element of <span class="lyx-mathjax mathjax-inline">$\left\{ k'\;|\;(k',a')\in\VECOF q\right\} $</span>, and from the labels of every <span class="lyx-mathjax mathjax-inline">$\VECOF{A_{Q}}$</span>. Any deterministic<label class="footnote-number" for="fn_4_34">34</label> allocation strategy will do; we will choose <span class="lyx-mathjax mathjax-inline">$\ell=1+\mathsf{max}\;\{j\;|\;\left(\CActor j{\Sigma'}\right)\in\VECOF{A_{Q}}\}$</span>. The new actor's initial state <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> and initial assertions <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> are computed from the actor specification <span class="lyx-mathjax mathjax-inline">$P$</span> by <span class="lyx-mathjax mathjax-inline">$(\Sigma,\ROUTES)=\FBOOT\ P$</span>.
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_52">\begin{align*}
\CState{\VECOF e}{\CCfg{\VECOF q(k,P)}R{\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\CQAct{\ell}{\ROUTES}}R{\VECOF{A_{Q}}(\CActor{\ell}{\Sigma})}}{\VECOF a}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered remark" id="x_4_2_0_0_56">
<div class="footnote" id="fn_4_35"><span class="counter footnote-counter"><span>35</span></span>An alternative approach to spawning could involve “fork” and “exec” operations analogous to those of the same name offered by Unix kernels. An actor could “fork”, leading to two (almost-) identical copies, both retaining the set of assertions current at the time of the fork. One copy would immediately perform an “exec” to replace its behavior function. Both actors would then tailor their assertion sets to their separate domains of responsibility.<span class="plain-layout-boundary"></span></div>
<p id="x_4_2_0_0_55"><span class="counter unnumbered remark"><span>4.15</span></span>The rule takes care to ensure that a new actor's initial <em>assertions</em> <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> are processed ahead of other queued actions <span class="lyx-mathjax mathjax-inline">$\VECOF q$</span>, even though the new actor's initial <em>actions</em> will be placed at the end of the queue and processed in order as usual. This allows a spawning actor to atomically delegate responsibility to a new actor by issuing a state-change notification immediately following the <span class="lyx-mathjax mathjax-inline">$\AActorName$</span> action. Assertions indicating to the world that the spawning party has “taken responsibility” for some task may be placed in the new actor's initial assertion set and omitted from the subsequent state-change notification. This eliminates any possibility of an intervening moment in which a peer might see a retraction of the assertions concerned. Furthermore, even if the new actor crashes during boot, there will be a guaranteed moment in time before its termination when its initial assertion set was visible to peers. Because the computation of the initial assertion set happens in the execution context of the spawning actor, an uncaught exception raised during that computation correctly blames the spawning actor for the failure. However, the computation of the initial <em>actions</em> is performed in the context of the spawned actor, and an exception at that moment correctly blames the spawned actor.<label class="footnote-number" for="fn_4_35">35</label></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_2_0_0_59">
<div class="footnote" id="fn_4_36"><span class="counter footnote-counter"><span>36</span></span>This scheduling policy, in conjunction with the determinism of the system (theorem <a class="cross-reference" href="#thm:determinism">4.20</a>) and the totality of leaf actor behavior functions, yields fairness <span class="citation citep">(<a class="citation" id="cite-100" href="#bib-Clinger1981">Clinger 1981</a>)</span>.<span class="plain-layout-boundary"></span></div>
<p id="x_4_2_0_0_58"><span class="counter numbered definition"><span>4.16</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:schedule"></a><a name="def:rule:schedule"></a>Finally, the <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span> rule allows quiescent, non-inert contained actors to take a step. It rotates the sequence of actors as it does so.<label class="footnote-number" for="fn_4_36">36</label>
<div class="lyx-mathjax mathjax-display" id="x_4_2_0_0_57">\[
\frac{\Sigma_{Q}\longrightarrow\Sigma'}{\CState{\VECOF e}{\CCfg{\cdot}R{\VECOF{A_{I}}(\CActor{\ell}{\Sigma_{Q}})\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\cdot}R{\VECOF{A_{Q}}\VECOF{A_{I}}(\CActor{\ell}{\Sigma'})}}{\VECOF a}}
\]
</div> Variations on this rule can express different scheduling policies. For example, sorting the sequence decreasing by event queue length prioritizes heavily-loaded actors.</p><span class="halmos"></span></div>
<h4 id="x_4_3_0_0_1"><a name="toc_4.3"></a><span class="counter section"><span>4.3</span></span><span class="heading-text section">Cross-layer communication</span></h4><p id="x_4_3_0_0_2">Actors label assertions and message bodies with <span class="lyx-mathjax mathjax-inline">$\Out{}$</span> to address them to the dataspace's own containing dataspace, but there is no corresponding means of addressing an assertion or message to a <em>contained</em> dataspace or actor. Actors may reach out, but not in. Because there is always a unique containing dataspace, reserving specific names for referring to it—the harpoon marks <span class="lyx-mathjax mathjax-inline">$\Out{}$</span> and <span class="lyx-mathjax mathjax-inline">$\In{}$</span>—is reasonable. These two reserved constructors bootstrap arbitrary cross-layer communication arrangements. Actors draw communications inward by reaching out. They establish subscriptions at outer layers which cause relevant messages and assertions to be relayed towards the inner requesting layer. In effect, they “pull” rather than having peers “push” information.</p>
<div class="footnote" id="fn_4_37"><span class="counter footnote-counter"><span>37</span></span>See discussion in section <a class="cross-reference" href="#sec:Syndicate-design-principles">2.6</a>.<span class="plain-layout-boundary"></span></div><p id="x_4_3_0_0_3">Directing communications to specific siblings requires a name for each actor. Actor IDs are, as a matter of principle,<label class="footnote-number" for="fn_4_37">37</label> not made available to the programmer. In cases where “pushing” information inward is desired and useful, and where the resulting sensitive dependence on the topological structure of the overall configuration is acceptable, the dataspace model leaves the specific naming scheme chosen up to the programmer, offering a mechanism (<span class="lyx-mathjax mathjax-inline">$\Out{}$</span> and <span class="lyx-mathjax mathjax-inline">$\In{}$</span>) but remaining neutral on policy.</p>
<h4 id="x_4_4_0_0_1"><a name="toc_4.4"></a><span class="counter section"><span>4.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Messages-versus-Assertions"></a><a name="sec:Messages-versus-Assertions"></a>Messages versus assertions</span></h4><p id="x_4_4_0_0_2">We have included message-sending actions <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span> as primitive operations. However, message transmission can be usefully viewed as a derived construct, as a special case of assertion signaling. We may achieve substantially the same effect as <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span> by asserting <span class="lyx-mathjax mathjax-inline">$c$</span>, holding the assertion for “long enough” for it to register with interested peers, and then retracting <span class="lyx-mathjax mathjax-inline">$c$</span> again. A message, then, can be imagined as a <em>transient</em> assertion.</p><p id="x_4_4_0_0_3">There are two interesting corner-cases to consider when thinking about messages in this way. The reduction rules as written have no trouble delivering messages of the form <span class="lyx-mathjax mathjax-inline">$\AMsg{\Obs c}$</span>, despite the effect that an assertion of <span class="lyx-mathjax mathjax-inline">$\Obs c$</span> would have; and a message <span class="lyx-mathjax mathjax-inline">$\AMsg{c'}$</span> will be delivered to interested recipients even if some neighboring actor is asserting the value <span class="lyx-mathjax mathjax-inline">$c'$</span> at the same time. In a variation on the dataspace model lacking primitive message-sending actions, neither situation works quite as expected.</p><p id="x_4_4_0_0_4">First, consider the assertion-based analogue of the message <span class="lyx-mathjax mathjax-inline">$\AMsg{\Obs c}$</span>. The sender would briefly assert <span class="lyx-mathjax mathjax-inline">$\Obs c$</span> before retracting it again. However, <span class="lyx-mathjax mathjax-inline">$\Obs c$</span> asserts interest in <span class="lyx-mathjax mathjax-inline">$c$</span>. For the duration of the assertion, it would have the effect of drawing matching assertions <span class="lyx-mathjax mathjax-inline">$c$</span> toward the sending actor. Primitive support for messages, by contrast, imagines that the “assertion” of the message lasts for an infinitesimal duration. This applies equally to “assertions” of messages that appear to denote interest in other assertions. By the time the events triggered by the message are to be delivered, it is as if the assertion of interest has <em>already been retracted</em>, so no events describing assertions <span class="lyx-mathjax mathjax-inline">$c$</span> make their way toward the sender.</p>
<div class="footnote" id="fn_4_38"><span class="counter footnote-counter"><span>38</span></span>This is in some ways similar to the idea of <em>medium access control.</em> Multiple stations transmitting at the same time “corrupt” each others' messages. Some means of ensuring the separation of overlapping transmissions in space or in time is required.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_4_39"><span class="counter footnote-counter"><span>39</span></span>If message sending were a derived concept, such a type system would not suffice to ensure two peers did not simultaneously try to “send message <span class="lyx-mathjax mathjax-inline">$c$</span>” by briefly asserting <span class="lyx-mathjax mathjax-inline">$c$</span>.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_4_40"><span class="counter footnote-counter"><span>40</span></span>Research into the design of such a type system is ongoing <span class="citation citep">(<a class="citation" id="cite-101" href="#bib-Caldwell2017">Caldwell, Garnock-Jones and Felleisen 2017</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_4_4_0_0_5">Second, consider performing the action <span class="lyx-mathjax mathjax-inline">$\AMsg{c'}$</span> when <span class="lyx-mathjax mathjax-inline">$c'$</span> is already being asserted by some <em>other</em> peer. The assertion-based analogue of <span class="lyx-mathjax mathjax-inline">$\AMsg{c'}$</span> is to briefly assert <span class="lyx-mathjax mathjax-inline">$c'$</span> and then to retract it. However, redundant assertions do not cause perceptible changes in state. The net effect of the fleeting assertion of <span class="lyx-mathjax mathjax-inline">$c'$</span> is zero; no events are delivered.<label class="footnote-number" for="fn_4_38">38</label> Again, by incorporating messages primitively, we side-step the problem. Strictly speaking, the <span class="lyx-mathjax mathjax-inline">$\RMessage$</span> rule should have a side-condition forbidding its application (or perhaps making it a no-op) when <span class="lyx-mathjax mathjax-inline">$(j,c')\in R$</span> for some <span class="lyx-mathjax mathjax-inline">$j$</span>. This would imply that sending certain messages at certain times would lead reduction to become stuck. Certain data would be reserved for use in message-sending; others, for more long-lived assertions and retractions. Were this to be elaborated into a type system, each dataspace would have a type representing its protocol. This type would classify values as either message-like or assertion-like.<label class="footnote-number" for="fn_4_39">39</label> Judgments would connect with the type system of the base language to ensure that the classifications were respected by produced actions.<label class="footnote-number" for="fn_4_40">40</label></p>
<h4 id="x_4_5_0_0_1"><a name="toc_4.5"></a><span class="counter section"><span>4.5</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:DS-properties"></a><a name="sec:DS-properties"></a>Properties</span></h4><p id="x_4_5_0_0_2">A handful of theorems capture invariants that support the design of and reasoning about effective protocols for dataspace model programs. Theorem <a class="cross-reference" href="#thm:soundness">4.17</a> ensures that the dataspace does not get stuck, even though individual actors within the dataspace may behave unpredictably. Theorem <a class="cross-reference" href="#thm:determinism">4.20</a> ensures deterministic reduction of the system. Theorem <a class="cross-reference" href="#thm:order">4.23</a> assures programmers that the dataspace does not reorder an actor's actions or any of the resulting events. Theorem <a class="cross-reference" href="#thm:conversational-sound-complete">4.35</a> makes a causal connection between the actions of an actor and the events it subsequently receives. It expresses the <em>purpose</em> of the dataspace: to keep actors informed of exactly the assertions and messages relevant to their interests as those interests change. Tests constructed in Redex <span class="citation citep">(<a class="citation" id="cite-102" href="#bib-Felleisen2009a">Felleisen, Findler and Flatt 2009</a>)</span> and proofs written for Coq <span class="citation citep">(<a class="citation" id="cite-103" href="#bib-Coq:manual">Coq development team 2004</a>)</span> confirm theorems <a class="cross-reference" href="#thm:soundness">4.17</a> and <a class="cross-reference" href="#thm:determinism">4.20</a>.</p>
<div class="theorem-like numbered theorem named" id="x_4_5_0_0_4">
<p id="x_4_5_0_0_3"><span class="counter numbered theorem"><span>4.17</span></span><span class="lyx-argument">Soundness<span class="plain-layout-boundary"></span></span> <a class="label-anchor" href="#thm:soundness"></a><a name="thm:soundness"></a>A state <span class="lyx-mathjax mathjax-inline">$\Sigma\in\TState$</span> is either inert (<span class="lyx-mathjax mathjax-inline">$\Sigma\in\TStateI$</span>) or there exists some <span class="lyx-mathjax mathjax-inline">$\Sigma'$</span> such that <span class="lyx-mathjax mathjax-inline">$\Sigma\longrightarrow\Sigma'$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof named" id="x_4_5_0_0_6">
<p id="x_4_5_0_0_5"><span class="counter unnumbered proof"><span>4.17</span></span><span class="lyx-argument">Proof (Sketch)<span class="plain-layout-boundary"></span></span> We employ the Wright/Felleisen technique <span class="citation citep">(<a class="citation" id="cite-104" href="#bib-Wright1994">Wright and Felleisen 1994</a>)</span> with the progress lemma below. The proof makes use of the fact that all leaf actor behavior functions are total.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_9">
<p id="x_4_5_0_0_8"><span class="counter numbered definition"><span>4.18</span></span><span class="lyx-argument">Height<span class="plain-layout-boundary"></span></span> Let the <em>height</em> of a behavior be defined as follows:
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_7">\begin{align*}
\mathit{height} &amp; :\TBeh\rightarrow\mathbb{N}\\
\mathit{height}\;\CBehPack{\tau}{\CBehF}u &amp; =0\\
\mathit{height}\;\CCfg{\VECOF q}R{\VECOF{\CActor{\ell}{\CState{\VECOF e}B{\VECOF a}}}} &amp; =1+\mathit{max}(\VECOF{\mathit{height}\;B})
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma named" id="x_4_5_0_0_11">
<p id="x_4_5_0_0_10"><span class="counter numbered lemma"><span>4.19</span></span><span class="lyx-argument">Progress<span class="plain-layout-boundary"></span></span> For all <span class="lyx-mathjax mathjax-inline">$C\in\TCfg$</span> and <span class="lyx-mathjax mathjax-inline">$H\in\mathbb{N}$</span> such that <span class="lyx-mathjax mathjax-inline">$\mathit{height}(C)\leq H$</span>, <span class="lyx-mathjax mathjax-inline">$C$</span> is either inert (<span class="lyx-mathjax mathjax-inline">$C\in\TCfgI$</span>) or there exists some <span class="lyx-mathjax mathjax-inline">$C',\VECOF a$</span> such that <span class="lyx-mathjax mathjax-inline">$\CState{\cdot}C{\cdot}\longrightarrow\CState{\cdot}{C'}{\VECOF a}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof named" id="x_4_5_0_0_13">
<p id="x_4_5_0_0_12"><span class="counter unnumbered proof"><span>4.19</span></span><span class="lyx-argument">Proof (Sketch)<span class="plain-layout-boundary"></span></span> By nested induction on the height bound and structure of <span class="lyx-mathjax mathjax-inline">$C$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered theorem named" id="x_4_5_0_0_15">
<p id="x_4_5_0_0_14"><span class="counter numbered theorem"><span>4.20</span></span><span class="lyx-argument">Deterministic Evaluation<span class="plain-layout-boundary"></span></span> <a class="label-anchor" href="#thm:determinism"></a><a name="thm:determinism"></a>For any <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> there exists at most one <span class="lyx-mathjax mathjax-inline">$\Sigma'$</span> such that <span class="lyx-mathjax mathjax-inline">$\Sigma\longrightarrow\Sigma'$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_23">
<p id="x_4_5_0_0_21"><span class="counter unnumbered proof"><span>4.20</span></span>The reduction relation is structured to ensure at most one applicable rule in any situation. Either
<ul id="x_4_5_0_0_20"><li id="x_4_5_0_0_16"><span class="lyx-mathjax mathjax-inline">$\Sigma=\CState{\VECOF ee_{0}}{B_{I}}{\VECOF a}$</span>, in which case event <span class="lyx-mathjax mathjax-inline">$e_{0}$</span> is consumed by <span class="lyx-mathjax mathjax-inline">$B_{I}$</span> (rules <span class="lyx-mathjax mathjax-inline">$\RNotifyLeaf$</span>, <span class="lyx-mathjax mathjax-inline">$\RNotifyDS$</span>, and <span class="lyx-mathjax mathjax-inline">$\RQuit$</span>); or</li><li id="x_4_5_0_0_17"><span class="lyx-mathjax mathjax-inline">$\Sigma=\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF{A_{Q}}(\CActor{\ell}{\CState{\VECOF e'}B{\VECOF a'a''}})\VECOF A}}{\VECOF a}$</span>, in which case <span class="lyx-mathjax mathjax-inline">$a''$</span> is <span class="lyx-mathjax mathjax-inline">$\RGather$</span>ed onto <span class="lyx-mathjax mathjax-inline">$\VECOF q$</span> (rule <span class="lyx-mathjax mathjax-inline">$\RGather$</span>); or</li><li id="x_4_5_0_0_18"><span class="lyx-mathjax mathjax-inline">$\Sigma=\CState{\VECOF e}{\CCfg{\VECOF q\CQAct k{a''}}R{\VECOF{A_{Q}}}}{\VECOF a}$</span>, in which case <span class="lyx-mathjax mathjax-inline">$a''$</span> is interpreted (<span class="lyx-mathjax mathjax-inline">$\RNewtable$</span>, <span class="lyx-mathjax mathjax-inline">$\RMessage$</span>, and <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span>); or</li><li id="x_4_5_0_0_19"><span class="lyx-mathjax mathjax-inline">$\Sigma=\CState{\VECOF e}{\CCfg{\cdot}R{\VECOF{A_{I}}(\CActor{\ell}{\Sigma_{Q}})\VECOF{A_{Q}}'}}{\VECOF a}$</span> and <span class="lyx-mathjax mathjax-inline">$\Sigma_{Q}\longrightarrow\Sigma'$</span>, in which case actor <span class="lyx-mathjax mathjax-inline">$\ell$</span> takes a step (rule <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span>).</li></ul></p>
<p id="x_4_5_0_0_22">Observe that the cases are disjoint: the first demands a <span class="lyx-mathjax mathjax-inline">$B_{I}$</span>, but in the others the configuration is not inert; the second demands some non-quiescent actor; the third demands a queued action and <em>only</em> quiescent actors; the fourth demands <em>no</em> queued actions and <em>only</em> quiescent actors. Therefore, assume there exists distinct <span class="lyx-mathjax mathjax-inline">$\Sigma'$</span> and <span class="lyx-mathjax mathjax-inline">$\Sigma''$</span> such that <span class="lyx-mathjax mathjax-inline">$\Sigma\longrightarrow\Sigma'$</span> and <span class="lyx-mathjax mathjax-inline">$\Sigma\longrightarrow\Sigma''$</span>. We may then show a contradiction by nested induction on the two instances of the reduction relation and systematic elimination of possible sources of difference between <span class="lyx-mathjax mathjax-inline">$\Sigma'$</span> and <span class="lyx-mathjax mathjax-inline">$\Sigma''$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered remark named" id="x_4_5_0_0_25">
<p id="x_4_5_0_0_24"><span class="counter numbered remark"><span>4.21</span></span><span class="lyx-argument">Concurrency and determinism<span class="plain-layout-boundary"></span></span> Despite appearances, theorem <a class="cross-reference" href="#thm:determinism">4.20</a> does not sacrifice concurrency; recall from chapter <a class="cross-reference" href="#CHAP:PHILOSOPHY-AND-OVERVIEW">2</a> the argument that sequential programs frequently include internal concurrency. Concurrency does not entail nondeterminism. Even with deterministic reduction rules as written, many sources of unpredictability remain. For example, programs might interact with the outside world, including external clocks of various kinds, leading to fine variation in timing of events; code written by one person might make use of “black box” library code written by another, without precisely-documented timing specifications; or fine details of the implementation of some component could change, leading to subtly different interleavings. Introduction of nondeterminism by, say, varying the <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span> rule or relaxing some of the quiescence or inertness constraints in the other rules would merely introduce another source of unpredictability. The essential properties of the dataspace model survive such changes unharmed.</p><span class="halmos"></span></div>
<div class="theorem-like numbered remark named" id="x_4_5_0_0_27">
<p id="x_4_5_0_0_26"><span class="counter numbered remark"><span>4.22</span></span><span class="lyx-argument">Dataspace reliability<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#remark:dataspace-reliability"></a><a name="remark:dataspace-reliability"></a>While individual leaf actors may exit at any time, <em>dataspace</em> actors cannot terminate at all: no means for voluntary exit is provided, and theorem <a class="cross-reference" href="#thm:soundness">4.17</a> assures us that a dataspace will not crash. In a correct implementation of the dataspace model, dataspace actors will likewise not crash. If the implementation is buggy enough that a dataspace does in fact crash, but not so buggy that it takes its <em>containing</em> dataspace down with it, the usual removal of an actor's assertions allows peers of the failing dataspace actor to observe the consequences of its termination. Abrupt failure of a dataspace is analogous to a crash of an entire computer: there is no opportunity for a clean shutdown of the programs the computer is running; instead, the entire computer simply vanishes offline from the perspective of its peers.</p><span class="halmos"></span></div>
<div class="theorem-like numbered theorem named" id="x_4_5_0_0_29">
<p id="x_4_5_0_0_28"><span class="counter numbered theorem"><span>4.23</span></span><span class="lyx-argument">Order Preservation<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#thm:order"></a><a name="thm:order"></a> If an actor produces action A before action B, then A is interpreted by the dataspace before B. Events are enqueued atomically with interpretation of the action that causes them. If event C for actor <span class="lyx-mathjax mathjax-inline">$\ell$</span> is enqueued before event D, also for <span class="lyx-mathjax mathjax-inline">$\ell$</span>, then C is delivered before D.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof named" id="x_4_5_0_0_31">
<p id="x_4_5_0_0_30"><span class="counter unnumbered proof"><span>4.23</span></span><span class="lyx-argument">Proof (Sketch)<span class="plain-layout-boundary"></span></span> The reduction rules consistently move items one-at-a-time from the front of one queue to the back of another, and events are only enqueued during action interpretation.</p><span class="halmos"></span></div>
<div class="footnote" id="fn_4_41"><span class="counter footnote-counter"><span>41</span></span>While theorem <a class="cross-reference" href="#thm:conversational-sound-complete">4.35</a> captures many important properties of the dataspace model, it remains future work to extend it to soundness and completeness properties for assertions relayed across nested dataspace layers.<span class="plain-layout-boundary"></span></div><p id="x_4_5_0_0_32">Our final theorem (<a class="cross-reference" href="#thm:conversational-sound-complete">4.35</a>) guarantees the programmer that each actor receives “the truth, the whole truth, and nothing but the truth” from the dataspace, according to the declared interests of the actor, keeping in mind that there may be updates to the actor's interest set pending in the pipeline. It ensures that the dataspace conveys <em>every</em> relevant assertion and <em>only</em> relevant assertions,<label class="footnote-number" for="fn_4_41">41</label> and shows that the dataspace is being <em>cooperative</em> in the sense of Grice's Cooperative Principle and Conversational Maxims (section <a class="cross-reference" href="#sec:Cooperating-by-sharing-knowledge">2.1</a> and figure <a class="cross-reference" href="#fig:Grice's-Conversational-Maxims">1</a>). The theorem directly addresses the maxims of Quantity, Quality, and Relation.</p><p id="x_4_5_0_0_33">Before we are able to formally state the theorem, we must define several concepts.</p>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_40">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_34">\(\newcommand{\TPath}{\T{Path}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_35">\(\newcommand{\resolvePathName}{\mathit{resolvePath}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_36">\(\newcommand{\resolvePath}[2]{\resolvePathName\;#1\;#2}
\)</div>
<p id="x_4_5_0_0_38"><span class="counter numbered definition"><span>4.24</span></span><span class="lyx-argument">Paths<span class="plain-layout-boundary"></span></span> A <em>path</em> <span class="lyx-mathjax mathjax-inline">$p\in\TPath=\VECOF{\TLoc}\ni\VECOF{\ell}$</span> is a possibly-empty sequence of locations. A path resolves to a <span class="lyx-mathjax mathjax-inline">$\TState$</span> by the partial recursive function <span class="lyx-mathjax mathjax-inline">$\resolvePathName$</span>:
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_37">\begin{align*}
\resolvePathName &amp; :\TState\times\TPath\rightharpoonup\TState\\
\resolvePath{\Sigma}{\cdot} &amp; =\Sigma\\
\resolvePath{\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF A(\CActor{\ell}{\Sigma})\VECOF{A'}}}{\VECOF a}}{\left(\ell\;p\right)} &amp; =\resolvePath{\Sigma}p\\
\resolvePath{\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF A}}{\VECOF a}}{\left(\ell\;p\right)} &amp; \phantom{=\;}\textrm{ undefined when there is no actor labeled }\ell\textrm{ in }\VECOF A
\end{align*}
</div></p>
<p id="x_4_5_0_0_39">The definition of <span class="lyx-mathjax mathjax-inline">$\resolvePathName$</span> makes it clear that locations in a path are ordered leftmost-outermost and rightmost-innermost with respect to a nested dataspace configuration. When <span class="lyx-mathjax mathjax-inline">$\resolvePath{\Sigma}p$</span> is defined, we say <span class="lyx-mathjax mathjax-inline">$p$</span> is in <span class="lyx-mathjax mathjax-inline">$\Sigma$</span>, and write <span class="lyx-mathjax mathjax-inline">$p\in\Sigma$</span>; otherwise, <span class="lyx-mathjax mathjax-inline">$p$</span> is not in <span class="lyx-mathjax mathjax-inline">$\Sigma$</span>, <span class="lyx-mathjax mathjax-inline">$p\notin\Sigma$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_44">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_41">\(\newcommand{\DSat}[2]{R_{#1}^{#2}}
\)</div>
<p id="x_4_5_0_0_43"><span class="counter numbered definition"><span>4.25</span></span><span class="lyx-argument">Dataspace contents for a path<span class="plain-layout-boundary"></span></span> We write <span class="lyx-mathjax mathjax-inline">$\DSat{\Sigma}p$</span> to denote the contents of the shared dataspace immediately surrounding the actor denoted by nonempty path <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> in <span class="lyx-mathjax mathjax-inline">$\Sigma$</span>. That is,
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_42">\[
\DSat{\Sigma}p=R\text{ where }\resolvePath{\Sigma}{p'}=\CState{\VECOF e}{\CCfg{\VECOF q}R{\VECOF A\left(\CActor{\ell}{\Sigma'}\right)\VECOF{A'}}}{\VECOF a}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_49">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_45">\(\newcommand{\interestsOfName}{\mathit{interestsOf}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_46">\(\newcommand{\interestsOf}[2]{\interestsOfName\left(#1,#2\right)}
\)</div>
<p id="x_4_5_0_0_48"><span class="counter numbered definition"><span>4.26</span></span><span class="lyx-argument">Current interest set of <span class="lyx-mathjax mathjax-inline">$p$</span> in <span class="lyx-mathjax mathjax-inline">$\Sigma$</span><span class="plain-layout-boundary"></span></span>The <em>current interest set</em> of the actor denoted by nonempty path <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> in a given state <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> is
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_47">\[
\interestsOf p{\Sigma}\triangleq\left\{ c\;|\;(\ell,\Obs c)\in\DSat{\Sigma}p\right\}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_53">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_50">\(\newcommand{\syllabus}[2]{#1\lessdot#2}
\)</div>
<p id="x_4_5_0_0_52"><span class="counter numbered definition"><span>4.27</span></span><span class="lyx-argument">Syllabus<span class="plain-layout-boundary"></span></span>The <em>syllabus</em> of an actor with nonempty path <span class="lyx-mathjax mathjax-inline">$p$</span> at state <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> is
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_51">\[
\syllabus p{\Sigma}\triangleq\left\{ c\;|\;(j,c)\in\DSat{\Sigma}p,c\in\interestsOf p{\Sigma}\right\}
\]
</div>The syllabus describes the dataspace's understanding of <em>what </em><span class="lyx-mathjax mathjax-inline">$p$</span><em> needs to know</em> from the dataspace, as of the moment captured by the state <span class="lyx-mathjax mathjax-inline">$\Sigma$</span>; the notation is chosen to connote the idea of <span class="lyx-mathjax mathjax-inline">$p$</span> “reading” from <span class="lyx-mathjax mathjax-inline">$\Sigma$</span>. The syllabus of <span class="lyx-mathjax mathjax-inline">$p$</span> at <span class="lyx-mathjax mathjax-inline">$\Sigma$</span> will guide the dataspace as it constructs events conveying changed knowledge to <span class="lyx-mathjax mathjax-inline">$p$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_56">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_54">\(\newcommand{\REDSEQ}[1]{\mathcal{S}(#1)}
\)</div>
<p id="x_4_5_0_0_55"><span class="counter numbered definition"><span>4.28</span></span><span class="lyx-argument">Reduction sequences<span class="plain-layout-boundary"></span></span>We use the notation <span class="lyx-mathjax mathjax-inline">$\REDSEQ P\in\VECOF{\TState}$</span> to denote a finite sequence of states corresponding to a prefix of the sequence of reductions of a program <span class="lyx-mathjax mathjax-inline">$P\in\TProg$</span>. We write <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{i}\in\TState$</span> to denote the <span class="lyx-mathjax mathjax-inline">$i$</span>th element of the sequence. A sequence <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> starts with <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{0}=\Sigma$</span> where <span class="lyx-mathjax mathjax-inline">$(\Sigma,\emptyset)=\FBOOT\left(\ADS P\right)$</span>. Subsequent states in <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> are pairwise related by the reduction relation; that is, <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{0}\longrightarrow\REDSEQ P_{1}\longrightarrow\cdots\longrightarrow\REDSEQ P_{\left|\REDSEQ P\right|}$</span>. We say that a path <span class="lyx-mathjax mathjax-inline">$p$</span> is in <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> if <span class="lyx-mathjax mathjax-inline">$p\in\REDSEQ P_{i}$</span> for some <span class="lyx-mathjax mathjax-inline">$i$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_60">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_57">\(\newcommand{\enqueuedAt}[4]{\mathit{enqueuedAt}\left(#1,#2,#3,#4\right)}
\)</div>
<p id="x_4_5_0_0_59"><span class="counter numbered definition"><span>4.29</span></span><span class="lyx-argument">Enqueued events<span class="plain-layout-boundary"></span></span>We write <span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ipe$</span> when event <span class="lyx-mathjax mathjax-inline">$e$</span> is enqueued for eventual delivery to actor <span class="lyx-mathjax mathjax-inline">$p$</span> in reduction sequence <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> at the transition <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{i}\longrightarrow\REDSEQ P_{i+1}$</span>:
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_58">\begin{align*}
\enqueuedAt{\REDSEQ P}ipe\iff &amp; \big(\resolvePath{\REDSEQ P_{i}}p=\CState{\VECOF e'}B{\VECOF a}\\
&amp; \wedge\resolvePath{\REDSEQ P_{i+1}}p=\CState{e\VECOF e'}B{\VECOF a}\big)
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_62">
<div class="footnote" id="fn_4_42"><span class="counter footnote-counter"><span>42</span></span>Here, as elsewhere in this chapter, <span class="lyx-mathjax mathjax-inline">$\{c\;|\;(j,c)\in R\}$</span> is interpreted as <span class="lyx-mathjax mathjax-inline">$\{c\;|\;\exists j.\;(j,c)\in R\}$</span> when <span class="lyx-mathjax mathjax-inline">$j$</span> is free.<span class="plain-layout-boundary"></span></div>
<p id="x_4_5_0_0_61"><span class="counter numbered definition"><span>4.30</span></span><span class="lyx-argument">Truthfulness<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:truthfulness"></a><a name="def:truthfulness"></a> An assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is called <em>truthful</em> with respect to a dataspace whose contents are <span class="lyx-mathjax mathjax-inline">$R$</span> if it contains only assertions actually present in <span class="lyx-mathjax mathjax-inline">$R$</span>. That is, <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is truthful if <span class="lyx-mathjax mathjax-inline">$\ROUTES\subseteq\{c\;|\;(j,c)\in R\}$</span>.<label class="footnote-number" for="fn_4_42">42</label></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_64">
<p id="x_4_5_0_0_63"><span class="counter numbered definition"><span>4.31</span></span><span class="lyx-argument">Relevance<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:relevance"></a><a name="def:relevance"></a> An assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is called <em>relevant</em> to an actor <span class="lyx-mathjax mathjax-inline">$\ell$</span> in a dataspace whose contents are <span class="lyx-mathjax mathjax-inline">$R$</span> if it contains only assertions of interest to <span class="lyx-mathjax mathjax-inline">$\ell$</span>; i.e., if <span class="lyx-mathjax mathjax-inline">$\ROUTES\subseteq\{c\;|\;(\ell,\Obs c)\in R\}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_66">
<p id="x_4_5_0_0_65"><span class="counter numbered definition"><span>4.32</span></span><span class="lyx-argument">Soundness<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:soundness"></a><a name="def:soundness"></a> An assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is called <em>sound</em> for an actor <span class="lyx-mathjax mathjax-inline">$\ell$</span> in a dataspace whose contents are <span class="lyx-mathjax mathjax-inline">$R$</span> if it is both truthful w.r.t <span class="lyx-mathjax mathjax-inline">$R$</span> and relevant w.r.t. <span class="lyx-mathjax mathjax-inline">$\ell$</span> and <span class="lyx-mathjax mathjax-inline">$R$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_68">
<p id="x_4_5_0_0_67"><span class="counter numbered definition"><span>4.33</span></span><span class="lyx-argument">Completeness<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:completeness"></a><a name="def:completeness"></a> An assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is called <em>complete</em> for an actor named <span class="lyx-mathjax mathjax-inline">$\ell$</span> in a dataspace whose contents are <span class="lyx-mathjax mathjax-inline">$R$</span> if it contains every assertion both actually present and of interest to <span class="lyx-mathjax mathjax-inline">$\ell$</span>; that is, if <span class="lyx-mathjax mathjax-inline">$\ROUTES\supseteq\left(\{c\;|\;(j,c)\in R\}\cap\{c\;|\;(\ell,\Obs c)\in R\}\right)$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_5_0_0_72">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_69">\(\newcommand{\MRSCN}[3]{\ROUTES_{#1}^{#3,#2}}
\)</div>
<p id="x_4_5_0_0_71"><span class="counter numbered definition"><span>4.34</span></span><a class="label-anchor" href="#def:mrscn"></a><a name="def:mrscn"></a><span class="lyx-argument">Most recent SCN event<span class="plain-layout-boundary"></span></span> Let <span class="lyx-mathjax mathjax-inline">$p$</span> be a path of an actor, <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> be a reduction sequence, and <span class="lyx-mathjax mathjax-inline">$i$</span> in index to a state in <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span>. The most recent SCN event enqueued for <span class="lyx-mathjax mathjax-inline">$p$</span> as it exists within <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{i}$</span>, written <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}$</span>, is computed by
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_70">\[
\MRSCN ip{\REDSEQ P}=\begin{cases}
\ROUTES' &amp; \text{if }\enqueuedAt{\REDSEQ P}{i-1}p{\ROUTES'}\text{; otherwise,}\\
\MRSCN{i-1}p{\REDSEQ P} &amp; \text{if }\resolvePath{\REDSEQ P_{i}}p\text{ is defined; otherwise,}\\
\emptyset
\end{cases}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered theorem named" id="x_4_5_0_0_79">
<p id="x_4_5_0_0_78"><span class="counter numbered theorem"><span>4.35</span></span><span class="lyx-argument">Conversational Soundness and Completeness<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#thm:conversational-sound-complete"></a><a name="thm:conversational-sound-complete"></a> Let <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> be a reduction sequence. For every actor denoted by a nonempty path <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> in <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span>, at every step <span class="lyx-mathjax mathjax-inline">$i$</span>,
<ol id="x_4_5_0_0_77"><li id="x_4_5_0_0_73"><a class="label-anchor" href="#enu:assertions-follow-actions"></a><a name="enu:assertions-follow-actions"></a><span class="lyx-mathjax mathjax-inline">$\interestsOf p{\REDSEQ P_{i}}$</span> depends solely on successive SCN actions issued by actor <span class="lyx-mathjax mathjax-inline">$p$</span>.</li><li id="x_4_5_0_0_74"><a class="label-anchor" href="#enu:syllabus-change-iff-scn"></a><a name="enu:syllabus-change-iff-scn"></a><span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i}}\not=\syllabus p{\REDSEQ P_{i+1}}$</span> iff there exists <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> such that <span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ip{\ROUTES}$</span>.</li><li id="x_4_5_0_0_75"><a class="label-anchor" href="#enu:scn-sound-complete"></a><a name="enu:scn-sound-complete"></a><span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ip{\ROUTES}$</span> implies that <span class="lyx-mathjax mathjax-inline">$\pi$</span> is sound and complete for <span class="lyx-mathjax mathjax-inline">$\ell$</span> and <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{i+1}}p$</span>.</li><li id="x_4_5_0_0_76"><a class="label-anchor" href="#enu:message-sound-complete"></a><a name="enu:message-sound-complete"></a><span class="lyx-mathjax mathjax-inline">$\resolvePath{\REDSEQ P_{i}}{p'}=\CState{\VECOF e}{\CCfg{\VECOF q\CQAct k{\AMsg c}}{\DSat{\REDSEQ P_{i}}p}{\VECOF A\left(\CActor{\ell}{\Sigma}\right)\VECOF A'}}{\VECOF a}\wedge c\in\interestsOf p{\REDSEQ P_{i}}$</span><br/><span class="lyx-mathjax mathjax-inline">$\iff\enqueuedAt{\REDSEQ P}ip{\AMsg c}$</span>.</li></ol></p><span class="halmos"></span></div><p id="x_4_5_0_0_80">That is: (<a class="cross-reference" href="#enu:assertions-follow-actions">1</a>) the dataspace's understanding of the interests of <span class="lyx-mathjax mathjax-inline">$p$</span> (which shape its syllabus) is solely determined by the actions of <span class="lyx-mathjax mathjax-inline">$p$</span>; (<a class="cross-reference" href="#enu:syllabus-change-iff-scn">2</a>) every time the syllabus of <span class="lyx-mathjax mathjax-inline">$p$</span> changes, an SCN event is enqueued for <span class="lyx-mathjax mathjax-inline">$p$</span>, and every SCN event enqueued for <span class="lyx-mathjax mathjax-inline">$p$</span> results from a change in its syllabus; (<a class="cross-reference" href="#enu:scn-sound-complete">3</a>) every SCN event for <span class="lyx-mathjax mathjax-inline">$p$</span> is sound and complete with respect to the interests of <span class="lyx-mathjax mathjax-inline">$p$</span> and the contents of the dataspace of <span class="lyx-mathjax mathjax-inline">$p$</span>; and (<a class="cross-reference" href="#enu:message-sound-complete">4</a>) every message action of interest to <span class="lyx-mathjax mathjax-inline">$p$</span> results in a message event for <span class="lyx-mathjax mathjax-inline">$p$</span>, and no other message events are produced for <span class="lyx-mathjax mathjax-inline">$p$</span>.</p>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_86">
<p id="x_4_5_0_0_81"><span class="counter unnumbered proof"><span>4.35</span></span> </p>
<p id="x_4_5_0_0_82">(<a class="cross-reference" href="#enu:assertions-follow-actions">1</a>) By lemma <a class="cross-reference" href="#lem:mrscn-action-reflected">4.36</a>, the <span class="lyx-mathjax mathjax-inline">$\RGather$</span> rule, and theorem <a class="cross-reference" href="#thm:order">4.23</a>.</p>
<p id="x_4_5_0_0_83">(<a class="cross-reference" href="#enu:syllabus-change-iff-scn">2</a>) Forward direction: by lemma <a class="cross-reference" href="#lem:mrscn-is-good">4.40</a>, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\not=\MRSCN{i+1}p{\REDSEQ P}$</span>. Let <span class="lyx-mathjax mathjax-inline">$\ROUTES=\MRSCN{i+1}p{\REDSEQ P}$</span>, and the conclusion follows from lemma <a class="cross-reference" href="#lem:mrscn-change-because-new-scn-event">4.37</a>. Reverse direction: we are given some <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> s.t. <span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ip{\ROUTES}$</span>. By definition, then, <span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}=\ROUTES$</span>; by lemma <a class="cross-reference" href="#lem:mrscn-necessity">4.42</a>, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\not=\ROUTES$</span>. Combining these facts, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\not=\MRSCN{i+1}p{\REDSEQ P}$</span>; now, apply lemma <a class="cross-reference" href="#lem:mrscn-is-good">4.40</a> and we are done.</p>
<p id="x_4_5_0_0_84">(<a class="cross-reference" href="#enu:scn-sound-complete">3</a>) By definition, in conjunction with our premises, <span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}=\ROUTES$</span>; lemma <a class="cross-reference" href="#lem:mrscn-sound-complete">4.41</a> yields our result.</p>
<p id="x_4_5_0_0_85">(<a class="cross-reference" href="#enu:message-sound-complete">4</a>) Forward direction: rule <span class="lyx-mathjax mathjax-inline">$\RMessage$</span> is the only applicable rule; the conclusion follows by definition of <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> for message routing. Reverse direction: likewise, because rule <span class="lyx-mathjax mathjax-inline">$\RMessage$</span> is the only rule that enqueues message events.</p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma" id="x_4_5_0_0_91">
<p id="x_4_5_0_0_90"><span class="counter numbered lemma"><span>4.36</span></span><a class="label-anchor" href="#lem:mrscn-action-reflected"></a><a name="lem:mrscn-action-reflected"></a>Let <span class="lyx-mathjax mathjax-inline">$p=(p'\;\ell)$</span> be a nonempty path of an actor in some <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span>. Wherever <span class="lyx-mathjax mathjax-inline">$\interestsOf p{\REDSEQ P_{i}}\not=\interestsOf p{\REDSEQ P_{i+1}}$</span>, we have that:
<ol id="x_4_5_0_0_89"><li id="x_4_5_0_0_87"><span class="lyx-mathjax mathjax-inline">$\VECOF q=\VECOF{q'}(\ell,\pi)$</span>, where <span class="lyx-mathjax mathjax-inline">$\resolvePath{\REDSEQ P_{i}}{p'}=\CState{\VECOF e}{\CCfg{\VECOF q}{\DSat{\REDSEQ P_{i}}p}{\VECOF A\left(\CActor{\ell}{\Sigma}\right)\VECOF{A'}}}{\VECOF a}$</span>, and</li><li id="x_4_5_0_0_88"><span class="lyx-mathjax mathjax-inline">$\interestsOf p{\REDSEQ P_{i+1}}=\left\{ c\;|\;\Obs c\in\ROUTES\right\} $</span>.</li></ol></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_93">
<p id="x_4_5_0_0_92"><span class="counter unnumbered proof"><span>4.36</span></span>Direct from the facts that rule <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> is the only possible rule that can apply as <span class="lyx-mathjax mathjax-inline">$\REDSEQ P_{i}\longrightarrow\REDSEQ P_{i+1}$</span> and that <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> replaces <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{i}}p$</span> in the containing dataspace of <span class="lyx-mathjax mathjax-inline">$p$</span> with <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{i+1}}p=R\oplus(\ell,\pi)$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma" id="x_4_5_0_0_95">
<p id="x_4_5_0_0_94"><span class="counter numbered lemma"><span>4.37</span></span><a class="label-anchor" href="#lem:mrscn-change-because-new-scn-event"></a><a name="lem:mrscn-change-because-new-scn-event"></a> <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\not=\MRSCN{i+1}p{\REDSEQ P}\implies\enqueuedAt{\REDSEQ P}ip{\MRSCN{i+1}p{\REDSEQ P}}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_97">
<p id="x_4_5_0_0_96"><span class="counter unnumbered proof"><span>4.37</span></span>Straightforward consequence of definition <a class="cross-reference" href="#def:mrscn">4.34</a>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_4_5_0_0_101">
<div class="lyx-mathjax mathjax-definitions" id="x_4_5_0_0_98">\(\newcommand{\InHole}[6]{#1\left[#3\right]\overset{#2:#6}{\longrightarrow}#4\left[#5\right]}
\)</div>
<p id="x_4_5_0_0_100"><span class="counter numbered definition"><span>4.38</span></span><a class="label-anchor" href="#def:InHole"></a><a name="def:InHole"></a>The notation <span class="lyx-mathjax mathjax-inline">$\InHole{\Sigma_{a}}p{\Sigma_{b}}{\Sigma_{c}}{\Sigma_{d}}r$</span> is interpreted as a relation defined by:
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_99">\begin{align*}
\InHole{\Sigma_{a}}{\cdot}{\Sigma_{a}}{\Sigma_{c}}{\Sigma_{c}}r &amp; \iff\Sigma_{a}\longrightarrow\Sigma_{c}\text{ by rule }r\\
\InHole{\Sigma_{a}}{(\ell\;p)}{\Sigma_{b}}{\Sigma_{c}}{\Sigma_{d}}r &amp; \iff\big(\Sigma_{a}\longrightarrow\Sigma_{c}\text{ by rule }\RSchedule\\
&amp; \phantom{\iff}\;\wedge\InHole{\left(\resolvePath{\Sigma_{a}}{\ell}\right)}p{\Sigma_{b}}{\left(\resolvePath{\Sigma_{c}}{\ell}\right)}{\Sigma_{d}}r\big)
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma" id="x_4_5_0_0_106">
<p id="x_4_5_0_0_105"><span class="counter numbered lemma"><span>4.39</span></span><a class="label-anchor" href="#lem:mrscn-change-by-bc"></a><a name="lem:mrscn-change-by-bc"></a>Let <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> be a nonempty path and <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> be a reduction sequence. If <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\not=\MRSCN{i+1}p{\REDSEQ P}$</span>,
<ol id="x_4_5_0_0_104"><li id="x_4_5_0_0_102"><span class="lyx-mathjax mathjax-inline">$\InHole{\REDSEQ P_{i}}{p'}{\Sigma'}{\REDSEQ P_{i+1}}{\Sigma''}{\RNewtable}$</span> for some <span class="lyx-mathjax mathjax-inline">$\Sigma',\Sigma''$</span></li><li id="x_4_5_0_0_103"><span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}=\{c\;|\;(j,c)\in\DSat{\REDSEQ P_{i+1}}p,(\ell,\Obs c)\in\DSat{\REDSEQ P_{i+1}}p\}=\syllabus p{\REDSEQ P_{i+1}}$</span></li></ol></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_108">
<p id="x_4_5_0_0_107"><span class="counter unnumbered proof"><span>4.39</span></span>1. By lemma <a class="cross-reference" href="#lem:mrscn-change-because-new-scn-event">4.37</a>, an SCN event must be enqueued for <span class="lyx-mathjax mathjax-inline">$p$</span> at this step; no other rule than <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> enqueues SCN events. 2. Metafunction <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> is the source of the new SCN event, which is equal to <span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}$</span> by definition. The first case of <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> must apply in order for some event to be enqueued; following the definitions and the use of <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> in the <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> rule gives us our result.</p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma" id="x_4_5_0_0_110">
<p id="x_4_5_0_0_109"><span class="counter numbered lemma"><span>4.40</span></span><a class="label-anchor" href="#lem:mrscn-is-good"></a><a name="lem:mrscn-is-good"></a>Let <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> be a nonempty path and <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> be a reduction sequence. For every <span class="lyx-mathjax mathjax-inline">$i$</span>, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}=\syllabus p{\REDSEQ P_{i}}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_119">
<p id="x_4_5_0_0_118"><span class="counter unnumbered proof"><span>4.40</span></span>By induction on <span class="lyx-mathjax mathjax-inline">$i$</span>.
<ul id="x_4_5_0_0_117"><li id="x_4_5_0_0_111">Case <span class="lyx-mathjax mathjax-inline">$i=0$</span>. Recall that <span class="lyx-mathjax mathjax-inline">$\left(\REDSEQ P_{0},\emptyset\right)=\FBOOT\left(\ADS P\right)=\left(\CState{\cdot}{\CCfg{\CQAct{\CMeta}P}{\emptyset}{\cdot}}{\cdot},\emptyset\right)$</span>. Vacuously true, because both <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{0}}p$</span> and <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{0}}$</span> are undefined for all <span class="lyx-mathjax mathjax-inline">$p$</span>.</li><li id="x_4_5_0_0_116">Case <span class="lyx-mathjax mathjax-inline">$i&gt;0$</span>. If <span class="lyx-mathjax mathjax-inline">$\MRSCN{i-1}p{\REDSEQ P}\not=\MRSCN ip{\REDSEQ P}$</span>, the result is immediate, by lemma <a class="cross-reference" href="#lem:mrscn-change-by-bc">4.39</a>. Otherwise, <span class="lyx-mathjax mathjax-inline">$\MRSCN{i-1}p{\REDSEQ P}=\MRSCN ip{\REDSEQ P}$</span>; combining this with the induction hypothesis, we learn that <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}=\syllabus p{\REDSEQ P_{i-1}}$</span>.<p id="x_4_5_0_0_112">There are two cases to consider: either the dataspace containing actor <span class="lyx-mathjax mathjax-inline">$p$</span> steps by rule <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span>, or some other kind of reduction takes place.</p>
<ul id="x_4_5_0_0_115"><li id="x_4_5_0_0_113">If for some <span class="lyx-mathjax mathjax-inline">$\Sigma',\Sigma''$</span> we have that <span class="lyx-mathjax mathjax-inline">$\InHole{\REDSEQ P_{i-1}}{p'}{\Sigma'}{\REDSEQ P_{i}}{\Sigma''}{\RNewtable}$</span>, then we know that an actor <span class="lyx-mathjax mathjax-inline">$\left(\CActor{\ell}{\CState{\VECOF e'}B{\cdot}}\right)$</span> is an immediate child of the dataspace configuration in <span class="lyx-mathjax mathjax-inline">$\Sigma'$</span>. Furthermore we know that <span class="lyx-mathjax mathjax-inline">$\left(\CActor{\ell}{\CState{\VECOF e'}B{\cdot}}\right)$</span> must also be an immediate child of the dataspace configuration in <span class="lyx-mathjax mathjax-inline">$\Sigma''$</span>, because otherwise <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}$</span> would differ from <span class="lyx-mathjax mathjax-inline">$\MRSCN{i-1}p{\REDSEQ P}$</span>. It follows then that the second case of <span class="lyx-mathjax mathjax-inline">$\FBCName$</span> must apply for actor <span class="lyx-mathjax mathjax-inline">$\ell$</span> in this reduction step, and so <span class="lyx-mathjax mathjax-inline">$\FBCName$</span>'s <span class="lyx-mathjax mathjax-inline">$\ROUTESnew=\ROUTESold$</span>, meaning that <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i}}=\syllabus p{\REDSEQ P_{i-1}}$</span>. By <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}=\syllabus p{\REDSEQ P_{i-1}}$</span>, we are done.</li><li id="x_4_5_0_0_114">Otherwise, it must be the case that <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{i-1}}p=\DSat{\REDSEQ P_{i}}p$</span>, because no other reduction step can possibly affect the <span class="lyx-mathjax mathjax-inline">$R$</span> register of the dataspace containing actor <span class="lyx-mathjax mathjax-inline">$p$</span>. Applying this to prove <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i}}=\syllabus p{\REDSEQ P_{i-1}}$</span> gives our result by <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}=\syllabus p{\REDSEQ P_{i-1}}$</span>.</li></ul></li></ul></p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma" id="x_4_5_0_0_121">
<p id="x_4_5_0_0_120"><span class="counter numbered lemma"><span>4.41</span></span><a class="label-anchor" href="#lem:mrscn-sound-complete"></a><a name="lem:mrscn-sound-complete"></a>Let <span class="lyx-mathjax mathjax-inline">$p=\left(p'\;\ell\right)$</span> be a nonempty path and <span class="lyx-mathjax mathjax-inline">$\REDSEQ P$</span> be a reduction sequence. For every <span class="lyx-mathjax mathjax-inline">$i$</span>, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}$</span> is both sound and complete w.r.t. <span class="lyx-mathjax mathjax-inline">$\ell$</span> and <span class="lyx-mathjax mathjax-inline">$\DSat{\REDSEQ P_{i}}p$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_126">
<p id="x_4_5_0_0_125"><span class="counter unnumbered proof"><span>4.41</span></span>By lemma <a class="cross-reference" href="#lem:mrscn-is-good">4.40</a>, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}=\syllabus p{\REDSEQ P_{i}}$</span>. We must show:
<ul id="x_4_5_0_0_124"><li id="x_4_5_0_0_122">Soundness demands truthfulness, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\subseteq\{c\;|\;(j,c)\in\DSat{\REDSEQ P_{i}}p\}$</span> and relevance, <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\subseteq\{c\;|\;(\ell,\Obs c)\in\DSat{\REDSEQ P_{i}}p\}$</span>. Both these properties are immediate from the definition of <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i}}$</span>.</li><li id="x_4_5_0_0_123">Completeness demands <span class="lyx-mathjax mathjax-inline">$\MRSCN ip{\REDSEQ P}\supseteq\left(\{c\;|\;(j,c)\in\DSat{\REDSEQ P_{i}}p\}\cap\{c\;|\;(\ell,\Obs c)\in\DSat{\REDSEQ P_{i}}p\}\right)$</span>; this is also immediate from the definition of <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i}}$</span>.</li></ul></p><span class="halmos"></span></div>
<div class="theorem-like numbered lemma named" id="x_4_5_0_0_128">
<p id="x_4_5_0_0_127"><span class="counter numbered lemma"><span>4.42</span></span><span class="lyx-argument">Necessity<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#lem:mrscn-necessity"></a><a name="lem:mrscn-necessity"></a><span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ip{\ROUTES'}\implies\MRSCN ip{\REDSEQ P}\not=\ROUTES'$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_4_5_0_0_131">
<p id="x_4_5_0_0_130"><span class="counter unnumbered proof"><span>4.42</span></span>Only rule <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> can enqueue an event <span class="lyx-mathjax mathjax-inline">$\ROUTES'$</span> for <span class="lyx-mathjax mathjax-inline">$p$</span>. But it will only do so if, in <span class="lyx-mathjax mathjax-inline">$\FBCName$</span>, <span class="lyx-mathjax mathjax-inline">$\Rnew\not=\Rold$</span>; that is, if
<div class="lyx-mathjax mathjax-display" id="x_4_5_0_0_129">\begin{align*}
\{c\;|\;(j,c)\in\DSat{\REDSEQ P_{i+1}}p,(\ell,\Obs c)\in\DSat{\REDSEQ P_{i+1}}p\} &amp; \not=\{c\;|\;(j,c)\in\DSat{\REDSEQ P_{i}}p,(\ell,\Obs c)\in\DSat{\REDSEQ P_{i}}p\}
\end{align*}
</div>Applying the definition of syllabus, this is <span class="lyx-mathjax mathjax-inline">$\syllabus p{\REDSEQ P_{i+1}}\not=\syllabus p{\REDSEQ P_{i}}$</span>, and lemma <a class="cross-reference" href="#lem:mrscn-is-good">4.40</a> gives <span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}\not=\MRSCN ip{\REDSEQ P}$</span>. By definition, <span class="lyx-mathjax mathjax-inline">$\MRSCN{i+1}p{\REDSEQ P}=\ROUTES'$</span> because <span class="lyx-mathjax mathjax-inline">$\enqueuedAt{\REDSEQ P}ip{\ROUTES'}$</span>, and so we know that <span class="lyx-mathjax mathjax-inline">$\ROUTES'\not=\MRSCN ip{\REDSEQ P}$</span>.</p><span class="halmos"></span></div><p id="x_4_5_0_0_132">The “soundness” properties of theorem <a class="cross-reference" href="#thm:conversational-sound-complete">4.35</a> forbid <em>overapproximation</em> of the interests of the actor; communicated assertions and messages must be genuinely relevant. However, when taken alone, they permit omission of information. The “completeness” properties ensure timely communication of <em>all</em> relevant assertions and messages, but taken alone permit inclusion of irrelevancies. It is only when both kinds of property are taken together that we obtain a practical result.</p><p id="x_4_5_0_0_133">It is interesting to consider variations on the model that weaken these properties. A dataspace allowing inclusion of assertions not in <span class="lyx-mathjax mathjax-inline">$R$</span> (violation of <em>truthfulness</em>) would be harmful: it would violate Grice's maxims of Quality, and hence risk being branded uncooperative. Likewise, a dataspace <em>omitting</em> assertions in <span class="lyx-mathjax mathjax-inline">$R$</span> it knows to be of interest (violation of <em>completeness</em>) would also be harmful: this violates the first maxim of Quantity and the maxim of Relation. By contrast, allowing inclusion of assertions not in the interest set of a given actor (violation of <em>relevance</em>) would not be harmful, and may even be useful, even though strictly this overinformativeness would be a violation of the second maxim of Quantity. For example, it may be more convenient or more efficient for a dataspace to convey “all sizes are available” than the collection of separate facts “size 4 is available”, “size 6 is available” and “size 7 is available” to some actor expressing interest only in the specific sizes 4, 6 and 7. As another example, use of a narrow probabilistic overapproximation of an actor's interest (e.g. a Bloom filter <span class="citation citep">(<a class="citation" id="cite-105" href="#bib-Bloom1970">Bloom 1970</a>)</span>) could save significant memory and CPU resources in a dataspace implementation while placing only the modest burden of discarding irrelevant assertions on each individual actor.</p><p id="x_4_5_0_0_134">All this is true only in situations where <em>secrecy</em> is not a concern. If it is important that actors be forbidden from learning the contents of certain assertions, then the relevance aspect of soundness suddenly becomes crucial. For example, consider a system using unguessable IDs as capabilities. Clearly, it would be wrong to send an actor spurious assertions mentioning capabilities that it does not legitimately hold. Secrecy is further discussed in section <a class="cross-reference" href="#par:Firewalls">11.3</a>.</p>
<h4 id="x_4_6_0_0_1"><a name="toc_4.6"></a><span class="counter section"><span>4.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:incremental-DS"></a><a name="sec:incremental-DS"></a>Incremental assertion-set maintenance</span></h4><p id="x_4_6_0_0_2">Taking section <a class="cross-reference" href="#sec:Formal-DS-semantics">4.2</a> literally implies that dataspaces convey entire sets of assertions back and forth every time some assertion changes. While wholesale transmission is a convenient illusion, it is intractable as an implementation strategy. Because the <em>change</em> in state from one moment to the next is usually small, actors and dataspaces transmit redundant information with each action and event. In short, the model needs an incremental semantics. Relatedly, while many actors find natural expression in terms of whole sets of assertions, some are best expressed in terms of reactions to changes in state. Supporting a change-oriented interface between leaf actors and their dataspaces simplifies the programmer's task in these cases.</p><p id="x_4_6_0_0_3">Starting from the definitions of section <a class="cross-reference" href="#sec:Informal-DS-semantics">4.1</a>, we replace assertion-set state-change notification events with <em>patches</em>. Patches allow incremental maintenance of the shared dataspace without materially changing the semantics in other respects. When extended to code in leaf actors, they permit incremental computation in response to changes. We will call the syntax and semantics already presented the <em>monolithic</em> dataspace model, and the altered syntax and semantics introduced in this section the <em>incremental</em> dataspace model.</p><p id="x_4_6_0_0_5">The required changes to program syntax are small. We replace assertion sets <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> with patches <span class="lyx-mathjax mathjax-inline">$\Delta$</span> in the syntax of events and actions:
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_4">\begin{align*}
\textrm{Events }e\in\TEvt &amp; ::=\AMsg c\;|\;\Delta\\
\textrm{Actions }a\in\TAct &amp; ::=\AMsg c\;|\;\Delta\;|\;P\\
\textrm{Patches }\Delta\in\TPatch &amp; ::=\CPatch{\ROUTESADD}{\ROUTESDEL}\textrm{ where }\ROUTESADD\cap\ROUTESDEL=\emptyset
\end{align*}
</div>All other definitions from figures <a class="cross-reference" href="#fig:DS-program-syntax">12</a> and <a class="cross-reference" href="#fig:DS-evaluation-syntax">14</a> remain the same. The configuration syntax is as before, except that queued events and actions now use patches instead of assertion sets. Behavior functions, too, exchange patches with their callers.</p>
<div class="footnote" id="fn_4_43"><span class="counter footnote-counter"><span>43</span></span>Disjointness of <span class="lyx-mathjax mathjax-inline">$\ROUTESADD$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTESDEL$</span> ensures that a patch can be applied either <span class="lyx-mathjax mathjax-inline">$\ROUTESADD$</span>-first or <span class="lyx-mathjax mathjax-inline">$\ROUTESDEL$</span>-first without affecting the result.<span class="plain-layout-boundary"></span></div><p id="x_4_6_0_0_6">Patches denote changes in assertion sets. They are intended to be applied to some existing set of assertions. The notation is chosen to resemble a substitution, with elements to be added to the set written above the line and those to be removed below. We require that a patch's two sets be disjoint.<label class="footnote-number" for="fn_4_43">43</label></p>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_9">
<p id="x_4_6_0_0_8"><span class="counter numbered definition"><span>4.43</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RPatch$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:patch"></a><a name="def:rule:patch"></a>To match the exchange of patches for assertion sets, we replace the <span class="lyx-mathjax mathjax-inline">$\RNewtable$</span> reduction rule (definition <a class="cross-reference" href="#def:rule:newtable">4.11</a> and figure <a class="cross-reference" href="#fig:DS-reductions">15</a>) with a rule for applying patches:
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_7">\begin{align*}
\CState{\VECOF e}{\CCfg{\VECOF q\CQAct k{\Delta}}{\rlap{R}\phantom{R\oplus\CQAct k{\Delta'}}}{\rlap{\VECOF{A_{Q}}}\phantom{\VECOF{\FBCD k{\Delta'}R{A_{Q}}}}}}{\phantom{(\FOUT k{\Delta'}R)}\VECOF a} &amp; &amp; &amp; &amp; (\RPatch)\\
\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\phantom{\CQAct k{\Delta}}}{R\oplus\CQAct k{\Delta'}}{\VECOF{\FBCD k{\Delta'}R{A_{Q}}}}}{(\FOUT k{\Delta'}R)\VECOF a}
\end{align*}
</div>where <span class="lyx-mathjax mathjax-inline">${\displaystyle \Delta=\CPatch{\ROUTESADD}{\ROUTESDEL}}$</span> and <span class="lyx-mathjax mathjax-inline">${\displaystyle \Delta'=\CPatch{\ROUTESADDpad-\{c\;|\;(k,c)\in R\}}{\ROUTESDEL\hspace{3pt}\cap\{c\;|\;(k,c)\in R\}}}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered remark" id="x_4_6_0_0_11">
<p id="x_4_6_0_0_10"><span class="counter unnumbered remark"><span>4.43</span></span>The effect of the definition of <span class="lyx-mathjax mathjax-inline">$\Delta'$</span> is to render harmless any attempt by <span class="lyx-mathjax mathjax-inline">$k$</span> to add an assertion it has already added or retract an assertion that is not asserted.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_14">
<p id="x_4_6_0_0_13"><span class="counter numbered definition"><span>4.44</span></span><span class="lyx-argument">Dataspace patching<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:oplus-incremental"></a><a name="def:mf:oplus-incremental"></a>The <span class="lyx-mathjax mathjax-inline">$\oplus$</span> operator, defined above for wholesale assertion-set updates (definition <a class="cross-reference" href="#def:mf:oplus-monolithic">4.10</a>), is straightforwardly adapted to patches:
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_12">\[
R\oplus(k,\CPatch{\ROUTESADD}{\ROUTESDEL})=R\cup\{(k,c)\,|\,c\in\ROUTESADD\}-\{(k,c)\,|\,c\in\ROUTESDEL\}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_17">
<p id="x_4_6_0_0_16"><span class="counter numbered definition"><span>4.45</span></span><span class="lyx-argument">Inbound patch transformation<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:inp-incremental"></a><a name="def:mf:inp-incremental"></a>The <span class="lyx-mathjax mathjax-inline">$\FINP$</span> metafunction is likewise easily adjusted:
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_15">\[
\FINP\;\CPatch{\ROUTESADD}{\ROUTESDEL}=\CPatch{\{\In c\;|\;c\in\ROUTESADDpad\}}{\{\In c\;|\;c\in\ROUTESDEL\}}
\]
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_20">
<div class="footnote" id="fn_4_44"><span class="counter footnote-counter"><span>44</span></span>The definition of <span class="lyx-mathjax mathjax-inline">$\ROUTES'$</span> here is analogous to that of <span class="lyx-mathjax mathjax-inline">$\ROUTESbullet$</span> in the definition of <span class="lyx-mathjax mathjax-inline">$\FBCDName$</span>, which also filters <span class="lyx-mathjax mathjax-inline">$R$</span> to compute a mask applied to the patch.<span class="plain-layout-boundary"></span></div>
<p id="x_4_6_0_0_19"><span class="counter numbered definition"><span>4.46</span></span><span class="lyx-argument">Outbound patch transformation<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:out-incremental"></a><a name="def:mf:out-incremental"></a>It is the <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> metafunction that requires deep surgery. We must take care not only to correctly relabel assertions in the resulting patch but to signal only true changes to the aggregate set of assertions of the entire dataspace:<label class="footnote-number" for="fn_4_44">44</label>
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_18">\begin{align*}
\FOUT{\ell}{\CPatch{\ROUTESADD}{\ROUTESDEL}}R &amp; =\CPatch{\{c\;|\;\Out c\in(\ROUTESADDpad-\ROUTES')\}\cup\{\Obs c\;|\;\Obs{\In c}\in(\ROUTESADDpad-\ROUTES')\}}{\{c\;|\;\Out c\in(\ROUTESDEL-\ROUTES')\}\cup\{\Obs c\;|\;\Obs{\In c}\in(\ROUTESDEL-\ROUTES')\}}\\
\textrm{where } &amp; \ROUTES'=\{c\,|\,(j,c)\in R,\,j\neq\ell\}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_24">
<p id="x_4_6_0_0_23"><span class="counter numbered definition"><span>4.47</span></span><span class="lyx-argument">Patch event broadcast<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:bcd"></a><a name="def:mf:bcd"></a>The metafunction <span class="lyx-mathjax mathjax-inline">$\FBCDName$</span>, used in the <span class="lyx-mathjax mathjax-inline">$\RPatch$</span> rule, constructs a state change notification patch event tailored to the interests of actor <span class="lyx-mathjax mathjax-inline">$\ell$</span>. The notification describes the net change to the shared dataspace caused by actor <span class="lyx-mathjax mathjax-inline">$k$</span>'s patch action—as far as that change is relevant to the interests of <span class="lyx-mathjax mathjax-inline">$\ell$</span>.
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_21">\begin{align*}
\FBCDName:\TID\times\TPatch\times\TSpace\times\TActorQ &amp; \rightarrow\TActor\\
\FBCD k{\CPatch{\ROUTESADD}{\ROUTESDEL}}{\Rold}{(\CActor{\ell}{\CState{\VECOF e}B{\cdot}})} &amp; =\begin{cases}
\CActor{\ell}{\CState{\rlap{\DeltaFb}\phantom{\DeltaOther}\VECOF e}B{\cdot}} &amp; \textrm{if \(\ell=k\) and \(\DeltaFb\not=\CPatch{\emptyset}{\emptyset}\)}\\
\CActor{\ell}{\CState{\DeltaOther\VECOF e}B{\cdot}} &amp; \textrm{if \(\ell\not=k\) and \(\DeltaOther\not=\CPatch{\emptyset}{\emptyset}\)}\\
\CActor{\ell}{\CState{\phantom{\DeltaOther}\VECOF e}B{\cdot}} &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_22">\begin{align*}
\textrm{where } &amp; \Rnew=\Rold\oplus(k,\CPatch{\ROUTESADD}{\ROUTESDEL})\\
&amp; \ROUTESstar=\{c\;|\;(j,c)\in\Rold\}\\
&amp; \ROUTESbullet=\{c\;|\;(j,c)\in\Rold,j\not=k\}\\
&amp; \ROUTESADDbullet=\ROUTESADD-\ROUTESbullet\\
&amp; \ROUTESDELbullet=\ROUTESDEL-\ROUTESbullet\\
&amp; \DeltaOther=\CPatch{\{c\;|\;c\in\ROUTESADDbullet,(\ell,\Obs c)\in\Rold\}}{\{c\;|\;c\in\ROUTESDELbullet,(\ell,\Obs c)\in\Rold\}}\\
&amp; \DeltaFb=\CPatch{\{c\;|\;c\in\ROUTESADDbullet,(\ell,\Obs c)\in\Rnew\}\cup\{c\;|\;c\in(\ROUTESstar\cup\ROUTESADDbullet-\ROUTESDELbullet),\Obs c\in\rlap{\ROUTESADD}\phantom{\ROUTESDEL}\}}{\{c\;|\;c\in\ROUTESDELbullet,(\ell,\Obs c)\in\Rold\}\cup\{c\;|\;c\in\rlap{\ROUTESstar}\phantom{(\ROUTESstar\cup\ROUTESADDbullet-\ROUTESDELbullet)},\Obs c\in\ROUTESDEL\}}
\end{align*}
</div>The patch <span class="lyx-mathjax mathjax-inline">$\Delta_{\mathit{fb}}$</span> that <span class="lyx-mathjax mathjax-inline">$\FBCDName$</span> constructs as feedback when <span class="lyx-mathjax mathjax-inline">$\ell=k$</span> differs from the patch <span class="lyx-mathjax mathjax-inline">$\Delta_{\mathit{other}}$</span> delivered to <span class="lyx-mathjax mathjax-inline">$k$</span>'s peers. While assertions made by <span class="lyx-mathjax mathjax-inline">$k$</span>'s peers do not change during the reduction, <span class="lyx-mathjax mathjax-inline">$k$</span>'s assertions do. Not only must new assertions in <span class="lyx-mathjax mathjax-inline">$\ROUTESADD$</span> be considered as potentially worthy of inclusion, but new subscriptions in <span class="lyx-mathjax mathjax-inline">$\ROUTESADD$</span> must be given the opportunity to examine the entirety of the aggregate state. Similar considerations arise for <span class="lyx-mathjax mathjax-inline">$\ROUTESDEL$</span>.</p><span class="halmos"></span></div><p id="x_4_6_0_0_25">The final changes adjust the <span class="lyx-mathjax mathjax-inline">$\RQuit$</span> and <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> rules to produce patches instead of assertion set state change notifications in case of process termination and startup.</p>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_28">
<p id="x_4_6_0_0_27"><span class="counter numbered definition"><span>4.48</span></span><span class="lyx-argument">Incremental <span class="lyx-mathjax mathjax-inline">$\RQuit$</span> rule<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:quit-incr"></a><a name="def:rule:quit-incr"></a>The <span class="lyx-mathjax mathjax-inline">$\RQuit$</span> rule becomes
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_26">\[
\CState{\VECOF ee_{0}}{\CBehPack{\tau}{\CBehF}u}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CBehPack{\T1}{\FNOOP}{()}}{\CPatch{\emptyset}{\TVal}\VECOF a'\VECOF a}
\]
</div>when <span class="lyx-mathjax mathjax-inline">$\CBehF(e_{0},u)=\EXIT{\VECOF a'}$</span>. The sole change from definition <a class="cross-reference" href="#def:rule:quit">4.6</a> is use of <span class="lyx-mathjax mathjax-inline">$\CPatch{\emptyset}{\TVal}$</span> in place of <span class="lyx-mathjax mathjax-inline">$\emptyset$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_4_6_0_0_31">
<p id="x_4_6_0_0_30"><span class="counter numbered definition"><span>4.49</span></span><span class="lyx-argument">Incremental <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> rule<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:spawn-incr"></a><a name="def:rule:spawn-incr"></a>The <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> rule becomes
<div class="lyx-mathjax mathjax-display" id="x_4_6_0_0_29">\[
\CState{\VECOF e}{\CCfg{\VECOF q(k,P)}R{\VECOF{A_{Q}}}}{\VECOF a}\longrightarrow\CState{\VECOF e}{\CCfg{\VECOF q\CQAct{\ell}{\CPatch{\ROUTES}{\emptyset}}}R{\VECOF{A_{Q}}(\CActor{\ell}{\Sigma})}}{\VECOF a}
\]
</div>where <span class="lyx-mathjax mathjax-inline">$\ell$</span> is chosen as in definition <a class="cross-reference" href="#def:rule:spawn">4.15</a> and where <span class="lyx-mathjax mathjax-inline">$(\Sigma,\ROUTES)=\FBOOT\ P$</span>. The only change from definition <a class="cross-reference" href="#def:rule:spawn">4.15</a> is use of <span class="lyx-mathjax mathjax-inline">$\CPatch{\ROUTES}{\emptyset}$</span> in place of <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>.</p><span class="halmos"></span></div>
<h6 class="unnumbered" id="x_4_6_0_0_32"><a name="toc_4.6"></a><span class="heading-text paragraph">Equivalence between monolithic and incremental models.</span></h6><p id="x_4_6_0_0_33">Programs using the incremental protocol and semantics are not directly comparable to those using the monolithic semantics. Each variation uses a unique language for communication between dataspaces and actors. However, any two assertion sets <span class="lyx-mathjax mathjax-inline">$\ROUTES_{1}$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTES_{2}$</span> can be equivalently represented by <span class="lyx-mathjax mathjax-inline">$\ROUTES_{1}$</span> and a patch <span class="lyx-mathjax mathjax-inline">$\CPatch{\ROUTES_{2}-\ROUTES_{1}}{\ROUTES_{1}-\ROUTES_{2}}$</span>, because <span class="lyx-mathjax mathjax-inline">$\ROUTES_{2}=\ROUTES_{1}\cup(\ROUTES_{2}-\ROUTES_{1})-(\ROUTES_{1}-\ROUTES_{2})$</span> and <span class="lyx-mathjax mathjax-inline">$(\ROUTES_{2}-\ROUTES_{1})\cap(\ROUTES_{1}-\ROUTES_{2})=\emptyset$</span>.</p>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_34">\(\newcommand{\XSPAWN}[1]{\llbracket #1\rrbracket }
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_35">\(\newcommand{\XSPAWNMM}[1]{\llparenthesis#1\rrparenthesis}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_36">\(\newcommand{\XSPAWNMI}[1]{\XSPAWN{#1}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_37">\(\newcommand{\MONOOF}[1]{#1_{\mathtt{M}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_38">\(\newcommand{\INCROF}[1]{#1_{\mathtt{I}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_39">\(\newcommand{\WRAPM}{\MONOOF{\mathsf{wrap}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_4_6_0_0_40">\(\newcommand{\WRAPI}{\INCROF{\mathsf{wrap}}}
\)</div><p id="x_4_6_0_0_41"> </p>
<div class="footnote" id="fn_4_45"><span class="counter footnote-counter"><span>45</span></span>The symmetry of translation between patches and assertion sets also makes it possible to embed incremental-protocol actors in a monolithic-protocol environment.<span class="plain-layout-boundary"></span></div><p id="x_4_6_0_0_42">This idea suggests a technique for embedding an actor communicating via the monolithic protocol into a dataspace that uses the incremental protocol.<label class="footnote-number" for="fn_4_45">45</label> Specifically, the actor <em>integrates</em> the series of incoming patches to obtain knowledge about the state of the world, and <em>differentiates</em> its outgoing assertion sets with respect to previous assertion sets.</p><p id="x_4_6_0_0_43">Every monolithic leaf actor can be translated into an equivalent incremental actor by composing its behavior function with a wrapper that performs this on-the-fly integration and differentiation. The reduction rules ensure that, if every monolithic leaf actor in a program is translated into an incremental actor in this way, each underlying monolithic-protocol behavior function receives events and emits actions <em>identical</em> to those seen in the run of the unmodified program using the monolithic semantics.</p>
<div class="theorem-like numbered definition" id="x_4_6_0_0_46">
<p id="x_4_6_0_0_44"><span class="counter numbered definition"><span>4.50</span></span>We write <span class="lyx-mathjax mathjax-inline">$\XSPAWNMI{\MONOOF P}$</span> to denote the translation of a monolithic-protocol program into the incremental-protocol language using this wrapping technique, and use <span class="lyx-mathjax mathjax-inline">$\mathtt{M}$</span> and <span class="lyx-mathjax mathjax-inline">$\mathtt{I}$</span> subscripts for monolithic and incremental constructs generally.</p>
<p id="x_4_6_0_0_45">The translation maintains additional state with each leaf actor in order to compute patches from assertion sets and vice versa and to expose information required for judging equivalence between the two kinds of machine state. Where a leaf actor has private state <span class="lyx-mathjax mathjax-inline">$u$</span> in an untranslated program, it has state <span class="lyx-mathjax mathjax-inline">$(u,\ROUTES_{i},\ROUTES_{o})$</span> in the translated program. The new registers <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span> are the actor's most recently delivered and produced assertion sets, respectively.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_4_6_0_0_49">
<p id="x_4_6_0_0_47"><span class="counter numbered definition"><span>4.51</span></span>We write <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma}\approx\INCROF{\Sigma}$</span> to denote equivalence between monolithic and incremental actor states. To see what this means, let us imagine hierarchical configurations as trees like the one in figure <a class="cross-reference" href="#fig:file-server-architecture">13</a>. Each actor and each dataspace becomes a node, and each edge represents the pair of queues connecting an actor to its container. For a monolithic-protocol configuration to be equivalent to an incremental-protocol configuration, it must have the same tree shape and equivalent leaf actors with identical private states. Furthermore, at each internal monolithic node (i.e., at each dataspace), the assertion store must be identical to that in the corresponding incremental node. Finally, events and actions queued along a given edge on the monolithic side must have the same <em>effects</em> as those queued on the corresponding incremental edge.</p>
<p id="x_4_6_0_0_48">The effects of monolithic and incremental action queues are the same when corresponding slots in the queues contain either identical message-send actions, spawn actions that result in equivalent actors, or state change notifications that have the same effect on the assertion store in the containing dataspace. Comparing event queues is similar, except that instead of requiring state change notifications to have identical effects on the shared dataspace, we require that they instead identically modify the <em>perspective</em> on the shared dataspace that the actor they are destined for has been accumulating.</p><span class="halmos"></span></div><p id="x_4_6_0_0_50">If the conditions for establishing <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma}\approx\INCROF{\Sigma}$</span> are satisfied, then reduction of <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma}$</span> proceeds in lockstep with reduction of the equivalent <span class="lyx-mathjax mathjax-inline">$\INCROF{\Sigma}$</span>, and equivalence is preserved at each step.</p>
<div class="theorem-like numbered theorem" id="x_4_6_0_0_55">
<p id="x_4_6_0_0_54"><span class="counter numbered theorem"><span>4.52</span></span><a class="label-anchor" href="#thm:equivalence"></a><a name="thm:equivalence"></a> For every monolithic program <span class="lyx-mathjax mathjax-inline">$\MONOOF P$</span>, let <span class="lyx-mathjax mathjax-inline">$(\MONOOF{\Sigma^{0}},\MONOOF{\pi^{0}})=\FBOOT(\MONOOF P)$</span> and <span class="lyx-mathjax mathjax-inline">$(\INCROF{\Sigma^{0}},\INCROF{\pi^{0}})=\FBOOT(\XSPAWNMI{\MONOOF P})$</span>. Then,
<ol id="x_4_6_0_0_53"><li id="x_4_6_0_0_51"><a class="label-anchor" href="#enu:initial-assertions-equal"></a><a name="enu:initial-assertions-equal"></a><span class="lyx-mathjax mathjax-inline">$\MONOOF{\pi^{0}}=\INCROF{\pi^{0}}$</span>.</li><li id="x_4_6_0_0_52"><a class="label-anchor" href="#enu:reduction-in-lockstep"></a><a name="enu:reduction-in-lockstep"></a>If there exists <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma}$</span> such that <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma^{0}}\MONOOF{\longrightarrow^{n}}\MONOOF{\Sigma}$</span> for some <span class="lyx-mathjax mathjax-inline">$n\in\mathbb{N}$</span>, then there exists a unique <span class="lyx-mathjax mathjax-inline">$\INCROF{\Sigma}$</span> such that <span class="lyx-mathjax mathjax-inline">$\INCROF{\Sigma^{0}}\INCROF{\longrightarrow^{n}}\INCROF{\Sigma}$</span> and <span class="lyx-mathjax mathjax-inline">$\MONOOF{\Sigma}\approx\INCROF{\Sigma}$</span>.</li></ol></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof named" id="x_4_6_0_0_57">
<p id="x_4_6_0_0_56"><span class="counter unnumbered proof"><span>4.52</span></span><span class="lyx-argument">Proof (Sketch)<span class="plain-layout-boundary"></span></span> Conclusion <a class="cross-reference" href="#enu:initial-assertions-equal">1</a> follows trivially from the definition of <span class="lyx-mathjax mathjax-inline">$\FBOOT$</span> and the fact that the translation process does not alter an actor's initial assertion set. The bulk of the proof is devoted to establishing conclusion <a class="cross-reference" href="#enu:reduction-in-lockstep">2</a>. We first define <span class="lyx-mathjax mathjax-inline">$\XSPAWNMM{\MONOOF P}$</span> to mean augmentation of the monolithic program with the same additional registers as provided by <span class="lyx-mathjax mathjax-inline">$\XSPAWNMI{\MONOOF P}$</span>. Second, we define an equivalence <span class="lyx-mathjax mathjax-inline">$\approx_{\mathtt{MM}}$</span> between <span class="lyx-mathjax mathjax-inline">$\XSPAWNMM{\cdot}$</span>-translated and untranslated monolithic machine states that ignores the extra registers, and prove that reduction respects <span class="lyx-mathjax mathjax-inline">$\approx_{\mathtt{MM}}$</span>. Third, we prove that <span class="lyx-mathjax mathjax-inline">$\XSPAWNMM{\MONOOF P}$</span> and <span class="lyx-mathjax mathjax-inline">$\XSPAWNMI{\MONOOF P}$</span> reduce in lockstep, and that an equivalence <span class="lyx-mathjax mathjax-inline">$\approx_{\mathtt{MI}}$</span> between translated monolithic and incremental states is preserved by reduction. Finally, we prove that the two notions of equivalence <span class="lyx-mathjax mathjax-inline">$\approx_{\mathtt{MM}}$</span> and <span class="lyx-mathjax mathjax-inline">$\approx_{\mathtt{MI}}$</span> together imply the desired equivalence <span class="lyx-mathjax mathjax-inline">$\approx$</span>. The full proof takes the form of a Coq script.</p><span class="halmos"></span></div>
<h4 id="x_4_7_0_0_1"><a name="toc_4.7"></a><span class="counter section"><span>4.7</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:incremental-examples"></a><a name="sec:incremental-examples"></a>Programming with the incremental protocol</span></h4><p id="x_4_7_0_0_2">The incremental protocol occasionally simplifies programs for leaf actors. This applies not only to examples in Dataspace ISWIM, but also to large programs written for the Racket or JavaScript dataspace model implementations. Occasional simplification is not the only advantage of incrementality: the incremental protocol often improves the efficiency of programs. Theorem <a class="cross-reference" href="#thm:equivalence">4.52</a> allows programmers to choose on an actor-by-actor basis which protocol is most appropriate for a given task.</p><p id="x_4_7_0_0_4">For example, the demand-matcher example (numbered <a class="cross-reference" href="#example:demand-matcher">4.3</a> above) can be implemented in a <em>locally-stateless</em> manner using patch-based state change notifications. It is no longer forced to maintain a record of the most recent set of active conversations, and thus no set subtraction is required. Instead, it can rely upon the added and removed sets in patch events it receives from its dataspace. The revised <span class="lyx-mathjax mathjax-inline">$\mathit{demandMatcher}$</span> behavior function takes <span class="lyx-mathjax mathjax-inline">$()$</span> as its actor-private state value, since each event it receives conveys all the information it needs:
<div class="lyx-mathjax mathjax-display" id="x_4_7_0_0_3">\begin{align*}
\mathit{demandMatcher}\;(\CPatch{\ROUTESADD}{\ROUTESDEL},()) &amp; =\CONTINUE{\left[\mathit{mkWorker}\,x\,|\,(\mathtt{hello},x)\in\ROUTESADD\right],()}
\end{align*}
</div></p><p id="x_4_7_0_0_5">More generally, theorem <a class="cross-reference" href="#thm:concision">4.53</a> can free actors written using the incremental protocol from maintaining sets of assertions they have “seen before”; they may rely on the dataspace to unambiguously signal (dis)appearance of assertions.</p>
<div class="theorem-like numbered theorem named" id="x_4_7_0_0_7">
<p id="x_4_7_0_0_6"><span class="counter numbered theorem"><span>4.53</span></span><span class="lyx-argument">Concision<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#thm:concision"></a><a name="thm:concision"></a> For all pairs of events <span class="lyx-mathjax mathjax-inline">$e=\CPatch{\ROUTES_{1}}{\ROUTES_{2}}$</span> and <span class="lyx-mathjax mathjax-inline">$e'=\CPatch{\ROUTES_{3}}{\ROUTES_{4}}$</span> delivered to an actor, <span class="lyx-mathjax mathjax-inline">$c\in\ROUTES_{1}\cap\ROUTES_{3}$</span> only if some event <span class="lyx-mathjax mathjax-inline">$\CPatch{\ROUTES_{5}}{\ROUTES_{6}}$</span> was delivered between <span class="lyx-mathjax mathjax-inline">$e$</span> and <span class="lyx-mathjax mathjax-inline">$e'$</span>, where <span class="lyx-mathjax mathjax-inline">$c\in\ROUTES_{6}$</span>. Symmetrically, <span class="lyx-mathjax mathjax-inline">$c$</span> cannot be retracted twice without being asserted in the interim.</p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof named" id="x_4_7_0_0_9">
<p id="x_4_7_0_0_8"><span class="counter unnumbered proof"><span>4.53</span></span><span class="lyx-argument">Proof (Sketch)<span class="plain-layout-boundary"></span></span> The <span class="lyx-mathjax mathjax-inline">$\textsf{patch}$</span> rule prunes patch actions against <span class="lyx-mathjax mathjax-inline">$R$</span> to ensure that only real changes are passed on in events. <span class="lyx-mathjax mathjax-inline">$R$</span> itself is then updated to incorporate the patch so that subsequent patches can be accurately pruned in turn.</p><span class="halmos"></span></div>
<h4 id="x_4_8_0_0_1"><a name="toc_4.8"></a><span class="counter section"><span>4.8</span></span><span class="heading-text section"><a class="label-anchor" href="#subsec:Styles-of-interaction"></a><a name="subsec:Styles-of-interaction"></a>Styles of interaction</span></h4>
<figure id="x_4_8_0_0_10"><a name="fig:Styles-of-interaction"></a>
<p class="align-center" id="x_4_8_0_0_9">
<div class="tabular" id="x_4_8_0_0_8"><table class="tabular"><tr><td class="alignment-center valignment-top width-0pt alignment-center valignment-top usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none">
<div class="frameless-box" id="x_4_8_0_0_3">
<p class="align-center" id="x_4_8_0_0_2">Short-lived observables<br/>(i.e. messages)</p><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none">
<div class="frameless-box" id="x_4_8_0_0_5">
<p class="align-center" id="x_4_8_0_0_4">Long-lived observables<br/>(i.e. assertions)</p><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true leftline-true usebox-none">Short-lived interest<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none">—<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true rightline-true usebox-none">Query-like behavior<span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none">Long-lived interest<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none">Publish-subscribe<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none">
<div class="frameless-box" id="x_4_8_0_0_7">
<p class="align-center" id="x_4_8_0_0_6">State replication,<br/>streaming queries</p><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></td></tr></table></div></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>16</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Styles-of-interaction"></a>Behavior resulting from variation of subscription lifetime and fact lifetime<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_4_8_0_0_11">The dataspace model offers a selection of different styles of interaction. In order for communication to occur at all, some actors must assert items of knowledge <span class="lyx-mathjax mathjax-inline">$c$</span>, and others must simultaneously assert interest in such knowledge, <span class="lyx-mathjax mathjax-inline">$\Obs c$</span>. (Here, we may treat message-sending <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span> as fleeting assertions of <span class="lyx-mathjax mathjax-inline">$c$</span>, as discussed in section <a class="cross-reference" href="#sec:Messages-versus-Assertions">4.4</a>.) Varying the <em>lifetimes</em> of assertions placed in the dataspace gives rise to patterns of information exchange reminiscent of publish/subscribe messaging, state replication, streaming queries, and instantaneous queries.</p><p id="x_4_8_0_0_12">Figure <a class="cross-reference" href="#fig:Styles-of-interaction">16</a> summarizes the situation. There are four regions of interest shown. Only three yield interesting patterns of interaction: if both assertions of interest and assertions of knowledge are very short-lived, no communication can occur. There is no moment when the two kinds of assertion exist simultaneously.</p><p id="x_4_8_0_0_13">When assertions of interest tend to be long-lived and assertions of the items of interest themselves tend to be brief in duration, a <em>publish/subscribe</em> pattern of interaction results. The assertions of interest can be thought of as <em>subscriptions</em> in this case. Publish/subscribe communication is naturally multi-party; however, point-to-point, channel-like messaging is readily available via a convention for assignment and use of channel names.</p><p id="x_4_8_0_0_14">As the lifetimes of assertions representing knowledge increase, the pattern of interaction takes on a different character. It begins to resemble a <em>streaming query</em> style of knowledge transfer, where long-lived queries over a changing set of rows yield incrementally-maintained result sets. The resemblance is particularly strong when cast in terms of the incremental patch actions <span class="lyx-mathjax mathjax-inline">$\Delta$</span> introduced in section <a class="cross-reference" href="#sec:incremental-DS">4.6</a>. Seen from a different perspective, this pattern of interaction appears similar to <em>state replication</em>, where spatially-distinct replicas of a set of information are maintained by exchange of messages. The monolithic state change notifications <span class="lyx-mathjax mathjax-inline">$\pi$</span> first introduced in section <a class="cross-reference" href="#sec:Informal-DS-semantics">4.1</a> most clearly capture the intuition backing this perspective.</p>
<div class="footnote" id="fn_4_46"><span class="counter footnote-counter"><span>46</span></span>Abstractly, of course, time is measured in number of reduction steps rather than any real-world measure.<span class="plain-layout-boundary"></span></div><p id="x_4_8_0_0_15">Finally, if we consider long-lived assertions of knowledge in combination with briefer and briefer assertions of interest in this knowledge, the style of interaction approaches that of clients making <tt>SELECT</tt> queries against a shared SQL database. Here, the assertions of interest can usefully be thought of as <em>queries</em>. An important consideration in this style of interaction is the length of time that each query is maintained.<label class="footnote-number" for="fn_4_46">46</label></p><p id="x_4_8_0_0_16">There is no general answer to the question of how long an assertion of interest should be maintained in order to effectively act as a query over matching assertions. It varies from protocol to protocol. In some protocols, it is certain that the assertions of interest will be present at the moment the query is established, in which case an immediate retraction of interest is sound. In other protocols, queries must be held in place for some time to allow them to be detected and responded to. The specific duration depends on the mechanism by which such responses are to be produced: a local actor may be able to compute a result in one round-trip of control transfer, on demand; an actor communicating with a remote system over a network link may require queries to be held for a certain number of seconds.</p><p id="x_4_8_0_0_17">An actor maintaining an assertion of interest for any non-trivial length of time at all runs the risk of the result set changing during the lifetime of the query. The longer the query is maintained, the more the style of interaction begins to resemble a streaming query and the less it has in common with SQL-style point-in-time queries of a snapshot of system state.</p></p>
<div class="lyx-mathjax mathjax-definitions" id="x_5_3_0_0_25">\(\newcommand{\PrPlus}{(\CUpdate{\mathit{rooms}}{\mathit{rooms}\cup\{r\}})}
\newcommand{\PrMinus}{(\CUpdate{\mathit{rooms}}{\mathit{rooms}-\{r\}})}
\newcommand{\DPlus}{\DAsserted{(\star,\mathtt{in},\CVar r)}}
\newcommand{\DMinus}{\DRetracted{(\star,\mathtt{in},\CVar r)}}
\)</div><p id="x_5_8_0_0_5">
<h3 id="x_5_0_0_0_1"><a name="toc_5"></a><span class="counter chapter"><span>5</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE"></a><a name="CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE"></a>Computational Model II: <span class="small-caps">Syndicate</span></span></h3><p id="x_5_0_0_0_2">With the dataspace model, we have a flexible facility for communicating changes in conversational state among a group of actors. We are able to express styles of interaction ranging from unicast, multicast and broadcast messaging through streaming queries and state replication to shared-database-like protocols. The model's emphasis on structured exchange of public aspects of component state allows us to express a wide range of effects including service presence, fate sharing, and demand matching. These effects in turn serve as mechanisms by which a range of resource-allocation, -management, and -release policies may be expressed.</p>
<div class="footnote" id="fn_5_47"><span class="counter footnote-counter"><span>47</span></span>The idea of such a new language is nonetheless interesting, worthy of future exploration.<span class="plain-layout-boundary"></span></div><p id="x_5_0_0_0_3">The dataspace model brings actors together into a conversational group, but says nothing about the internal structure of each leaf actor. Such actors are not only stateful, but <em>internally</em> concurrent. Each leaf actor is frequently engaged in more than one simultaneous conversation. Ordinary programming languages offer no assistance to the programmer for managing intra-actor control and state, even when (like Dataspace ISWIM) extended with dataspace-model-specific data types and functions. However, to simply discard such languages would be a mistake: practicality demands interoperability. If we design a new language specifically for leaf actor programming, we forfeit the benefits of the enormous quantity of useful software written in already-existing languages.<label class="footnote-number" for="fn_5_47">47</label> Instead, we seek tools for integrating the dataspace model not only with existing programs and libraries but with existing ways of thinking.</p>
<div class="footnote" id="fn_5_48"><span class="counter footnote-counter"><span>48</span></span>Actor languages face some of the same issues, especially as they relate to (de)multiplexing of conversations. Erlang, for example, is like the unadorned dataspace model in funneling all communication for an actor through a single behavior function. The E strategy of allocating a new object (what E terms a facet) to handle a given sub-conversation is an interesting approach that takes advantage of E's ability to offer peers different perspectives on shared state in a single vat. E facets thus overlap in intent with <span class="small-caps">Syndicate</span> facets at least in part.<span class="plain-layout-boundary"></span></div><p id="x_5_0_0_0_4">We will need new <em>control</em> structures reflecting the conversation-related concepts the dataspace model introduces. Programmers are asked to think in terms of asynchronous (nested sub-)conversations, but given ordinary sequential control flow. They are asked to maintain connections between actor-private state and published assertions in a shared space, but given ordinary variables and heaps. They are asked to respond to conversational implicatures expressing peers' needs, but offered no support for turning such demands into manageable units of programming. Conversely, they are asked to respond to signals indicating abandonment of a conversation by releasing local related resources, but given no means of precisely delimiting such resources. Finally, when a local control decision is made to end an interaction, programmers are left to manually ensure that this is communicated to affected peers.<label class="footnote-number" for="fn_5_48">48</label></p><p id="x_5_0_0_0_5">The second part of the <span class="small-caps">Syndicate</span> design therefore builds on the dataspace model by proposing new language features to address these challenges. The new features are intended for incorporation into base languages used to express leaf actor behaviors. The central novelty is an explicit representation of a (sub-)conversation named a <em>facet</em>. Facets nest, forming a tree that mirrors the nested conversational structure of the actor's interactions. Each actor's private state is held in <em>fields</em>; each field is associated with a particular facet. Special declarations called <em>endpoints</em> allow the programmer to connect assertions in the dataspace with values held in local fields in a bidirectional manner. Endpoints describing <em>interest</em> in assertions—that is, endpoints that publish assertions of the form <span class="lyx-mathjax mathjax-inline">$\Obs c$</span> into the dataspace—offer a convenient syntactic location for the specification of responses to the appearance and disappearance of matching assertions.</p><p id="x_5_0_0_0_6">Facets, fields, and endpoints together allow the programmer to write programs in terms of conversations, conversational state, and conversational interactions. They connect local to shared state. They offer a unit of resource management that can come and go with changes in expressed demand. Finally, because the connection between a facet and the surrounding dataspace is bidirectional, adding or removing a facet automatically adds or removes its endpoints' assertions, allowing peers to detect and respond to the change. In the extreme case of an actor crash, all its facets are removed, automatically (if abruptly) ending all of its conversations.</p>
<h6 class="unnumbered" id="x_5_0_0_0_7"><a name="toc_5"></a><span class="heading-text paragraph"><span class="small-caps">Syndicate/λ</span>.</span></h6><p id="x_5_0_0_0_8">Chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> used an informal quasi-language, Dataspace ISWIM, to illustrate the formal system underpinning the dataspace model. Here, we take a slightly different tack, illustrating new language features by presenting them as part of an otherwise-minimal, mathematical, <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus-inspired base language with just enough structure to act as a backdrop. We call this language <span class="small-caps">Syndicate/λ</span>, by analogy with the full prototype implementations <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span>. In our formal presentation, we abstract away from concrete details of base value types and specific built-in operations; where needed for examples, we reuse the notation and concepts sketched for Dataspace ISWIM.</p>
<h4 id="x_5_1_0_0_1"><a name="toc_5.1"></a><span class="counter section"><span>5.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Informal-PLLAMBDA-semantics"></a><a name="sec:Informal-PLLAMBDA-semantics"></a>Abstract <span class="small-caps">Syndicate/λ</span> syntax and informal semantics</span></h4>
<figure class="fullwidth" id="x_5_1_0_0_4"><a name="fig:PLLAMBDA-program-syntax"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_1_0_0_2">\begin{align*}
\textrm{Programs }\CPr\in\TPr &amp; :=\CInert &amp; &amp; \textrm{inert}\\
&amp; \EQPAR\CSeq{\CPr}{\CPr} &amp; &amp; \textrm{composition}\\
&amp; \EQPAR\CCall ee &amp; &amp; \textrm{procedure call}\\
&amp; \EQPAR\CBind xe{\CPr} &amp; &amp; \textrm{bind immutable variable}\\
&amp; \EQPAR\CField xe{\CPr} &amp; &amp; \textrm{allocate mutable field}\\
&amp; \EQPAR\CUpdate xe &amp; &amp; \textrm{update mutable field}\\
&amp; \EQPAR\CSend e &amp; &amp; \textrm{send message via dataspace}\\
&amp; \EQPAR\CSpawn{\CPr} &amp; &amp; \textrm{spawn actor}\\
&amp; \EQPAR\CDS{\CPr} &amp; &amp; \textrm{spawn dataspace}\\
&amp; \EQPAR\CFacet x{A\CEndpoint D{\CPr}\;\dots} &amp; &amp; \textrm{start facet}\\
&amp; \EQPAR\CStop x{\CPr} &amp; &amp; \textrm{stop facet}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_5_1_0_0_3">\begin{align*}
\textrm{Expressions }e\in\TExpr &amp; :=b\;|\;(e,\dots)\;|\;p\;e\;\dots\;|\;x\;|\;\CProc{\CClause P{\CPr}\;\dots}\\
\textrm{Local values }v\in\THVal &amp; :=b\;|\;(v,\dots)\;|\;\phantom{p\;e\;\dots\;|\;x\;|\;}\CProc{\CClause P{\CPr}\;\dots}\\
\textrm{Assertions }c\in\TVal &amp; :=b\;|\;(c,\dots)\\
\textrm{Assertion sets }\ROUTES\in\TASet &amp; =\SETOF{\TVal}\\
\textrm{Names }x\in\TVar &amp; \;\textrm{(used to denote variables, fields, facets)}\\
\\
\textrm{Event patterns }D\in\TEPat &amp; :=\DAsserted P\\
&amp; \EQPAR\DRetracted P\\
&amp; \EQPAR\DMessage P\\
&amp; \EQPAR\DStart\\
&amp; \EQPAR\DStop\\
\\
\textrm{Dataspace events }\CEvt\in\TEvt &amp; :=\AMsg c\;|\;\Delta\\
\textrm{Local events }\CHEvt\in\THEvt &amp; :=\AMsg c\;|\;\Delta\;|\;\DStart\:|\;\DStop\\
\textrm{Dataspace actions }a\in\TAct &amp; :=\AMsg c\;|\;\Delta\;|\;\AActor g{\pi}\\
\\
\textrm{Patterns }P\in\TPat &amp; :=\star\;|\;b\;|\;(P,\dots)\;|\;p\;e\;\dots\;|\;x\;|\;\CVar x\\
\textrm{Assertion templates }k\in\TTemplate &amp; :=\star\;|\;b\;|\;(k,\dots)\;|\;p\;e\;\dots\;|\;x\\
\textrm{Pattern values }\CPVal\in\TPVal &amp; :=\star\;|\;b\;|\;(k,\dots)\;|\;\phantom{p\;e\;\dots\;|\;x\;|\;}\CVar x\\
\textrm{Assertion endpoints }A\in\TTemplates &amp; :=\emptyset\;|\;k\cup A\\
\textrm{Base values }b\in\TBVal &amp; =\textrm{Atoms, incl. strings, symbols, numbers, etc.}\\
\textrm{Primitive functions }p\in\TPrim
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>17</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLLAMBDA-program-syntax"></a>Syntax of <span class="small-caps">Syndicate/λ</span> programs<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_5_1_0_0_5">Figure <a class="cross-reference" href="#fig:PLLAMBDA-program-syntax">17</a> displays the syntax of <span class="small-caps">Syndicate/λ</span>. It is stratified into expressions <span class="lyx-mathjax mathjax-inline">$e\in\TExpr$</span> and reactive, imperative <em>programs </em><span class="lyx-mathjax mathjax-inline">$\CPr\in\TPr$</span>. Expressions are both terminating and pure up to exceptions caused by partial primitive functions. Programs describe the interesting features of the language. While expressions yield values, programs are evaluated solely for their side effects.</p><p id="x_5_1_0_0_6">The empty or inert program is written <span class="lyx-mathjax mathjax-inline">$\CInert$</span>. A semicolon is used to denote a form of sequential composition, <span class="lyx-mathjax mathjax-inline">$\CSeq{\CPr_{1}}{\CPr_{2}}$</span>. The inert program <span class="lyx-mathjax mathjax-inline">$\CInert$</span> is both a left and a right identity for this form of composition. In this chapter, we identify terms up to arbitrary composition with <span class="lyx-mathjax mathjax-inline">$\CInert$</span>. This avoids spurious nondeterminism in reduction.</p><p id="x_5_1_0_0_7">The usual <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus syntax for application, <span class="lyx-mathjax mathjax-inline">$\CCall{e_{1}}{e_{2}}$</span>, is only available to programs, because the language includes only <em>procedure</em> values <span class="lyx-mathjax mathjax-inline">$\CProc{\CClause P{\CPr}\;\dots}$</span> instead of the function values familiar from <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus. Each <span class="lyx-mathjax mathjax-inline">$\CClause P{\CPr}$</span> in a procedure value is a branch of a pattern-match construct. When the procedure is called, the supplied argument is tested against each <span class="lyx-mathjax mathjax-inline">$P$</span> in left-to-right order, and the entire call reduces to the corresponding <span class="lyx-mathjax mathjax-inline">$\CPr$</span>, substituted appropriately.</p>
<div class="footnote" id="fn_5_49"><span class="counter footnote-counter"><span>49</span></span>The “well-formedness” judgment of section <a class="cross-reference" href="#sec:Well-formedness-and-errors">5.5</a> enforces this requirement, among others.<span class="plain-layout-boundary"></span></div><p id="x_5_1_0_0_8">It is not only <span class="small-caps">Syndicate/λ</span> syntax that is stratified. <span class="small-caps">Syndicate/λ</span> bindings come in three flavors: immutable variables (“variables”), mutable fields (“fields”), and names for facets (“facet names”). The first two are introduced by the two forms of <span class="lyx-mathjax mathjax-inline">$\KLet$</span>, and the third is introduced as an automatic consequence of creating a facet. Variables may include values containing procedures, but fields must not. While not strictly required, this restriction captures some of the spirit of programming in <span class="small-caps">Syndicate</span>; recall from section <a class="cross-reference" href="#sec:Syndicate-design-principles">2.6</a> the desire to eschew sharing of higher-order data. Field update, <span class="lyx-mathjax mathjax-inline">$\CUpdate xe$</span>, naturally applies only to fields, not variables,<label class="footnote-number" for="fn_5_49">49</label> and the value to be stored in the field must not directly or indirectly contain a procedure value.</p><p id="x_5_1_0_0_9">The command <span class="lyx-mathjax mathjax-inline">$\CSend e$</span> emits a dataspace model action of the form <span class="lyx-mathjax mathjax-inline">$\AMsg c$</span>, where <span class="lyx-mathjax mathjax-inline">$c$</span> is the result of evaluating <span class="lyx-mathjax mathjax-inline">$e$</span>. Similarly, the command <span class="lyx-mathjax mathjax-inline">$\CSpawn{\CPr}$</span> spawns a sibling actor in the dataspace, and <span class="lyx-mathjax mathjax-inline">$\CDS{\CPr}$</span> spawns a sibling <em>dataspace</em> initially containing a lone actor with behavior <span class="lyx-mathjax mathjax-inline">$\CPr$</span>. Spawned programs <span class="lyx-mathjax mathjax-inline">$\CPr$</span> may refer to arbitrary variables and fields of their spawning actor; at the moment of the spawn, the store is effectively duplicated, meaning that mutations to fields subsequently performed affect only the actor performing them.</p><p id="x_5_1_0_0_10">The final two syntactic forms create and destroy facets. The form <span class="lyx-mathjax mathjax-inline">$\CFacet x{A\CEndpoint D{\CPr}\ \dots}$</span> specifies a facet template which is instantiated at the moment the form is interpreted. Once instantiated, the new facet's endpoints—the assertion endpoint <span class="lyx-mathjax mathjax-inline">$A$</span> and the event-handling endpoints <span class="lyx-mathjax mathjax-inline">$(D\;\CPr)$</span>—become active and contribute assertions to the aggregate of assertions published by the actor as a whole.</p><p id="x_5_1_0_0_11">Each assertion endpoint <span class="lyx-mathjax mathjax-inline">$A$</span> is written using syntax chosen to connote set construction. The meaning of such an endpoint is exactly a set of assertions, the union of the sets denoted by the assertion templates <span class="lyx-mathjax mathjax-inline">$k$</span> embedded in the syntax of the assertion endpoint. Changing a field that is referred to by an assertion endpoint <em>automatically</em> changes the assertions published by that endpoint. In this way, <span class="small-caps">Syndicate/λ</span> programs are able to publish assertions that track changes in local state.</p>
<div class="footnote" id="fn_5_50"><span class="counter footnote-counter"><span>50</span></span>The <span class="lyx-mathjax mathjax-inline">$\DStart$</span> and <span class="lyx-mathjax mathjax-inline">$\DStop$</span> events are purely internal, having no connection to any dataspace-level events or actions. They are used for structuring the ordering of side-effects within a <span class="small-caps">Syndicate/λ</span> actor.<span class="plain-layout-boundary"></span></div><p id="x_5_1_0_0_12">Similarly, event-handling endpoints <span class="lyx-mathjax mathjax-inline">$(D\ \CPr)$</span> contribute assertions of interest derived from the event pattern <span class="lyx-mathjax mathjax-inline">$D$</span> into the dataspace, as well as specifying a subprogram <span class="lyx-mathjax mathjax-inline">$\CPr$</span> to run when any event relating to <span class="lyx-mathjax mathjax-inline">$D$</span> is delivered. Event patterns <span class="lyx-mathjax mathjax-inline">$D$</span> may select the appearance (<span class="lyx-mathjax mathjax-inline">$\DAsserted P$</span>) or disappearance (<span class="lyx-mathjax mathjax-inline">$\DRetracted P$</span>) of assertions matching some pattern, the arrival of a message (<span class="lyx-mathjax mathjax-inline">$\DMessage P$</span>) matching some pattern, or the <em>synthetic</em> events <span class="lyx-mathjax mathjax-inline">$\DStart$</span> and <span class="lyx-mathjax mathjax-inline">$\DStop$</span> which relate to facet lifecycle.<label class="footnote-number" for="fn_5_50">50</label> Patterns that contain binders <span class="lyx-mathjax mathjax-inline">$\CVar x$</span> capture portions of assertions in matching events, making <span class="lyx-mathjax mathjax-inline">$x$</span> available in subprograms <span class="lyx-mathjax mathjax-inline">$\CPr$</span>. As with assertion endpoints, every pattern <span class="lyx-mathjax mathjax-inline">$P$</span> automatically tracks changes in fields it refers to.</p><p id="x_5_1_0_0_13">The form <span class="lyx-mathjax mathjax-inline">$\CStop x{\CPr}$</span>, only legal when surrounded by a facet named <span class="lyx-mathjax mathjax-inline">$x$</span>, causes that facet—and all its nested subfacets—to terminate cleanly, executing any <span class="lyx-mathjax mathjax-inline">$\DStop$</span> event handlers they might have. Once a terminating facet becomes inert, after its <span class="lyx-mathjax mathjax-inline">$\DStop$</span> handlers have completed their tasks, its assertions are removed from the shared dataspace and the facet itself is then deleted. The program <span class="lyx-mathjax mathjax-inline">$\CPr$</span> in <span class="lyx-mathjax mathjax-inline">$\CStop x{\CPr}$</span> is then scheduled to execute <em>alongside</em> the terminating facet, so that any facets that <span class="lyx-mathjax mathjax-inline">$\CPr$</span> creates will exist in the actor's facet tree as <em>siblings</em> of the just-stopped facet <span class="lyx-mathjax mathjax-inline">$x$</span>.</p><p id="x_5_1_0_0_14">Despite being layered atop the dataspace model, the events and actions of that model are not directly exposed to the <span class="small-caps">Syndicate/λ</span> programmer the way that they are in Dataspace ISWIM. Instead of yielding values describing actions to perform in a functional style, programs perform side-effecting operations like <span class="lyx-mathjax mathjax-inline">$\KSend$</span> and <span class="lyx-mathjax mathjax-inline">$\KSpawn$</span>. Instead of functional state transduction, programs imperatively update fields. Instead of describing changes to published assertion sets, programs create facets with embedded endpoints. Finally, instead of manually directing control flow by analyzing and interpreting received events, programs declare event-handling endpoints, which are activated as appropriate.</p>
<div class="theorem-like numbered example" id="x_5_1_0_0_21">
<div class="footnote" id="fn_5_51"><span class="counter footnote-counter"><span>51</span></span>We have dispensed here with the <span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span> field of example <a class="cross-reference" href="#example:reference-cell">4.2</a>.<span class="plain-layout-boundary"></span></div>
<p id="x_5_1_0_0_16"><span class="counter numbered example"><span>5.1</span></span><a class="label-anchor" href="#example:hll:reference-cell"></a><a name="example:hll:reference-cell"></a>For our first example, let us revisit the shared mutable reference cell actors of example <a class="cross-reference" href="#example:reference-cell">4.2</a>. First, we spawn an actor implementing the cell itself:<label class="footnote-number" for="fn_5_51">51</label>
<div class="lyx-mathjax mathjax-display" id="x_5_1_0_0_15">\[
\CSpawn{(\CField v0{\CFacet{\mathit{box}}{\emptyset\cup(\mathtt{value},v)\CEndpoint{\DMessage{(\mathtt{set},\CVar{v'})}}{(\CUpdate v{v'})}}})}
\]
</div></p>
<p id="x_5_1_0_0_17">This actor first creates a new field <span class="lyx-mathjax mathjax-inline">$v$</span>, initialized to zero. It then creates a single facet named <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span>, which has an assertion endpoint that places the assertion <span class="lyx-mathjax mathjax-inline">$(\mathtt{value},v)$</span> into the shared dataspace. The semantics of <span class="small-caps">Syndicate/λ</span> automatically update this published assertion as the value of <span class="lyx-mathjax mathjax-inline">$v$</span> changes in response to subsequent events. The <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> facet also has a single event-handling endpoint. In response to an incoming <span class="lyx-mathjax mathjax-inline">$\mathtt{set}$</span> message, the endpoint updates the field <span class="lyx-mathjax mathjax-inline">$v$</span> to contain the new value <span class="lyx-mathjax mathjax-inline">$v'$</span> specified in the received message.</p>
<p id="x_5_1_0_0_19">The client actor from example <a class="cross-reference" href="#example:reference-cell">4.2</a> can be written as follows:
<div class="lyx-mathjax mathjax-display" id="x_5_1_0_0_18">\[
\CSpawn{\CFacet{\mathit{boxClient}}{\emptyset\CEndpoint{\DAsserted{(\mathtt{value},\CVar v)}}{(\CSend{(\mathtt{set},v+1)})}}}
\]
</div></p>
<p id="x_5_1_0_0_20">This actor is stateless, having no fields. It creates a single facet, <span class="lyx-mathjax mathjax-inline">$\mathit{boxClient}$</span>, which makes no assertions but contains a single event-handling endpoint which responds to patch events. If such a patch event describes the appearance of an assertion matching the pattern <span class="lyx-mathjax mathjax-inline">$(\mathtt{value},\CVar v)$</span>, the endpoint sends a message <span class="lyx-mathjax mathjax-inline">$\AMsg{(\mathtt{set},v+1)}$</span> via the dataspace. (We imagine here that <span class="lyx-mathjax mathjax-inline">$\TPrim$</span> includes functions for arithmetic and assume a convenient infix syntax.) Of course, the <span class="lyx-mathjax mathjax-inline">$\mathit{box}$</span> actor responds to such messages by updating its <span class="lyx-mathjax mathjax-inline">$\mathtt{value}$</span> assertion, which triggers <span class="lyx-mathjax mathjax-inline">$\mathit{boxClient}$</span> again. This cycle repeats <em>ad infinitum</em>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_5_1_0_0_26">
<p id="x_5_1_0_0_23"><span class="counter numbered example"><span>5.2</span></span><a class="label-anchor" href="#example:hll:demand-matcher"></a><a name="example:hll:demand-matcher"></a>Next, we translate the demand-matcher from example <a class="cross-reference" href="#example:demand-matcher">4.3</a> to <span class="small-caps">Syndicate/λ</span>:
<div class="lyx-mathjax mathjax-display" id="x_5_1_0_0_22">\begin{align*}
&amp; \CBind{\mathit{worker}}{\CProc{\CClause{\CVar x}{\CFacet w{\emptyset\CEndpoint{\DRetracted{(\mathtt{hello},x)}}{\left(\CStop w{\CInert}\right)}\CEndpoint{\DStart}{\dots}}}}}{}\\
&amp; \CSpawn{\CFacet{\mathit{demandMatcher}}{\emptyset\CEndpoint{\DAsserted{(\mathtt{hello},\CVar x)}}{\left(\CSpawn{(\CCall{\mathit{worker}}x)}\right)}}}
\end{align*}
</div></p>
<p id="x_5_1_0_0_24">The single event-handling endpoint in facet <span class="lyx-mathjax mathjax-inline">$\mathit{demandMatcher}$</span> responds to each asserted <span class="lyx-mathjax mathjax-inline">$\mathtt{hello}$</span> tuple by spawning a new actor, which begins its existence by calling the procedure <span class="lyx-mathjax mathjax-inline">$\mathit{worker}$</span>, passing it the <span class="lyx-mathjax mathjax-inline">$x$</span> from the assertion that led to its creation. In turn, <span class="lyx-mathjax mathjax-inline">$\mathit{worker}$</span> creates a facet <span class="lyx-mathjax mathjax-inline">$w$</span> which monitors <em>retraction</em> of <span class="lyx-mathjax mathjax-inline">$(\mathtt{hello},x)$</span> in addition to performing whichever startup actions a worker should perform. When the last peer to assert <span class="lyx-mathjax mathjax-inline">$(\mathtt{hello},x)$</span> retracts its assertion, the worker terminates itself by performing a <span class="lyx-mathjax mathjax-inline">$\DStop$</span> command on its top-level facet, supplying <span class="lyx-mathjax mathjax-inline">$\CInert$</span> to replace it.</p>
<p id="x_5_1_0_0_25">The concision of <span class="small-caps">Syndicate/λ</span> has allowed us to show how a worker terminates itself once demand for its existence disappears. The Dataspace ISWIM version of example <a class="cross-reference" href="#example:demand-matcher">4.3</a> omits this functionality: it is possible but verbose to express in Dataspace ISWIM.</p><span class="halmos"></span></div>
<h4 id="x_5_2_0_0_1"><a name="toc_5.2"></a><span class="counter section"><span>5.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Formal-PLLAMBDA-semantics"></a><a name="sec:Formal-PLLAMBDA-semantics"></a>Formal semantics of <span class="small-caps">Syndicate/λ</span></span></h4>
<figure class="fullwidth" id="x_5_2_0_0_6"><a name="fig:PLLAMBDA-evaluation-syntax"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_2">\begin{align*}
\textrm{Facet trees }\CS,T\in\TTree &amp; :=\CPr &amp; &amp; \textrm{unreduced code}\\
&amp; \EQPAR\CErr &amp; &amp; \text{exception}\\
&amp; \EQPAR\CSeq{\CS}{\CS} &amp; &amp; \textrm{composition}\\
&amp; \EQPAR\EFacet x{A\CEndpoint D{\CPr}\;\dots}S &amp; &amp; \textrm{running facet}\\
&amp; \EQPAR\EFacetStop x{A\;D\;\dots}S &amp; &amp; \textrm{stopping facet}\\
&amp; \EQPAR\EKill S &amp; &amp; \textrm{termination boundary}
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_3">\[
\textrm{Inert facet trees }\CSI,T_{I}\in\TTreeI:=\CInert\;|\;\CSeq{\CSI}{\CSI}\;|\;\EFacet x{A\CEndpoint D{\CPr}\;\dots}{\CSI}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_4">\begin{align*}
\textrm{Contexts }\CE,F\in\TE &amp; :=\hole\;|\;\CSeq{\CE}{\CS}\;|\;\CSeq{\CSI}{\CE\;|\;\EFacet x{A\CEndpoint D{\CPr}\ \dots}{\CE\;|\;\EFacetStop x{A\;D\;\dots}{\CE\;|\;\EKill{\CE}}}}
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_5">\begin{align*}
\textrm{Field stores }\CStore\in\TStore &amp; =\TVar\rightharpoonup\TVal\\
\textrm{Machine states }\CM\in\TM &amp; :=\Machine{\CStore}{\ROUTES}{\ROUTES}{\VECOF a}{\CS}\\
\textrm{Inert machine states }\CMI\in\TMI &amp; :=\Machine{\CStore}{\ROUTES}{\ROUTES}{\cdot}{\CSI}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>18</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLLAMBDA-evaluation-syntax"></a>Evaluation Syntax, Contexts and Machine States<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_5_2_0_0_7">Figure <a class="cross-reference" href="#fig:PLLAMBDA-evaluation-syntax">18</a> introduces syntax for describing evaluation states of <span class="lyx-mathjax mathjax-inline">$\TTree$</span>s of facets, as well as a specification of what it means for such a tree to be inert, a definition of evaluation contexts (<span class="lyx-mathjax mathjax-inline">$\TE$</span>), field <span class="lyx-mathjax mathjax-inline">$\TStore$</span>s, and reducible and inert machine states (<span class="lyx-mathjax mathjax-inline">$\TM$</span> and <span class="lyx-mathjax mathjax-inline">$\TMI$</span>).</p><p id="x_5_2_0_0_8">A tree of facets may include unreduced commands drawn from <span class="lyx-mathjax mathjax-inline">$\TPr$</span>. Reduction interprets these commands, applying any side effects they entail to the machine state. A tree may also include an exception marker, <span class="lyx-mathjax mathjax-inline">$\CErr$</span>, which arises as a result of various run-time error conditions and leads to abrupt actor termination. The composition operator on facet trees loses much of the flavor of sequentiality that it enjoys in programs, and acts instead primarily to separate (and order) adjacent sibling facets in the tree. However, evaluation contexts prefer redexes in the left-hand side of a composition to those in the right-hand side, thus preserving the intuitive ordering of effects.</p><p id="x_5_2_0_0_9">The form <span class="lyx-mathjax mathjax-inline">$\EFacet x{A\CEndpoint D{\CPr}\;\dots}S$</span> describes an instantiated, running facet, with active endpoints. It serves as an interior node in a facet tree. Any facets contained in <span class="lyx-mathjax mathjax-inline">$S$</span> are considered nested children of <span class="lyx-mathjax mathjax-inline">$x$</span>. If <span class="lyx-mathjax mathjax-inline">$x$</span> is later stopped, all facets in <span class="lyx-mathjax mathjax-inline">$S$</span> are stopped as well.</p>
<div class="footnote" id="fn_5_52"><span class="counter footnote-counter"><span>52</span></span>Note, however, that <span class="lyx-mathjax mathjax-inline">$\CStop x{\CPr}$</span> explicitly hoists <span class="lyx-mathjax mathjax-inline">$\CPr$</span> out of any termination boundary associated with facet <span class="lyx-mathjax mathjax-inline">$x$</span>.<span class="plain-layout-boundary"></span></div><p id="x_5_2_0_0_10">The final two syntactic forms describing facet trees relate to shutdown of facets. First, <span class="lyx-mathjax mathjax-inline">$\EFacetStop x{A\;D\;\dots}S$</span> describes a facet that is marked as <em>terminating</em>. The facet cannot be deleted until <span class="lyx-mathjax mathjax-inline">$S$</span> has reached inertness, but it will no longer react to incoming events, as can be seen from the lack of <span class="lyx-mathjax mathjax-inline">$\CPr$</span> event handlers associated with each <span class="lyx-mathjax mathjax-inline">$D$</span>. Second, <span class="lyx-mathjax mathjax-inline">$\EKill S$</span> marks a <em>contour</em> within the tree. Contained facets and subfacets of <span class="lyx-mathjax mathjax-inline">$S$</span> will transition to terminating state as soon as they become inert. An explicit contour is necessary because a facet may create a sibling or child facet as a response to being terminated, and such “hail mary” facets must not be allowed to escape termination.<label class="footnote-number" for="fn_5_52">52</label></p><p id="x_5_2_0_0_11">The reduction relation <span class="lyx-mathjax mathjax-inline">$\CM\longrightarrow\CM'$</span> operates on a machine state <span class="lyx-mathjax mathjax-inline">$\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{\CS}$</span> containing five registers:</p>
<ol id="x_5_2_0_0_17"><li id="x_5_2_0_0_12"><span class="lyx-mathjax mathjax-inline">$\CStore$</span> is the store, mapping field identifiers in <span class="lyx-mathjax mathjax-inline">$\TVar$</span> to field values in <span class="lyx-mathjax mathjax-inline">$\TVal$</span>. Higher-order values such as procedures may not be placed in the store.</li><li id="x_5_2_0_0_13"><span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> is the actor's record of the assertions it has learned from the dataspace. As patch events arrive from the dataspace, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> is updated.</li><li id="x_5_2_0_0_14"><span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span> is the actor's record of the assertions it has placed into the dataspace. As fields are updated and facets are created and destroyed, the actor issues patch actions and updates <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span> to account for the changes.</li><li id="x_5_2_0_0_15"><span class="lyx-mathjax mathjax-inline">$\VECOF a$</span> is an accumulator of dataspace model actions produced. As messages are sent, actors are spawned, and changes are made to published assertions, actions are appended to this register.</li><li id="x_5_2_0_0_16"><span class="lyx-mathjax mathjax-inline">$\CS$</span> is the tree of facets, the actor's behavior and control state. Reduction drives this tree of facets toward inertness.</li></ol>
<h6 class="unnumbered" id="x_5_2_0_0_18"><a name="toc_5.2"></a><span class="heading-text paragraph">Evaluation of expressions and patterns.</span></h6><p id="x_5_2_0_0_19">The semantics of <span class="small-caps">Syndicate/λ</span> depends on evaluation of expressions in a number of places. Evaluation of expressions is straightforward, since no function or procedure calls (other than to primitives) are allowed. In addition, because <span class="small-caps">Syndicate/λ</span> <em>patterns</em> include calls to primitive functions and references to field values, the semantics requires a means of “evaluating” a pattern.</p>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_22">
<div class="footnote" id="fn_5_53"><span class="counter footnote-counter"><span>53</span></span>Field references are not resolved under <span class="lyx-mathjax mathjax-inline">$\lambda$</span> (per the last line of the definition of <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span>), because to do so would be premature: updates to the store between the use of <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span> and subsequent invocation of the procedure would be lost.<span class="plain-layout-boundary"></span></div>
<p id="x_5_2_0_0_21"><span class="counter numbered definition"><span>5.3</span></span><span class="lyx-argument">Evaluation of expressions<span class="plain-layout-boundary"></span></span>The partial metafunction <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span> evaluates an <span class="lyx-mathjax mathjax-inline">$\TExpr$</span> to a <span class="lyx-mathjax mathjax-inline">$\THVal$</span>, resolving field references using a <span class="lyx-mathjax mathjax-inline">$\TStore$</span>.<label class="footnote-number" for="fn_5_53">53</label>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_20">\begin{align*}
\FEVALLName &amp; :\TStore\times\TExpr\rightharpoonup\THVal\\
\FEVALL{\CStore}b &amp; =b\\
\FEVALL{\CStore}{(e,\dots)} &amp; =(\FEVALL{\CStore}e,\dots)\\
\FEVALL{\CStore}{(p\ e\ \dots)} &amp; =\FDELTAL p{\VECOF{\FEVALL{\CStore}e}}\\
\FEVALL{\CStore}x &amp; =\CStore[x]\\
\FEVALL{\CStore}{\CProc{\CClause P{\CPr}\;\dots}} &amp; =\CProc{\CClause P{\CPr}\;\dots}\\
\\
\FEVALName &amp; :\TStore\times\TExpr\rightharpoonup\TVal\\
\FEVAL{\CStore}e &amp; =v\textrm{ if }v=\FEVALL{\CStore}e\in\TVal
\end{align*}
</div>The metafunction <span class="lyx-mathjax mathjax-inline">$\FEVALName$</span> is like <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span>, but with domain <span class="lyx-mathjax mathjax-inline">$\TVal$</span> instead of <span class="lyx-mathjax mathjax-inline">$\THVal$</span>. It is used in contexts where procedure values are forbidden, such as values used to initialize or update a field, or values serving as the body of a message to be transmitted. Both <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span> and <span class="lyx-mathjax mathjax-inline">$\FEVALName$</span> are undefined in cases where they depend on a use of <span class="lyx-mathjax mathjax-inline">$\FDELTALName$</span> that is in turn undefined.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_25">
<p id="x_5_2_0_0_24"><span class="counter numbered definition"><span>5.4</span></span><span class="lyx-argument">Primitive functions<span class="plain-layout-boundary"></span></span>The partial metafunction <span class="lyx-mathjax mathjax-inline">$\FDELTALName$</span> interprets applications of primitive functions <span class="lyx-mathjax mathjax-inline">$p\in\TPrim$</span>, and <span class="lyx-mathjax mathjax-inline">$\FDELTAName$</span> is to <span class="lyx-mathjax mathjax-inline">$\FDELTALName$</span> as <span class="lyx-mathjax mathjax-inline">$\FEVALName$</span> is to <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span>. We do not specify a fixed <span class="lyx-mathjax mathjax-inline">$\TPrim$</span> here, and so escape the need to fix <span class="lyx-mathjax mathjax-inline">$\FDELTALName$</span> in any detail.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_23">\begin{align*}
\FDELTALName &amp; :\TPrim\times\VECOF{\THVal}\rightharpoonup\THVal\\
\FDELTAName &amp; :\TPrim\times\VECOF{\THVal}\rightharpoonup\TVal
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_28">
<p id="x_5_2_0_0_27"><span class="counter numbered definition"><span>5.5</span></span><span class="lyx-argument">“Evaluation” of patterns<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:mf:snapshot"></a><a name="def:mf:snapshot"></a>The metafunction <span class="lyx-mathjax mathjax-inline">$\FSNAPSHOTName$</span> “evaluates” a pattern by computing the results of any embedded calls to primitive operations or references to field values from the store. This “evaluation” process may fail with an exception; however, if it succeeds, the resulting pattern does not include any primitive operations or field references, and therefore is guaranteed not to signal an exception when used.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_26">\begin{align*}
\FSNAPSHOTName &amp; :\TStore\times\TPat\rightarrow\OrError{\TPVal}\\
\FSNAPSHOT{\CStore}{\star} &amp; =\star\\
\FSNAPSHOT{\CStore}b &amp; =b\\
\FSNAPSHOT{\CStore}{()} &amp; =()\\
\FSNAPSHOT{\CStore}{(P_{1},P_{2},\dots)} &amp; =\begin{cases}
(P_{1}',P_{2}',\dots) &amp; \text{if }P_{1}'=\FSNAPSHOT{\CStore}{P_{1}}\\
&amp; \text{and }(P_{2}',\dots)=\FSNAPSHOT{\CStore}{(P_{2},\dots)}\\
\CErr &amp; \text{otherwise}
\end{cases}\\
\FSNAPSHOT{\CStore}{\left(p\;e\;\dots\right)} &amp; =\begin{cases}
v &amp; \text{if }v=\FDELTA p{\VECOF{\FEVALL{\CStore}e}}\\
\CErr &amp; \text{otherwise }
\end{cases}\\
\FSNAPSHOT{\CStore}x &amp; =\CStore[x]\\
\FSNAPSHOT{\CStore}{\CVar x} &amp; =\CVar x
\end{align*}
</div></p><span class="halmos"></span></div>
<h6 class="unnumbered" id="x_5_2_0_0_29"><a name="toc_5.2"></a><span class="heading-text paragraph">The active assertion set.</span></h6><p id="x_5_2_0_0_30">As facets come and go and fields change their values, the set of assertions to be placed into the surrounding dataspace by a <span class="small-caps">Syndicate/λ</span> actor changes. The set must be tracked and, as it changes, corresponding patch actions must be computed and emitted.</p>
<figure class="fullwidth" id="x_5_2_0_0_32"><a name="fig:mf:assertions"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_31">\begin{align*}
\FASSERTIONSName &amp; :\TStore\times\TTree\rightharpoonup\TASet\\
\FASSERTIONS{\CStore}{\CS} &amp; =\begin{cases}
\CSeq{\FASSERTIONS{\CStore}T}{\FASSERTIONS{\CStore}{T'}} &amp; \textrm{if }S=\CSeq T{T'}\\
\FASSERTIONS{\CStore}A\cup\FASSERTIONS{\CStore}D\cup\dots\cup\FASSERTIONS{\CStore}T &amp; \textrm{if }S=\EFacet x{A\CEndpoint D{\CPr}\;\dots}T\\
\FASSERTIONS{\CStore}A\cup\FASSERTIONS{\CStore}D\cup\dots\cup\FASSERTIONS{\CStore}T &amp; \textrm{if }S=\EFacetStop x{A\;D\;\dots}T\\
\emptyset &amp; \textrm{otherwise}
\end{cases}\\
\\
\FASSERTIONSName &amp; :\TStore\times\TEPat\rightharpoonup\TASet\\
\FASSERTIONS{\CStore}D &amp; =\begin{cases}
\emptyset &amp; \textrm{if }D=\DStart\textrm{ or }D=\DStop\\
\{\Obs c\;|\;c\in\ROUTES\} &amp; \textrm{if }D=\DAsserted P\textrm{, }D=\DRetracted P\textrm{ or }D=\DMessage P\\
&amp; \text{where }\ROUTES=\FASSERTIONSName'\;\left(\FSNAPSHOT{\CStore}P\right)
\end{cases}\\
\\
\FASSERTIONSName' &amp; :\TPVal\rightarrow\TASet\\
\FASSERTIONSName'\;P &amp; =\begin{cases}
\TVal &amp; \textrm{if }P=\star\textrm{ or }P=\CVar x\\
\{b\} &amp; \textrm{if }P=b\\
\{()\} &amp; \textrm{if }P=()\\
\{v\times v'\;|\;v\in\FASSERTIONSName'\;P',v'\in\FASSERTIONSName'\;(P'',\dots)\} &amp; \textrm{if }P=(P',P'',\dots)
\end{cases}\\
\\
\FASSERTIONSName &amp; :\TStore\times\TTemplates\rightharpoonup\TASet\\
\FASSERTIONS{\CStore}A &amp; =\begin{cases}
\emptyset &amp; \textrm{if }A=\emptyset\\
\FASSERTIONS{\CStore}k\cup\FASSERTIONS{\CStore}{A'} &amp; \textrm{if }A=k\cup A'
\end{cases}\\
\\
\FASSERTIONSName &amp; :\TStore\times\TTemplate\rightharpoonup\TASet\\
\FASSERTIONS{\CStore}k &amp; =\FASSERTIONSName'\;\left(\FSNAPSHOT{\CStore}k\right)
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>19</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:mf:assertions"></a>The (overloaded) <span class="lyx-mathjax mathjax-inline">$\FASSERTIONSName$</span> metafunction<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered definition" id="x_5_2_0_0_34">
<div class="footnote" id="fn_5_54"><span class="counter footnote-counter"><span>54</span></span>For simplicity of presentation, <span class="lyx-mathjax mathjax-inline">$\FASSERTIONSName$</span> is given as a partial function; it is undefined where <span class="lyx-mathjax mathjax-inline">$\FSNAPSHOTName$</span> yields <span class="lyx-mathjax mathjax-inline">$\CErr$</span>.<span class="plain-layout-boundary"></span></div>
<p id="x_5_2_0_0_33"><span class="counter numbered definition"><span>5.6</span></span>The metafunction <span class="lyx-mathjax mathjax-inline">$\FASSERTIONSName$</span>, which extracts the current set of assertions from a tree of facets, is defined in figure <a class="cross-reference" href="#fig:mf:assertions">19</a>.<label class="footnote-number" for="fn_5_54">54</label> It is a pedestrian structural traversal of syntax except when processing an event pattern <span class="lyx-mathjax mathjax-inline">$D$</span>. In that case, it specially adds the assertion-of-interest constructor <span class="lyx-mathjax mathjax-inline">$\Obs{\cdot}$</span> to each assertion arising from the pattern inside <span class="lyx-mathjax mathjax-inline">$D$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_2_0_0_37">
<p id="x_5_2_0_0_36"><span class="counter numbered definition"><span>5.7</span></span><a class="label-anchor" href="#def:mf:patch"></a><a name="def:mf:patch"></a>In situations where an actor's assertion set may have changed, the metafunction <span class="lyx-mathjax mathjax-inline">$\FPATCHName$</span> is used to compute an updated <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span> register as well as a patch to be appended to the pending action accumulator.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_35">\begin{align*}
\FPATCHName &amp; :\TStore\times\TASet\times\TTree\rightarrow\OrError{\left(\TASet\times\TPatch\right)}\\
\FPATCH{\CStore}{\ROUTES_{o}}{\CS} &amp; =\begin{cases}
\left(\ROUTES_{o}',\CPatch{(\ROUTES_{o}'-\ROUTES_{o})}{(\ROUTES_{o}-\ROUTES_{o}')}\right) &amp; \textrm{if }\ROUTES_{o}'=\FASSERTIONS{\CStore}{\CS}\\
\CErr &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_2_0_0_40">
<p id="x_5_2_0_0_39"><span class="counter numbered definition"><span>5.8</span></span>The metafunction <span class="lyx-mathjax mathjax-inline">$\FEMIT$</span> takes care of combining a patch action (often resulting from <span class="lyx-mathjax mathjax-inline">$\FPATCHName$</span>) with an existing action queue. Any adjacent enqueued patch actions are <em>coalesced</em> using a patch composition operator. By contrast, no such coalescing is desired (or possible) when enqueueing message or actor-creation actions.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_38">\begin{align*}
\FEMIT &amp; :\VECOF{\TAct}\times\TPatch\rightarrow\VECOF{\TAct}\\
\FEMIT\;\cdot\;\Delta &amp; =\Delta\\
\FEMIT\;(\VECOF a\ a')\;\Delta &amp; =\begin{cases}
\VECOF a\;(\Delta\circ\Delta') &amp; \textrm{if }a'=\Delta'\\
\VECOF a\;a'\;\Delta &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_43">
<p id="x_5_2_0_0_42"><span class="counter numbered definition"><span>5.9</span></span><span class="lyx-argument">Patch composition<span class="plain-layout-boundary"></span></span>The patch composition operator is defined as follows:
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_41">\begin{align*}
\cdot\circ\cdot &amp; :\TPatch\times\TPatch\rightarrow\TPatch\\
\CPatch{\ROUTESADD'}{\ROUTESDEL'}\circ\CPatch{\ROUTESADD}{\ROUTESDEL} &amp; =\CPatch{\ROUTESADD\cup\ROUTESADD'-\ROUTESDEL'}{\ROUTESDEL-\ROUTESADD'\cup\ROUTESDEL'}
\end{align*}
</div></p><span class="halmos"></span></div>
<h6 class="unnumbered" id="x_5_2_0_0_44"><a name="toc_5.2"></a><span class="heading-text paragraph">Pattern matching.</span></h6><p id="x_5_2_0_0_45">The <span class="small-caps">Syndicate/λ</span> semantics also makes use of pattern matching in a number of places. Occasionally, a suite of patterns with matching continuations must be searched for the first match for some value; at other times, matching of a single pattern with a single value is required.</p>
<div class="theorem-like numbered definition" id="x_5_2_0_0_48">
<p id="x_5_2_0_0_47"><span class="counter numbered definition"><span>5.10</span></span><a class="label-anchor" href="#def:mf:matchInOrder"></a><a name="def:mf:matchInOrder"></a>The metafunction <span class="lyx-mathjax mathjax-inline">$\FMATCHINORDERName$</span> searches a collection of <span class="lyx-mathjax mathjax-inline">$\CClause P{\CPr}$</span> branches, often extracted from a procedure value, to find the first that matches the argument value given. If none of the branches match, an exception is signaled.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_46">\begin{align*}
\FMATCHINORDERName &amp; :\TStore\times\THVal\times\VECOF{(\TPat\times\TPr)}\rightarrow\OrError{\TPr}\\
\FMATCHINORDER{\CStore}v{\cdot} &amp; =\CErr\\
\hspace{-2em}\FMATCHINORDER{\CStore}v{((P,\CPr)\;\VECOF{(P',\CPr')})} &amp; =\begin{cases}
\CErr &amp; \text{if }\FSNAPSHOT{\CStore}P=\CErr\\
\CPr'' &amp; \textrm{if }\FMATCH{\left(\FSNAPSHOT{\CStore}P\right)}v{\CPr}=\CPr''\\
\FMATCHINORDER{\CStore}v{\VECOF{(P',\CPr')}} &amp; \textrm{if }\FMATCH{\left(\FSNAPSHOT{\CStore}P\right)}v{\CPr}\textrm{ is undefined}
\end{cases}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_2_0_0_51">
<div class="footnote" id="fn_5_55"><span class="counter footnote-counter"><span>55</span></span>As written, <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span> admits repeated pattern variables, allowing later uses of a binder to shadow earlier uses. Implementations of the <span class="small-caps">Syndicate</span> design may reasonably vary in their responses to this situation, depending on the idioms of the base language.<span class="plain-layout-boundary"></span></div>
<p id="x_5_2_0_0_50"><span class="counter numbered definition"><span>5.11</span></span><a class="label-anchor" href="#def:mf:match"></a><a name="def:mf:match"></a>The partial metafunction <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span> is defined when the given <span class="lyx-mathjax mathjax-inline">$\THVal$</span> matches the given <span class="lyx-mathjax mathjax-inline">$\TPVal$</span>, and is otherwise undefined. The result of <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span> is a program fragment that, when interpreted, uses <span class="lyx-mathjax mathjax-inline">$\KLet$</span> to bind pattern variables before continuing with the <span class="lyx-mathjax mathjax-inline">$\TPr$</span> given to <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span>.<label class="footnote-number" for="fn_5_55">55</label>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_49">\begin{align*}
\FMATCHName &amp; :\TPVal\times\THVal\times\TPr\rightharpoonup\TPr\\
\FMATCH{\star}v{\CPr} &amp; =\CPr\\
\FMATCH bb{\CPr} &amp; =\CPr\\
\FMATCH{()}{()}{\CPr} &amp; =\CPr\\
\FMATCH{(P,P',\dots)}{(v,v',\dots)}{\CPr} &amp; =\FMATCH Pv{(\FMATCH{(P',\dots)}{(v',\dots)}{\CPr})}\\
\FMATCH{\CVar x}v{\CPr} &amp; =\CBind xv{\CPr}
\end{align*}
</div></p><span class="halmos"></span></div>
<h6 class="unnumbered" id="x_5_2_0_0_52"><a name="toc_5.2"></a><span class="heading-text paragraph">Reduction relation.</span></h6>
<figure class="fullwidth" id="x_5_2_0_0_54"><a name="fig:PLLAMBDA-reduction-rules-I"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_53">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CCall{e_{1}}{e_{2}}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E\left[\mathit{S}\right]} &amp; &amp; (\RCall)\\
\textrm{where } &amp; S=\begin{cases}
\FMATCHINORDER{\CStore}v{\VECOF{(P,\CPr)}} &amp; \text{if }\CProc{\CClause P{\CPr}\;\dots}=\FEVALL{\CStore}{e_{1}}\\
&amp; \textrm{and }v=\FEVALL{\CStore}{e_{2}}\\
\CErr &amp; \text{otherwise }
\end{cases}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CBind xe{\CPr}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[S]} &amp; &amp; (\RLet)\\
\textrm{where } &amp; S=\begin{cases}
\SUBSTval{\CPr}vx &amp; \text{if }v=\FEVALL{\CStore}e\\
\CErr &amp; \text{otherwise}
\end{cases}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CField xe{\CPr}]} &amp; \longrightarrow\Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[S]} &amp; &amp; (\RNewField)\\
\textrm{where } &amp; y\textrm{ fresh and }\left(\CStore',S\right)=\begin{cases}
\left(\EXTEND{\CStore}yv,\SUBSTfield{\CPr}yx\right) &amp; \text{if }v=\FEVAL{\CStore}e\\
\left(\CStore,\CErr\right) &amp; \text{otherwise}
\end{cases}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CUpdate xe]} &amp; \longrightarrow\Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E[S]} &amp; &amp; (\RSetField)\\
\textrm{where } &amp; x\in\mathsf{dom}(\CStore)\\
&amp; \left(\CStore',S,\ROUTES_{o}',\Delta\right)=\begin{cases}
\left(\EXTEND{\CStore}xv,\CInert,\ROUTES_{o}',\Delta\right) &amp; \text{if }v=\FEVAL{\CStore}e\\
&amp; \text{and }(\ROUTES_{o}',\Delta)=\rlap{\FPATCH{\CStore}{\ROUTES_{o}}{E[0]}}\\
\left(\CStore,\CErr,\ROUTES_{o},\CPatch{\emptyset}{\emptyset}\right) &amp; \text{otherwise}
\end{cases}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSend e]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;\VECOF a'}{E[S]} &amp; &amp; (\RSend)\\
\text{where } &amp; \left(\VECOF a',S\right)=\begin{cases}
\left(\AMsg v,0\right) &amp; \text{if }v=\FEVAL{\CStore}e\\
\left(\cdot,\CErr\right) &amp; \text{otherwise}
\end{cases}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSpawn{\CPr}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;(\AActor{(\FSETUP\;(\CStore,\CPr))}{\emptyset})}{E[\CInert]} &amp; &amp; (\RSpawn)\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CDS{\CPr}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;a'}{E[0]} &amp; &amp; (\RDataspace)\\
\textrm{where } &amp; a'=\ADS{(\AActor{(\FSETUP\;(\CStore,\CPr))}{\emptyset)}}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>20</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLLAMBDA-reduction-rules-I"></a><span class="small-caps">Syndicate/λ</span> reduction rules (procedure call, variables, fields, actions)<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure class="fullwidth" id="x_5_2_0_0_56"><a name="fig:PLLAMBDA-reduction-rules-II"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_55">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CFacet x{A\CEndpoint D{\CPr}\;\dots}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E\left[S'\right]} &amp; &amp; (\RBootFacet)\\
\textrm{where } &amp; S=\left(\EFacet y{A\CEndpoint D{\left(\SUBSTfacet{\CPr}yx\right)}\;\dots}T\right)\\
&amp; (S',\ROUTES_{o}',\Delta)=\begin{cases}
(S,\ROUTES_{o}',\Delta) &amp; \rlap{\text{if }(\ROUTES_{o}',\Delta)=\FPATCH{\CStore}{\ROUTES_{o}}{E\left[S\right]}}\\
\left(\CErr,\ROUTES_{o},\CPatch{\emptyset}{\emptyset}\right) &amp; \rlap{\text{otherwise}}
\end{cases}\\
&amp; T_{\DStart}=\FHANDLE{\emptyset}{\ROUTES_{i}}{\CStore}{\DStart}{\VECOF{(D,\CPr)}}\\
&amp; T_{\DAsserted{\!\!}}=\FHANDLE{\emptyset}{\ROUTES_{i}}{\CStore}{\CPatch{\ROUTES_{i}}{\emptyset}}{\VECOF{(D,\CPr)}}\\
&amp; T=\SUBSTfacet{\left(\CSeq{T_{\DStart}}{T_{\DAsserted{\!\!}}}\right)}yx\\
&amp; y\textrm{ fresh}\\
\\
\hspace{-4em}\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacet x{A\CEndpoint D{\CPr}\;\dots}{F[\CStop x{\CPr'}]}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EKill{\EFacet x{A\CEndpoint D{\CPr}\;\dots}{F[\CInert]}}}{\CPr'}]} &amp; &amp; (\RStopFacetA)\\
\textrm{where } &amp; x\notin\BV F\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{F[\CStop x{\CPr'}]}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EFacetStop x{A\;D\;\dots}{F[\CInert]}}{\CPr'}]} &amp; &amp; (\RStopFacetB)\\
\textrm{where } &amp; x\notin\BV F\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\CInert}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CInert]} &amp; &amp; (\RStopChildA)\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\CSeq{\CSI}{T_{I}}}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EKill{\CSI}}{\EKill{T_{I}}}]} &amp; &amp; (\RStopChildB)\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\EFacet x{A\CEndpoint D{\CPr}\;\dots}{\CSI}}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{\EKill{\CSeq{\CSI}T}}]} &amp; &amp; (\RStopChildC)\\
\textrm{where } &amp; T=\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}}{\CStore}{\DStop}{\VECOF{(D,\CPr)}}\\
\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{\CInert}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E[S']} &amp; &amp; (\RBurial)\\
\textrm{where } &amp; (S',\ROUTES_{o}',\Delta)=\begin{cases}
(0,\ROUTES_{o}',\Delta) &amp; \rlap{\text{if }(\ROUTES_{o}',\Delta)=\FPATCH{\CStore}{\ROUTES_{o}}{E[\CInert]}}\\
\left(\CErr,\ROUTES_{o},\CPatch{\emptyset}{\emptyset}\right) &amp; \rlap{\text{otherwise}}
\end{cases}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>21</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLLAMBDA-reduction-rules-II"></a><span class="small-caps">Syndicate/λ</span> reduction rules (facet startup and shutdown)<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_5_56"><span class="counter footnote-counter"><span>56</span></span>The development of the reduction rules was informed by discussions with Sam Caldwell.<span class="plain-layout-boundary"></span></div><p id="x_5_2_0_0_57">The reduction relation is defined by fourteen rules,<label class="footnote-number" for="fn_5_56">56</label> shown in full in figures <a class="cross-reference" href="#fig:PLLAMBDA-reduction-rules-I">20</a> and <a class="cross-reference" href="#fig:PLLAMBDA-reduction-rules-II">21</a>. The <span class="lyx-mathjax mathjax-inline">$\RCall$</span> rule implements procedure call, and rule <span class="lyx-mathjax mathjax-inline">$\RLet$</span> allows introduction of immutable variables. The <span class="lyx-mathjax mathjax-inline">$\RNewField$</span> and <span class="lyx-mathjax mathjax-inline">$\RSetField$</span> rules manipulate fields, while rules <span class="lyx-mathjax mathjax-inline">$\RSend$</span>, <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\RDataspace$</span> produce actions for interpretation by an actor's surrounding dataspace. The remainder of the rules relate to facet startup and shutdown: <span class="lyx-mathjax mathjax-inline">$\RBootFacet$</span> instantiates a facet, while the two <span class="lyx-mathjax mathjax-inline">$\RULENAME{stop-facet}$</span> rules, three <span class="lyx-mathjax mathjax-inline">$\RULENAME{stop-child}$</span> rules, and <span class="lyx-mathjax mathjax-inline">$\RBurial$</span> rule combine to handle the process of facet termination.</p>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_60">
<p id="x_5_2_0_0_59"><span class="counter numbered definition"><span>5.12</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RCall$</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#def:rule:call"></a><a name="def:rule:call"></a>The <span class="lyx-mathjax mathjax-inline">$\RCall$</span> rule interprets procedure calls <span class="lyx-mathjax mathjax-inline">$\CCall{e_{1}}{e_{2}}$</span>:
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_58">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CCall{e_{1}}{e_{2}}]}\longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E\left[\mathit{S}\right]}
\]
</div>It first attempts to evaluate both <span class="lyx-mathjax mathjax-inline">$e_{1}$</span> and <span class="lyx-mathjax mathjax-inline">$e_{2}$</span> to elements of <span class="lyx-mathjax mathjax-inline">$\THVal$</span> via the metafunction <span class="lyx-mathjax mathjax-inline">$\FEVALLName$</span>. If both <span class="lyx-mathjax mathjax-inline">$\FEVALL{\CStore}{e_{1}}=\CProc{\CClause P{\CPr}\;\dots}\in\THVal$</span> and <span class="lyx-mathjax mathjax-inline">$\FEVALL{\CStore}{e_{2}}=v\in\THVal$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\FMATCHINORDER{\CStore}v{\VECOF{(P,\CPr)}}$</span> on the right hand side of the relation; otherwise, <span class="lyx-mathjax mathjax-inline">$S=\CErr$</span>.</p><span class="halmos"></span></div>
<figure class="fullwidth" id="x_5_2_0_0_64"><a name="fig:mf:fv-bv"></a>
<div class="frameless-box" id="x_5_2_0_0_63">
<div class="frameless-box" id="x_5_2_0_0_62"><span class="scriptsize">
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_61">\begin{align*}
\FVName &amp; :\TTree\rightarrow\SETOF{\TVar} &amp; \BVName &amp; :\TE\rightarrow\SETOF{\TVar}\\
\FV 0 &amp; =\emptyset &amp; \BV{\hole} &amp; =\emptyset\\
\FV{\CSeq ST} &amp; =\FV S\cup\FV T &amp; \BV{\CSeq E{\CS}} &amp; =\BV E\\
\FV{\CCall{e_{1}}{e_{2}}} &amp; =\FV{e_{1}}\cup\FV{e_{2}} &amp; \BV{\CSeq{\CSI}E} &amp; =\BV E\\
\FV{\CField xe{\CPr}} &amp; =\FV e\cup(\FV{\CPr}-\{x\}) &amp; \BV{\EFacet x{A\CEndpoint D{\CPr}\;\dots}E} &amp; =\{x\}\cup\BV E\\
\FV{\CBind xe{\CPr}} &amp; =\FV e\cup(\FV{\CPr}-\{x\}) &amp; \BV{\EFacetStop x{A\;D\;\dots}E} &amp; =\{x\}\cup\BV E\\
\FV{\CUpdate xe} &amp; =\{x\}\cup\FV e &amp; \BV{\EKill E} &amp; =\BV E\\
\FV{\CSpawn{\CPr}} &amp; =\FV{\CPr}\\
\FV{\CDS{\CPr}} &amp; =\FV{\CPr}\\
\FV{\CStop x{\CPr}} &amp; =\{x\}\cup\FV{\CPr}\\
\FV{\CFacet x{A\CEndpoint D{\CPr}\;\dots}} &amp; =\left(\FV A\cup(\FV D\cup(\FV{\CPr}-\FORMALS D))\cup\dots\right)-\{x\}\hspace{-10em}\\
\FV{\EFacet x{A\CEndpoint D{\CPr}\;\dots}T} &amp; =\left(\FV A\cup(\FV D\cup(\FV{\CPr}-\FORMALS D))\cup\dots\cup\FV T\right)-\{x\}\hspace{-7em} &amp; \FVName &amp; :\TTemplates\rightarrow\SETOF{\TVar}\\
\FV{\EFacetStop x{A\;D\;\dots}T} &amp; =\left(\FV A\cup\FV D\cup\dots\cup\FV T\right)-\{x\}\hspace{-10em} &amp; \FV{\emptyset} &amp; =\emptyset\\
\FV{\EKill S} &amp; =\FV S &amp; \FV{k\cup A} &amp; =\FV k\cup\FV A\\
\\
\FVName &amp; :\TExpr\rightarrow\SETOF{\TVar} &amp; \FVName &amp; :\TTemplate\rightarrow\SETOF{\TVar}\\
\FV b &amp; =\emptyset &amp; \FV{\star} &amp; =\emptyset\\
\FV{(e,\dots)} &amp; =\FV e\cup\dots &amp; \FV b &amp; =\emptyset\\
\FV{p\ e\ \dots} &amp; =\FV e\cup\dots &amp; \FV{(k,\dots)} &amp; =\FV e\cup\dots\\
\FV x &amp; =\{x\} &amp; \FV{p\ e\ \dots} &amp; =\FV e\cup\dots\\
\FV{\CProc{\CClause P{\CPr}\;\dots}} &amp; =(\FV P\cup(\FV{\CPr}-\FORMALS P))\cup\dots\hspace{-10em} &amp; \FV x &amp; =\{x\}\\
\\
\FVName &amp; :\TEPat\rightarrow\SETOF{\TVar} &amp; \FORMALSName &amp; :\TEPat\rightarrow\SETOF{\TVar}\\
\FV{\DAsserted P} &amp; =\FV P &amp; \FORMALS{\DAsserted P} &amp; =\FORMALS P\\
\FV{\DRetracted P} &amp; =\FV P &amp; \FORMALS{\DRetracted P} &amp; =\FORMALS P\\
\FV{\DMessage P} &amp; =\FV P &amp; \FORMALS{\DMessage P} &amp; =\FORMALS P\\
\FV{\DStart}=\FV{\DStop} &amp; =\emptyset &amp; \hspace{-10em}\FORMALS{\DStart}=\FORMALS{\DStop} &amp; =\emptyset\\
\\
\FVName &amp; :\TPat\rightarrow\SETOF{\TVar} &amp; \FORMALSName &amp; :\TPat\rightarrow\SETOF{\TVar}\\
\FV{\star} &amp; =\emptyset &amp; \FORMALS{\star} &amp; =\emptyset\\
\FV b &amp; =\emptyset &amp; \FORMALS b &amp; =\emptyset\\
\FV{(P,\dots)} &amp; =\FV P\cup\dots &amp; \FORMALS{(P,\dots)} &amp; =\FORMALS P\cup\dots\\
\FV{p\ e\ \dots} &amp; =\FV e\cup\dots &amp; \FORMALS{p\ e\ \dots} &amp; =\emptyset\\
\FV x &amp; =\{x\} &amp; \FORMALS x &amp; =\emptyset\\
\FV{\CVar x} &amp; =\emptyset &amp; \FORMALS{\CVar x} &amp; =\{x\}
\end{align*}
</div></span><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>22</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:mf:fv-bv"></a>Free and bound names<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_67">
<div class="footnote" id="fn_5_57"><span class="counter footnote-counter"><span>57</span></span>See <span class="citation citet"><a class="citation" id="cite-106" href="#bib-Barendregt1984"><span>Barendregt<span class="parens"> (</span>1984<span class="parens">)</span></span></a> <span class="citation-after">ch. 2</span></span>. Our notation <span class="lyx-mathjax mathjax-inline">$\SUBSTval{\CPr}vx$</span> reads “replace <span class="lyx-mathjax mathjax-inline">$x$</span> with <span class="lyx-mathjax mathjax-inline">$v$</span> in <span class="lyx-mathjax mathjax-inline">$\CPr$</span>”.<span class="plain-layout-boundary"></span></div>
<p id="x_5_2_0_0_66"><span class="counter numbered definition"><span>5.13</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RLet$</span><span class="plain-layout-boundary"></span></span>The first kind of <span class="lyx-mathjax mathjax-inline">$\KLet$</span> construct allows programmers to give names to values drawn from <span class="lyx-mathjax mathjax-inline">$\THVal$</span>. Machine states do not include an environment, and so our presentation makes use of hygienic substitution<label class="footnote-number" for="fn_5_57">57</label> to replace references to a bound variable <span class="lyx-mathjax mathjax-inline">$x$</span> with its <span class="lyx-mathjax mathjax-inline">$\KLet$</span>-computed value while respecting the notion of free names captured by the metafunction <span class="lyx-mathjax mathjax-inline">$\FVName$</span> (figure <a class="cross-reference" href="#fig:mf:fv-bv">22</a>).
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_65">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CBind xe{\CPr}]}\longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[S]}
\]
</div>If <span class="lyx-mathjax mathjax-inline">$\FEVALL{\CStore}e=v\in\THVal$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\SUBSTval{\CPr}vx$</span> on the right hand side; otherwise, <span class="lyx-mathjax mathjax-inline">$S=\CErr$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_70">
<p id="x_5_2_0_0_69"><span class="counter numbered definition"><span>5.14</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RNewField$</span><span class="plain-layout-boundary"></span></span>The second kind of <span class="lyx-mathjax mathjax-inline">$\KLet$</span> construct creates a new field, allocating a fresh name <span class="lyx-mathjax mathjax-inline">$y$</span> for the field and substituting <span class="lyx-mathjax mathjax-inline">$y$</span> for references to the field in the body of the <span class="lyx-mathjax mathjax-inline">$\KLet$</span>. The store <span class="lyx-mathjax mathjax-inline">$\CStore$</span> in the machine state is updated with the initial value of the field, which is constrained to be drawn from <span class="lyx-mathjax mathjax-inline">$\TVal$</span>.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_68">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CField xe{\CPr}]}\longrightarrow\Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[S]}
\]
</div>If <span class="lyx-mathjax mathjax-inline">$\FEVAL{\CStore}e=v\in\TVal$</span> then <span class="lyx-mathjax mathjax-inline">$\CStore'=\EXTEND{\CStore}yv$</span> and <span class="lyx-mathjax mathjax-inline">$S=\CPr$</span> on the right hand side; otherwise, <span class="lyx-mathjax mathjax-inline">$\CStore'=\CStore$</span> and <span class="lyx-mathjax mathjax-inline">$S=\CErr$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_73">
<p id="x_5_2_0_0_72"><span class="counter numbered definition"><span>5.15</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RSetField$</span><span class="plain-layout-boundary"></span></span>In rule <span class="lyx-mathjax mathjax-inline">$\RSetField$</span>, we see the first production of an action for transmission to the surrounding dataspace. Updating a field affects any assertions depending on the field, and a patch action must be issued to communicate any changed assertions to the actor's peers.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_71">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CUpdate xe]}\longrightarrow\Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E[S]}\textrm{ where }x\in\mathsf{dom}(\CStore)
\]
</div>If <span class="lyx-mathjax mathjax-inline">$\FEVAL{\CStore}e=v\in\TVal$</span>, then <span class="lyx-mathjax mathjax-inline">$\CStore'=\EXTEND{\CStore}xv$</span>, <span class="lyx-mathjax mathjax-inline">$S=\CInert$</span>, and <span class="lyx-mathjax mathjax-inline">$(\ROUTES_{o}',\Delta)=\FPATCH{\CStore}{\ROUTES_{o}}{E[0]}$</span>. Otherwise, <span class="lyx-mathjax mathjax-inline">$\CStore'=\CStore$</span>, <span class="lyx-mathjax mathjax-inline">$S=\CErr$</span>, and <span class="lyx-mathjax mathjax-inline">$(\ROUTES_{o}',\Delta)=(\ROUTES_{o},\CPatch{\emptyset}{\emptyset})$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_76">
<p id="x_5_2_0_0_75"><span class="counter numbered definition"><span>5.16</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RSend$</span><span class="plain-layout-boundary"></span></span>The <span class="lyx-mathjax mathjax-inline">$\RSend$</span> rule is entirely straightforward:
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_74">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSend e]}\longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;\VECOF a'}{E[S]}
\]
</div>If <span class="lyx-mathjax mathjax-inline">$\FEVAL{\CStore}{e=v\in\TVal}$</span>, then <span class="lyx-mathjax mathjax-inline">$S=0$</span> and <span class="lyx-mathjax mathjax-inline">$\VECOF a'=\AMsg v$</span>; otherwise, <span class="lyx-mathjax mathjax-inline">$S=\CErr$</span> and <span class="lyx-mathjax mathjax-inline">$\VECOF a'$</span> is the empty sequence.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_80">
<p id="x_5_2_0_0_79"><span class="counter numbered definition"><span>5.17</span></span><span class="lyx-argument">Rules <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\RDataspace$</span><span class="plain-layout-boundary"></span></span>The <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\RDataspace$</span> rules are also uncomplicated, but depend on the <span class="lyx-mathjax mathjax-inline">$\FSETUP$</span> metafunction, which we will not discuss until section <a class="cross-reference" href="#sec:PLLAMBDA-DS-interface">5.4</a>.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_77">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSpawn{\CPr}]}\longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;(\AActor{(\FSETUP\;(\CStore,\CPr))}{\emptyset})}{E[\CInert]}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_78">\[
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CDS{\CPr}]}\longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a\;\left(\ADS{(\AActor{(\FSETUP\;(\CStore,\CPr))}{\emptyset)}}\right)}{E[0]}
\]
</div></p><span class="halmos"></span></div><p id="x_5_2_0_0_81">The remaining reduction rules (figure <a class="cross-reference" href="#fig:PLLAMBDA-reduction-rules-II">21</a>) all relate to various stages of a facet's lifecycle.</p>
<div class="theorem-like numbered definition" id="x_5_2_0_0_84">
<p id="x_5_2_0_0_83"><span class="counter numbered definition"><span>5.18</span></span>Rule <span class="lyx-mathjax mathjax-inline">$\RBootFacet$</span> interprets a facet template <span class="lyx-mathjax mathjax-inline">$\CFacet x{A\CEndpoint D{\CPr}\ \dots}$</span>, renaming it, transforming it to an interior node in the facet tree and delivering two <em>synthetic events</em> to it.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_82">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CFacet x{A\CEndpoint D{\CPr}\;\dots}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E\left[S'\right]}\\
\textrm{where } &amp; S=\left(\EFacet y{A\CEndpoint D{\left(\SUBSTfacet{\CPr}yx\right)}\;\dots}T\right)\\
&amp; (S',\ROUTES_{o}',\Delta)=\begin{cases}
(S,\ROUTES_{o}',\Delta) &amp; \text{if }(\ROUTES_{o}',\Delta)=\FPATCH{\CStore}{\ROUTES_{o}}{E\left[S\right]}\\
\left(\CErr,\ROUTES_{o},\CPatch{\emptyset}{\emptyset}\right) &amp; \text{otherwise}
\end{cases}\\
&amp; T_{\DStart}=\FHANDLE{\emptyset}{\ROUTES_{i}}{\CStore}{\DStart}{\VECOF{(D,\CPr)}}\\
&amp; T_{\DAsserted{\!\!}}=\FHANDLE{\emptyset}{\ROUTES_{i}}{\CStore}{\CPatch{\ROUTES_{i}}{\emptyset}}{\VECOF{(D,\CPr)}}\\
&amp; T=\SUBSTfacet{\left(\CSeq{T_{\DStart}}{T_{\DAsserted{\!\!}}}\right)}yx\\
&amp; y\textrm{ fresh}
\end{align*}
</div>First, a <span class="lyx-mathjax mathjax-inline">$\DStart$</span> event allows the facet to execute any startup actions necessary following the establishment of its assertions and endpoints by the action <span class="lyx-mathjax mathjax-inline">$\Delta$</span>. Second, a synthetic <em>patch</em> <span class="lyx-mathjax mathjax-inline">$\CPatch{\ROUTES_{i}}{\emptyset}$</span> is delivered to the new facet, intended to “catch it up” on events preceding its instantiation. The patch conveys to the facet the sum total of the assertions that the actor has already learned from its dataspace. This latter event is necessary because otherwise any event-handlers in the new facet do not have a chance to react to existing assertions; the dataspace is economical with its events, never repeating itself unnecessarily, as shown by theorem <a class="cross-reference" href="#thm:concision">4.53</a>. The final effect of <span class="lyx-mathjax mathjax-inline">$\RBootFacet$</span> is to update <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span> and issue a patch <span class="lyx-mathjax mathjax-inline">$\Delta$</span> to account for the assertions of the new facet.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_87">
<p id="x_5_2_0_0_86"><span class="counter numbered definition"><span>5.19</span></span><span class="lyx-argument">The <span class="lyx-mathjax mathjax-inline">$\RULENAME{stop-facet}$</span> rules<span class="plain-layout-boundary"></span></span> Rules <span class="lyx-mathjax mathjax-inline">$\RStopFacetA$</span> and <span class="lyx-mathjax mathjax-inline">$\RStopFacetB$</span> handle explicit facet termination requests:
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_85">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacet x{A\CEndpoint D{\CPr}\;\dots}{F[\CStop x{\CPr'}]}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EKill{\EFacet x{A\CEndpoint D{\CPr}\;\dots}{F[\CInert]}}}{\CPr'}]}\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{F[\CStop x{\CPr'}]}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EFacetStop x{A\;D\;\dots}{F[\CInert]}}{\CPr'}]}
\end{align*}
</div>The nested context <span class="lyx-mathjax mathjax-inline">$F$</span> is used to connect the containing facet named <span class="lyx-mathjax mathjax-inline">$x$</span> with the redex requesting its termination, <span class="lyx-mathjax mathjax-inline">$\CStop x{\CPr'}$</span>. A side-condition <span class="lyx-mathjax mathjax-inline">$x\notin\BV F$</span> applies (see figure <a class="cross-reference" href="#fig:mf:fv-bv">22</a>); it ensures that the facet name <span class="lyx-mathjax mathjax-inline">$x$</span> is not captured by any node in <span class="lyx-mathjax mathjax-inline">$F$</span> sitting between the identified facet <span class="lyx-mathjax mathjax-inline">$x$</span> and the termination request. In the first of the two rules, <span class="lyx-mathjax mathjax-inline">$\RStopFacetA$</span>, facet <span class="lyx-mathjax mathjax-inline">$x$</span> is an ordinary running facet that has not yet begun its termination process. The rule encloses it in <span class="lyx-mathjax mathjax-inline">$\EKill{\cdot}$</span> to trigger termination. In the second, <span class="lyx-mathjax mathjax-inline">$\RStopFacetB$</span>, facet <span class="lyx-mathjax mathjax-inline">$x$</span> is an already-terminated facet that is awaiting final tear-down, and no additional <span class="lyx-mathjax mathjax-inline">$\EKill{\cdot}$</span> is required. In each case, the <span class="lyx-mathjax mathjax-inline">$\CPr'$</span> is hoisted to a position adjacent to facet <span class="lyx-mathjax mathjax-inline">$x$</span>, just inside the outer context <span class="lyx-mathjax mathjax-inline">$\CE$</span>, but outside the scope of the <span class="lyx-mathjax mathjax-inline">$\EKill{\cdot}$</span> termination contour corresponding to <span class="lyx-mathjax mathjax-inline">$x$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_90">
<p id="x_5_2_0_0_89"><span class="counter numbered definition"><span>5.20</span></span><span class="lyx-argument">The <span class="lyx-mathjax mathjax-inline">$\RULENAME{stop-child}$</span> rules<span class="plain-layout-boundary"></span></span>Termination boundaries <span class="lyx-mathjax mathjax-inline">$\EKill{\cdot}$</span> are moved leafward through a facet tree by rules <span class="lyx-mathjax mathjax-inline">$\RStopChildA$</span>, <span class="lyx-mathjax mathjax-inline">$\RStopChildB$</span>, and <span class="lyx-mathjax mathjax-inline">$\RStopChildC$</span>.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_88">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\CInert}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CInert]}\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\CSeq{\CSI}{T_{I}}}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\CSeq{\EKill{\CSI}}{\EKill{T_{I}}}]}\\
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EKill{\EFacet x{A\CEndpoint D{\CPr}\;\dots}{\CSI}}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{\EKill{\CSeq{\CSI}T}}]}\\
\textrm{where } &amp; T=\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}}{\CStore}{\DStop}{\VECOF{(D,\CPr)}}
\end{align*}
</div>The first two of the three are simple structural rules. It is <span class="lyx-mathjax mathjax-inline">$\RStopChildC$</span> where a termination boundary and a running facet interact. The rule applies only when the facet is inert; that is, where any previously-triggered event handlers have run their course. As the termination boundary passes by the facet's node, the node is converted from the form <span class="lyx-mathjax mathjax-inline">$\EFacet x{A\CEndpoint D{\CPr}\;\dots}S$</span> to the form <span class="lyx-mathjax mathjax-inline">$\EFacetStop x{A\;D\;\dots}S$</span> and a <span class="lyx-mathjax mathjax-inline">$\DStop$</span> event is synthesized and delivered to the facet's event-handling endpoints. Any resulting commands are inserted adjacent to the existing (inert) children, but remain <em>inside</em> the termination contour.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_2_0_0_93">
<p id="x_5_2_0_0_92"><span class="counter numbered definition"><span>5.21</span></span><span class="lyx-argument">Rule <span class="lyx-mathjax mathjax-inline">$\RBurial$</span><span class="plain-layout-boundary"></span></span> The final tear-down of a terminated facet does not take place until all of its children have not only become inert but have actually reduced to a literal <span class="lyx-mathjax mathjax-inline">$\CInert$</span>. The <span class="lyx-mathjax mathjax-inline">$\RBurial$</span> rule takes care of this case. It is here that we finally see a patch action issued to remove the assertions of the terminating facet from the actor's aggregate assertion set.
<div class="lyx-mathjax mathjax-display" id="x_5_2_0_0_91">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{E[\EFacetStop x{A\;D\;\dots}{\CInert}]} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}'}{\FEMIT\;\VECOF a\;\Delta}{E[S']}
\end{align*}
</div>If <span class="lyx-mathjax mathjax-inline">$\FPATCH{\CStore}{\ROUTES_{o}}{E[\CInert]}$</span> yields a pair <span class="lyx-mathjax mathjax-inline">$(\ROUTES_{o}',\Delta)$</span>, then <span class="lyx-mathjax mathjax-inline">$S'=\CInert$</span>; otherwise, <span class="lyx-mathjax mathjax-inline">$\FPATCHName$</span> yields <span class="lyx-mathjax mathjax-inline">$\CErr$</span> and we set <span class="lyx-mathjax mathjax-inline">$S'=\CErr$</span>, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}'=\ROUTES_{o}$</span> and <span class="lyx-mathjax mathjax-inline">$\Delta=\CPatch{\emptyset}{\emptyset}$</span>.</p><span class="halmos"></span></div>
<h4 id="x_5_3_0_0_1"><a name="toc_5.3"></a><span class="counter section"><span>5.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:PLLAMBDA-interpretation-of-events"></a><a name="sec:PLLAMBDA-interpretation-of-events"></a>Interpretation of events</span></h4><p id="x_5_3_0_0_2">Several of the reduction rules appeal to a metafunction <span class="lyx-mathjax mathjax-inline">$\FHANDLEName$</span> to compute the consequences of a reaction to an event by a collection of event-handling endpoints. As we will see in section <a class="cross-reference" href="#sec:PLLAMBDA-DS-interface">5.4</a>, the same metafunction is used to distribute events arriving from the containing dataspace among the facets in an actor's facet tree.</p>
<div class="theorem-like numbered definition" id="x_5_3_0_0_13">
<p id="x_5_3_0_0_11"><span class="counter numbered definition"><span>5.22</span></span><a class="label-anchor" href="#def:mf:handle"></a><a name="def:mf:handle"></a>The <span class="lyx-mathjax mathjax-inline">$\FHANDLEName$</span> function itself is straightforward:
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_3">\begin{align*}
\FHANDLEName &amp; :\TASet\times\TASet\times\TStore\times\THEvt\times\VECOF{(\TEPat\times\TPr)}\rightarrow\TTree\\
\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CHEvt}{\cdot} &amp; =\CInert\\
\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CHEvt}{((D,\CPr)\;\VECOF{(D',\CPr')})} &amp; =\CSeq{\CS}{\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CHEvt}{\VECOF{(D',\CPr')}}}
\end{align*}
</div>where <span class="lyx-mathjax mathjax-inline">$S$</span> in the second clause is defined by cases:
<ul id="x_5_3_0_0_10"><li id="x_5_3_0_0_4">if <span class="lyx-mathjax mathjax-inline">$D=\DAsserted P$</span> and <span class="lyx-mathjax mathjax-inline">${\displaystyle \CHEvt=\CPatch{\ROUTESADD}{\ROUTESDEL}}$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\FPROJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\ROUTESADD}P{\CPr}$</span>; otherwise,</li><li id="x_5_3_0_0_5">if <span class="lyx-mathjax mathjax-inline">$D=\DRetracted P$</span> and <span class="lyx-mathjax mathjax-inline">$\CHEvt=\CPatch{\ROUTESADD}{\ROUTESDEL}$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\FPROJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\ROUTESDEL}P{\CPr}$</span>; otherwise,</li><li id="x_5_3_0_0_6">if <span class="lyx-mathjax mathjax-inline">$D=\DMessage P$</span> and <span class="lyx-mathjax mathjax-inline">$\CHEvt=\AMsg c$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\FMATCHINORDER{\CStore}c{((P,\CPr)\;(\star,\CInert))}$</span>; otherwise,</li><li id="x_5_3_0_0_7">if <span class="lyx-mathjax mathjax-inline">$D=\DStart$</span> and <span class="lyx-mathjax mathjax-inline">$\CHEvt=\DStart$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\CPr$</span>; otherwise,</li><li id="x_5_3_0_0_8">if <span class="lyx-mathjax mathjax-inline">$D=\DStop$</span> and <span class="lyx-mathjax mathjax-inline">$\CHEvt=\DStop$</span>, then <span class="lyx-mathjax mathjax-inline">$S=\CPr$</span>; otherwise,</li><li id="x_5_3_0_0_9"><span class="lyx-mathjax mathjax-inline">$S=0$</span>.</li></ul></p>
<p id="x_5_3_0_0_12">The sequence of event-handling endpoints becomes a composition of programs. Each endpoint becomes <span class="lyx-mathjax mathjax-inline">$\CInert$</span> if the given event does not apply. Patch events apply to <span class="lyx-mathjax mathjax-inline">$\KAsserted$</span> and <span class="lyx-mathjax mathjax-inline">$\KRetracted$</span> endpoints; message events to <span class="lyx-mathjax mathjax-inline">$\KMessage$</span> endpoints; and <span class="lyx-mathjax mathjax-inline">$\DStart$</span> and <span class="lyx-mathjax mathjax-inline">$\DStop$</span> events to <span class="lyx-mathjax mathjax-inline">$\DStart$</span> and <span class="lyx-mathjax mathjax-inline">$\DStop$</span> endpoints. The interesting cases are message delivery and patch handling. Message delivery delegates to <span class="lyx-mathjax mathjax-inline">$\FMATCHINORDERName$</span> with the event-handler's pattern <span class="lyx-mathjax mathjax-inline">$P$</span> and continuation <span class="lyx-mathjax mathjax-inline">$\CPr$</span> augmented with a catch-all <span class="lyx-mathjax mathjax-inline">$\CInert$</span> clause to handle the case where the incoming message does not match <span class="lyx-mathjax mathjax-inline">$P$</span>. Patch processing delegates to the metafunction <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_3_0_0_17">
<p id="x_5_3_0_0_16"><span class="counter numbered definition"><span>5.23</span></span><a class="label-anchor" href="#def:mf:project"></a><a name="def:mf:project"></a>The <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> metafunction extracts a <em>finite sequence</em> of assertions matching pattern <span class="lyx-mathjax mathjax-inline">$P$</span> from an assertion set carried in a patch. Each relevant assertion should generate one instance of the event handler program <span class="lyx-mathjax mathjax-inline">$\CPr$</span>. It is clearly an error to attempt to iterate over an infinite set; therefore, <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> yields an exception in cases where the assertion set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> being projected contains an infinite number of individual assertions that happen to match the pattern <span class="lyx-mathjax mathjax-inline">$P$</span>.
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_14">\begin{align*}
\FPROJECTName &amp; :\TASet\times\TASet\times\TStore\times\TASet\times\TPat\times\TPr\rightarrow\TTree\\
\FPROJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\ROUTES}P{\CPr} &amp; =\begin{cases}
\CErr &amp; \text{if }P'=\CErr\\
\FUNROLL\;m &amp; \textrm{if }|m|\in\mathbb{N}\textrm{ (i.e., \(m\) is finite)}\\
\CErr &amp; \text{otherwise}
\end{cases}
\end{align*}
</div>where
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_15">\begin{align*}
P' &amp; =\FSNAPSHOT{\CStore}P\\
m &amp; =\left\{ \FMATCH{P'}{\CPVal}{\CPr}\;|\;\CPVal\in\{\FINST{P'}v\;|\;v\in\ROUTES\},\FKNOWN{\CPVal}{\ROUTES_{i}}\not=\FKNOWN{\CPVal}{\ROUTES_{i}'}\right\} \\
\FKNOWN{\CPVal}{\ROUTES''} &amp; =1\textrm{, if some \(c\in\ROUTES''\) exists s.t. \(\FMATCH{\CPVal}c{\CInert}\) is defined; }0\text{, otherwise}\\
\FUNROLL\;\left\{ S,S',\dots\right\} &amp; =\CSeq S{\CSeq{S'}{\CSeq{\dots}{\CInert}}}
\end{align*}
</div></p><span class="halmos"></span></div><p id="x_5_3_0_0_18">The first step in <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>'s operation is to filter the set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> using metafunction <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span>, retaining only those assertions that match <span class="lyx-mathjax mathjax-inline">$P'$</span>.</p>
<div class="theorem-like numbered definition" id="x_5_3_0_0_21">
<p id="x_5_3_0_0_20"><span class="counter numbered definition"><span>5.24</span></span><a class="label-anchor" href="#def:mf:inst"></a><a name="def:mf:inst"></a>The partial function <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> is similar to <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span> (definition <a class="cross-reference" href="#def:mf:match">5.11</a>), in that it is defined only where the structure of the pattern matches the assertion; however, it is different in that it yields a <span class="lyx-mathjax mathjax-inline">$\TPVal$</span> as a result that includes detail only where it is <em>relevant</em> to the supplied pattern.
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_19">\begin{align*}
\FINSTName &amp; :\TPVal\times\TVal\rightharpoonup\TPVal\\
\FINST{\star}c &amp; =\star\\
\FINST bb &amp; =b\\
\FINST{(P,\dots)}{(v,\dots)} &amp; =(\FINST Pv,\dots)\\
\FINST{\CVar x}v &amp; =v
\end{align*}
</div>Where the pattern is <span class="lyx-mathjax mathjax-inline">$\star$</span>, meaning “any value is acceptable”, the precise value that was given is <em>obscured</em> in the output of <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span>. This causes irrelevant detail to be eliminated from consideration. By gathering together results from <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span>, <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> collapses together assertions from <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> that are identical up to “uninteresting” positions in the syntax of <span class="lyx-mathjax mathjax-inline">$P$</span>.</p><span class="halmos"></span></div><p id="x_5_3_0_0_22">Returning to the operation of <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>, the next step after filtering and partial transformation of the input set <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> is to take each <span class="lyx-mathjax mathjax-inline">$\CPVal\in\TPVal$</span> drawn from the set of <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> results and use the arguments <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span> given to <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> to decide whether <span class="lyx-mathjax mathjax-inline">$\CPVal$</span> is <em>novel</em> or not.</p><p id="x_5_3_0_0_23">The set <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> denotes the set of <em>known assertions</em> just prior to the arrival of the event that <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> is processing. The set <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span> denotes the result of updating <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> with the contents of the arriving event. That is, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> is “what the actor knew before”, and <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span> is “what the actor knows now.”</p><p id="x_5_3_0_0_24">If a particular <span class="lyx-mathjax mathjax-inline">$\CPVal$</span> corresponds to some assertion in <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span>, but not to any in <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span>, or conversely corresponds to some assertion in <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span> but none in <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span>, then the actor has learned something new, and the handler program <span class="lyx-mathjax mathjax-inline">$\CPr$</span> should be instantiated for this <span class="lyx-mathjax mathjax-inline">$\CPVal$</span>. However, if <span class="lyx-mathjax mathjax-inline">$\CPVal$</span> corresponds to some assertion in both or neither of <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span>, then nothing relevant has changed for the actor, and <span class="lyx-mathjax mathjax-inline">$\CPr$</span> should not be instantiated.</p>
<div class="theorem-like numbered example" id="x_5_3_0_0_33">
<p id="x_5_3_0_0_27"><span class="counter numbered example"><span>5.25</span></span><a class="label-anchor" href="#example:hll:roomnames"></a><a name="example:hll:roomnames"></a>Consider the presence-management portion of a chat service with multiple rooms. Assertions <span class="lyx-mathjax mathjax-inline">$(\mathit{userName},\mathtt{in},\mathit{roomName})$</span> denote presence of the named user in the named room. Rooms are said to “exist” only when inhabited by at least one user. Users joining the system are presented with a list of currently-extant rooms to choose from. A program for calculating this list might be written (assuming suitable data structures and primitive operations for sets):
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_26">\begin{align*}
&amp; \CField{\mathit{rooms}}{\emptyset}{}\\
&amp; \CFacet{\mathit{track}}{\begin{array}{ll}
\emptyset\\
(\DPlus &amp; \PrPlus)\\
(\DMinus &amp; \PrMinus)
\end{array}}
\end{align*}
</div></p>
<p id="x_5_3_0_0_32">Imagine now that two users, <tt>Alice</tt> and <tt>Bob</tt>, arrive and join the room <tt>Lobby</tt> <em>simultaneously</em>. This results in delivery of a patch event <span class="lyx-mathjax mathjax-inline">$\Delta=\CPatch{\ROUTES^{+}}{\emptyset}$</span> where <span class="lyx-mathjax mathjax-inline">$\ROUTES^{+}=\{(\mathtt{Alice},\mathtt{in},\mathtt{Lobby}),(\mathtt{Bob},\mathtt{in},\mathtt{Lobby})\}$</span> to our list-management actor. Ultimately, a call to <span class="lyx-mathjax mathjax-inline">$\FHANDLEName$</span> takes place:
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_28">\[
\FHANDLE{\emptyset}{\ROUTES^{+}}{\CStore}{\Delta}{((\DPlus,\PrPlus)\;(\DMinus,\PrMinus))}
\]
</div>For the <span class="lyx-mathjax mathjax-inline">$\KRetracted$</span> endpoint, <span class="lyx-mathjax mathjax-inline">$\FHANDLEName$</span> delegates to <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>:
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_29">\[
\FPROJECT{\emptyset}{\ROUTES^{+}}{\CStore}{\emptyset}{(\star,\mathtt{in},\CVar r)}{\PrMinus}
\]
</div>which yields <span class="lyx-mathjax mathjax-inline">$\CInert$</span>. The situation for the <span class="lyx-mathjax mathjax-inline">$\KAsserted$</span> endpoint is more interesting:
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_30">\[
\FPROJECT{\emptyset}{\ROUTES^{+}}{\CStore}{\ROUTES^{+}}{(\star,\mathtt{in},\CVar r)}{\PrPlus}
\]
</div>Because the pattern ignores the first component of matching triples, we have that
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_31">\[
\{(\star,\mathtt{in},\mathtt{Lobby})\}=\{\FINST{(\star,\mathtt{in},\CVar r)}v\;|\;v\in\ROUTES^{+}\}
\]
</div>Now, <span class="lyx-mathjax mathjax-inline">$\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\emptyset}\not=\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\ROUTES^{+}}$</span>, so <span class="lyx-mathjax mathjax-inline">$\FMATCHName$</span> is invoked and the actor processes the new knowledge of the room <tt>Lobby</tt>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_5_3_0_0_37">
<p id="x_5_3_0_0_36"><span class="counter numbered example"><span>5.26</span></span>Imagine now that <tt>Alice</tt> leaves the room, while <tt>Bob</tt> stays on. This results in a patch event <span class="lyx-mathjax mathjax-inline">$\Delta=\CPatch{\emptyset}{\ROUTES^{-}}$</span> where <span class="lyx-mathjax mathjax-inline">$\ROUTES^{-}=\{(\mathtt{Alice},\mathtt{in},\mathtt{Lobby})\}$</span>. At the time of the event, the total knowledge of the actor is <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}=\{(\mathtt{Alice},\mathtt{in},\mathtt{Lobby}),(\mathtt{Bob},\mathtt{in},\mathtt{Lobby})\}$</span>. Updating <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> with the patch yields <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'=\{(\mathtt{Bob},\mathtt{in},\mathtt{Lobby})\}$</span>. This time, the <span class="lyx-mathjax mathjax-inline">$\KAsserted$</span> endpoint has nothing to do, but the <span class="lyx-mathjax mathjax-inline">$\KRetracted$</span> endpoint triggers:
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_34">\[
\FPROJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\ROUTES^{-}}{(\star,\mathtt{in},\CVar r)}{\PrMinus}
\]
</div>Again, the pattern ignores the first component of matching triples in <span class="lyx-mathjax mathjax-inline">$\ROUTES^{-}$</span>, so
<div class="lyx-mathjax mathjax-display" id="x_5_3_0_0_35">\[
\{(\star,\mathtt{in},\mathtt{Lobby})\}=\{\FINST{(\star,\mathtt{in},\CVar r)}v\;|\;v\in\ROUTES^{-}\}
\]
</div>However, this time, <span class="lyx-mathjax mathjax-inline">$\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\ROUTES_{i}}=\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\ROUTES_{i}'}$</span> since in each case <em>some</em> assertion matching the pattern is contained in the assertion set. Therefore, this event does <em>not</em> lead to our list-tracking actor updating its <span class="lyx-mathjax mathjax-inline">$\mathit{rooms}$</span> field. This is what we want: <tt>Bob</tt> is still present in <tt>Lobby</tt>. Even though <tt>Alice</tt> left, the room itself has not vanished yet.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_5_3_0_0_39">
<p id="x_5_3_0_0_38"><span class="counter numbered example"><span>5.27</span></span>Finally, <tt>Bob</tt> leaves the room. The patch event is <span class="lyx-mathjax mathjax-inline">$\Delta=\CPatch{\emptyset}{\ROUTES^{-}}$</span> again but with <span class="lyx-mathjax mathjax-inline">$\ROUTES^{-}=\{(\mathtt{Bob},\mathtt{in},\mathtt{Lobby})\}$</span> this time. At the time of the event, <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}=\{(\mathtt{Bob},\mathtt{in},\mathtt{Lobby})\}$</span>, and so <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'=\emptyset$</span>. The <span class="lyx-mathjax mathjax-inline">$\KRetracted$</span> endpoint triggers again, as before; and, as before, <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> leaves us a single value for <span class="lyx-mathjax mathjax-inline">$\CPVal$</span>, namely <span class="lyx-mathjax mathjax-inline">$(\star,\mathtt{in},\mathtt{Lobby})$</span>. This time, however, <span class="lyx-mathjax mathjax-inline">$\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\ROUTES_{i}}\not=\FKNOWN{(\star,\mathtt{in},\mathtt{Lobby})}{\ROUTES_{i}'}$</span> because <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}'$</span> is empty, and so <span class="lyx-mathjax mathjax-inline">$\PrMinus$</span> is instantiated with <span class="lyx-mathjax mathjax-inline">$r=\mathtt{Lobby}$</span>, and the actor removes <tt>Lobby</tt> from <span class="lyx-mathjax mathjax-inline">$\mathit{rooms}$</span>.</p><span class="halmos"></span></div>
<h4 id="x_5_4_0_0_1"><a name="toc_5.4"></a><span class="counter section"><span>5.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:PLLAMBDA-DS-interface"></a><a name="sec:PLLAMBDA-DS-interface"></a>Interfacing <span class="small-caps">Syndicate/λ</span> to the dataspace model</span></h4><p id="x_5_4_0_0_2">Thus far, we have discussed the internal operation of <span class="small-caps">Syndicate/λ</span> actors, but have not addressed the question of their interface to the wider world. The path to an answer begins with the way <span class="small-caps">Syndicate/λ</span> constructs <span class="lyx-mathjax mathjax-inline">$\AActorName$</span> actions. To start an actor with store <span class="lyx-mathjax mathjax-inline">$\CStore$</span> and code <span class="lyx-mathjax mathjax-inline">$\CPr$</span>, <span class="small-caps">Syndicate/λ</span> issues the dataspace model action <span class="lyx-mathjax mathjax-inline">$\AActor{(\FSETUP\;(\CStore,\CPr))}{\emptyset}$</span>. This term appears in rules <span class="lyx-mathjax mathjax-inline">$\RSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\RDataspace$</span>, as well.</p>
<div class="theorem-like numbered definition" id="x_5_4_0_0_5">
<p id="x_5_4_0_0_4"><span class="counter numbered definition"><span>5.28</span></span>The function <span class="lyx-mathjax mathjax-inline">$\FSETUP$</span> produces a boot function of type <span class="lyx-mathjax mathjax-inline">$\TBoot$</span> (figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a>) which in turn describes the behavior function and initial state of a new actor. Every <span class="small-caps">Syndicate/λ</span> actor has behavior function <span class="lyx-mathjax mathjax-inline">$\FHLL$</span> and a state value drawn from set <span class="lyx-mathjax mathjax-inline">$\TMI$</span> (fig. <a class="cross-reference" href="#fig:PLLAMBDA-evaluation-syntax">18</a>).
<div class="lyx-mathjax mathjax-display" id="x_5_4_0_0_3">\begin{align*}
\FSETUP &amp; :\TStore\times\TPr\rightarrow\TBoot\\
\FSETUP\;(\CStore,\CPr) &amp; =\lambda().\begin{cases}
\INIT{\VECOF a,\CBehPack{\TMI}{\FHLL}{\Machine{\CStore'}{\emptyset}{\ROUTES_{o}}{\cdot}{\CS}}} &amp; \textrm{if }\CS\in\TTreeI\textrm{ and }S\not=\CInert\\
\EXIT{\VECOF a} &amp; \textrm{otherwise}
\end{cases}\\
\textrm{where } &amp; \Machine{\CStore}{\emptyset}{\emptyset}{\cdot}{\CPr}\longrightarrow^{*}\Machine{\CStore'}{\emptyset}{\ROUTES_{o}}{\VECOF a}S\not\longrightarrow
\end{align*}
</div>The initial state value contains information extracted from a use of the reduction relation, starting from <span class="lyx-mathjax mathjax-inline">$\CStore$</span> and <span class="lyx-mathjax mathjax-inline">$\CPr$</span>. If reduction stops in an exception-signaling configuration or fails to generate at least one running facet, <span class="lyx-mathjax mathjax-inline">$\FSETUP$</span> instructs the dataspace to terminate the nascent actor.</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_4_0_0_8">
<p id="x_5_4_0_0_7"><span class="counter numbered definition"><span>5.29</span></span><a class="label-anchor" href="#def:mf:pm"></a><a name="def:mf:pm"></a>The operator <span class="lyx-mathjax mathjax-inline">$\pm$</span> incorporates changes described by an incoming event to a previous record of the contents of the surrounding dataspace. When given a patch event, it updates the assertion set. By contrast, a message event is treated as an infinitesimally-brief assertion of its carried value, as discussed in section <a class="cross-reference" href="#sec:Messages-versus-Assertions">4.4</a>, and the assertion set remains unchanged.
<div class="lyx-mathjax mathjax-display" id="x_5_4_0_0_6">\begin{align*}
\cdot\pm\cdot &amp; :\TASet\times\TEvt\rightarrow\TASet\\
\ROUTES\pm\CPatch{\ROUTESADD}{\ROUTESDEL} &amp; =\ROUTES\cup\ROUTESADD-\ROUTESDEL\\
\ROUTES\pm\AMsg c &amp; =\ROUTES
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_4_0_0_11">
<p id="x_5_4_0_0_10"><span class="counter numbered definition"><span>5.30</span></span><a class="label-anchor" href="#def:mf:inject"></a><a name="def:mf:inject"></a>The <span class="lyx-mathjax mathjax-inline">$\FINJECTName$</span> function traverses a facet tree, using <span class="lyx-mathjax mathjax-inline">$\FHANDLEName$</span> to deliver an incoming event to the event-handler endpoints of every running facet.
<div class="lyx-mathjax mathjax-display" id="x_5_4_0_0_9">\begin{align*}
\FINJECTName &amp; :\TASet\times\TASet\times\TStore\times\TEvt\times\TTreeI\rightarrow\TTree\\
\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\CInert} &amp; =\CInert\\
\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{(\CSeq{\CSI}{T_{I}})} &amp; =\CSeq{\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\CSI}}{\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{T_{I}}}\\
\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\EFacet x{A\CEndpoint D{\CPr}\;\dots}{\CSI}} &amp; =\EFacet x{A\CEndpoint D{\CPr}\;\dots}{(\CSeq{\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\CSI}}{\FHANDLE{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\VECOF{(D,\CPr)}}})}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition" id="x_5_4_0_0_14">
<p id="x_5_4_0_0_13"><span class="counter numbered definition"><span>5.31</span></span><a class="label-anchor" href="#def:mf:interp"></a><a name="def:mf:interp"></a>The behavior function <span class="lyx-mathjax mathjax-inline">$\FHLL$</span> integrates an event arriving from the dataspace with the machine state held in the actor's private state value, reduces the result, and returns. If the actor terminates all its facets or if reduction yields an exception, <span class="lyx-mathjax mathjax-inline">$\FHLL$</span> instructs the dataspace to terminate the actor.
<div class="lyx-mathjax mathjax-display" id="x_5_4_0_0_12">\begin{align*}
\FHLL &amp; :\TBehF{\TMI}\\
\FHLL\;(\CEvt,\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\cdot}{\CSI}) &amp; =\begin{cases}
\CONTINUE{\FEMIT\;\VECOF a\ \Delta,\;\Machine{\CStore'}{\ROUTES_{i}'}{\ROUTES_{o}''}{\cdot}{\CS''}} &amp; \textrm{if }\CS''\in\TTreeI\textrm{ and }\CS''\not=\CInert\\
\EXIT{\VECOF a} &amp; \textrm{otherwise}
\end{cases}\\
\textrm{where } &amp; \ROUTES_{i}'=\ROUTES_{i}\pm\CEvt\\
&amp; \Machine{\CStore}{\ROUTES_{i}'}{\ROUTES_{o}}{\cdot}{\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\CEvt}{\CSI}}\longrightarrow^{*}\Machine{\CStore'}{\ROUTES_{i}'}{\ROUTES_{o}'}{\VECOF a}{\CS'}\not\longrightarrow\\
&amp; (S'',\ROUTES_{o}'',\Delta)=\begin{cases}
\left(S',\ROUTES_{o}'',\Delta\right) &amp; \text{if }(\ROUTES_{o}'',\Delta)=\FPATCH{\CStore'}{\ROUTES_{o}'}{\CS'}\\
\left(\CErr,\ROUTES_{o}',\CPatch{\emptyset}{\emptyset}\right) &amp; \text{otherwise }
\end{cases}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered remark" id="x_5_4_0_0_17">
<div class="footnote" id="fn_5_58"><span class="counter footnote-counter"><span>58</span></span>Ongoing collaborative work includes the development of a type system which ensures termination of <span class="small-caps">Syndicate/λ</span> programs, among other benefits <span class="citation citep">(<a class="citation" id="cite-107" href="#bib-Caldwell2017">Caldwell, Garnock-Jones and Felleisen 2017</a>)</span>.<span class="plain-layout-boundary"></span></div>
<p id="x_5_4_0_0_16"><span class="counter unnumbered remark"><span>5.31</span></span><span class="small-caps">Syndicate/λ</span> is an untyped language, and can express nontermination:
<div class="lyx-mathjax mathjax-display" id="x_5_4_0_0_15">\begin{align*}
&amp; \phantom{\longrightarrow\;}\CCall{\CProc{\CClause{\CVar x}{\left(\CCall xx\right)}}}{\CProc{\CClause{\CVar x}{\left(\CCall xx\right)}}}\\
&amp; \longrightarrow\CBind x{\CProc{\CClause{\CVar x}{\left(\CCall xx\right)}}}{\left(\CCall xx\right)}\\
&amp; \longrightarrow\CCall{\CProc{\CClause{\CVar x}{\left(\CCall xx\right)}}}{\CProc{\CClause{\CVar x}{\left(\CCall xx\right)}}}\\
&amp; \longrightarrow\cdots
\end{align*}
</div>Despite this, we have equipped it with the behavior function <span class="lyx-mathjax mathjax-inline">$\FHLL$</span> for interfacing it with the dataspace model, even though, strictly speaking, the dataspace model demands a terminating leaf actor language.<label class="footnote-number" for="fn_5_58">58</label> <span class="small-caps">Syndicate/λ</span> thus shares with its extant implementations the flaw that programmers must take care to ensure their programs terminate.</p><span class="halmos"></span></div>
<h4 id="x_5_5_0_0_1"><a name="toc_5.5"></a><span class="counter section"><span>5.5</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Well-formedness-and-errors"></a><a name="sec:Well-formedness-and-errors"></a>Well-formedness and Errors</span></h4>
<figure class="fullwidth" id="x_5_5_0_0_4"><a name="fig:Types,-type-environments"></a>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_2">\begin{align*}
\tau &amp; ::=\mathsf{var}\;|\;\mathsf{field}\;|\;\mathsf{facet}\\
\Gamma &amp; ::=\cdot\;|\;\Gamma,x:\tau
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_3">\begin{align*}
\mathit{prune}(\cdot) &amp; =\cdot &amp; \mathit{pruneUpTo}(x,\cdot) &amp; =\cdot\\
\mathit{prune}(\Gamma,x:\mathsf{var}) &amp; =\mathit{prune}(\Gamma),x:\mathsf{var} &amp; \mathit{pruneUpTo}(x,\;\Gamma,z:\mathsf{var}) &amp; =\mathit{pruneUpTo}(x,\;\Gamma),z:\mathsf{var}\\
\mathit{prune}(\Gamma,x:\mathsf{field}) &amp; =\mathit{prune}(\Gamma),x:\mathsf{field} &amp; \mathit{pruneUpTo}(x,\;\Gamma,z:\mathsf{field}) &amp; =\mathit{pruneUpTo}(x,\;\Gamma),z:\mathsf{field}\\
\mathit{prune}(\Gamma,x:\mathsf{facet}) &amp; =\mathit{prune}(\Gamma) &amp; \mathit{pruneUpTo}(x,\;\Gamma,z:\mathsf{facet}) &amp; =\mathit{pruneUpTo}(x,\;\Gamma)\qquad(x\not=z)\\
&amp; &amp; \mathit{pruneUpTo}(x,\;\Gamma,x:\mathsf{facet}) &amp; =\Gamma\\
\mathit{extend}(\Gamma,\{\VECOF x\}) &amp; =\Gamma\VECOF{,x:\mathsf{var}}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>23</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Types,-type-environments"></a>”Types”, type environments, and their metafunctions<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure class="fullwidth" id="x_5_5_0_0_31"><a name="fig:Well-formedness-judgements"></a>
<div class="lyx-mathjax mathjax-definitions" id="x_5_5_0_0_5">\(\newcommand{\J}[3]{#1\vdash#2\;#3}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_5_5_0_0_6">\(\newcommand{\Jok}[2]{\J{#1}{#2}{\mathsf{wf}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_5_5_0_0_7">\(\newcommand{\TBOX}[1]{\boxed{#1}}
\)</div>
<div class="boxed-box" id="x_5_5_0_0_13">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_8">\[
\TBOX{\Jok{\Gamma}{\CPr}}\qquad\frac{}{\Jok{\Gamma}{\CInert}}\qquad\frac{\Jok{\Gamma}{\CPr_{1}}\quad\Jok{\Gamma}{\CPr_{2}}}{\Jok{\Gamma}{\CSeq{\CPr_{1}}{\CPr_{2}}}}\qquad\frac{\Jok{\Gamma}{e_{1}}\quad\Jok{\Gamma}{e_{2}}}{\Jok{\Gamma}{\CCall{e_{1}}{e_{2}}}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_9">\[
\frac{\Jok{\Gamma}e\quad\Jok{\Gamma,x:\mathsf{var}}{\CPr}}{\Jok{\Gamma}{\CBind xe{\CPr}}}\qquad\frac{\Jok{\Gamma}e\quad\Jok{\Gamma,x:\mathsf{field}}{\CPr}}{\Jok{\Gamma}{\CField xe{\CPr}}}\qquad\frac{\Gamma(x)=\mathsf{field}\quad\Jok{\Gamma}e}{\Jok{\Gamma}{\CUpdate xe}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_10">\[
\frac{\Jok{\Gamma}e}{\Jok{\Gamma}{\CSend e}}\qquad\frac{\Jok{\mathit{prune}(\Gamma)}{\CPr}}{\Jok{\Gamma}{\CSpawn{\CPr}}}\qquad\frac{\Jok{\mathit{prune}(\Gamma)}{\CPr}}{\Jok{\Gamma}{\CDS{\CPr}}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_11">\[
\frac{\Gamma'=\Gamma,x:\mathsf{facet}\quad\Jok{\Gamma'}A\quad(\Jok{\Gamma'}D\wedge\Jok{\mathit{extend}(\Gamma',\FORMALS D)}{\CPr})\quad\cdots}{\Jok{\Gamma}{\CFacet x{A\CEndpoint D{\CPr}\;\dots}}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_12">\[
\frac{\Gamma(x)=\mathsf{facet}\quad\Jok{\mathit{pruneUpTo}(x,\Gamma)}{\CPr}}{\Jok{\Gamma}{\CStop x{\CPr}}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_16">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_14">\[
\TBOX{\Jok{\Gamma}e}\qquad\frac{}{\Jok{\Gamma}b}\qquad\frac{\Jok{\Gamma}e\quad\cdots}{\Jok{\Gamma}{(e,\dots)}}\qquad\frac{\Jok{\Gamma}e\quad\cdots}{\Jok{\Gamma}{p\;e\;\dots}}\qquad\frac{\Gamma(x)=\mathsf{var}\text{ or }\Gamma(x)=\mathsf{field}}{\Jok{\Gamma}x}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_15">\[
\frac{(\Jok{\Gamma}P\wedge\Jok{\mathit{extend}(\Gamma,\FORMALS P)}{\CPr})\quad\cdots}{\Jok{\Gamma}{\CProc{\CClause P{\CPr}\;\dots}}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_18">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_17">\[
\TBOX{\Jok{\Gamma}A}\qquad\frac{}{\Jok{\Gamma}{\emptyset}}\qquad\frac{\Jok{\Gamma}k\quad\Jok{\Gamma}A}{\Jok{\Gamma}{k\cup A}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_21">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_19">\[
\TBOX{\Jok{\Gamma}P}\qquad\frac{}{\Jok{\Gamma}{\star}}\qquad\frac{}{\Jok{\Gamma}b}\qquad\frac{\Jok{\Gamma}P\quad\cdots}{\Jok{\Gamma}{(P,\dots)}}\qquad\frac{\Jok{\Gamma}e\quad\cdots}{\Jok{\Gamma}{p\;e\;\dots}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_20">\[
\frac{\Gamma(x)=\mathsf{var}\text{ or }\Gamma(x)=\mathsf{field}}{\Jok{\Gamma}x}\qquad\frac{}{\Jok{\Gamma}{\CVar x}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_23">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_22">\[
\TBOX{\Jok{\Gamma}k}\qquad\text{(like \(\Jok{\Gamma}P\) but without the case for \(\CVar x\))}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_26">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_24">\[
\TBOX{\Jok{\Gamma}D}\qquad\frac{}{\Jok{\Gamma}{\DStart}}\qquad\frac{}{\Jok{\Gamma}{\DStop}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_25">\[
\frac{\Jok{\Gamma}P}{\Jok{\Gamma}{\DAsserted P}}\qquad\frac{\Jok{\Gamma}P}{\Jok{\Gamma}{\DRetracted P}}\qquad\frac{\Jok{\Gamma}P}{\Jok{\Gamma}{\DMessage P}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="boxed-box" id="x_5_5_0_0_30">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_27">\[
\TBOX{\Jok{\Gamma}S}\qquad\frac{\Jok{\Gamma}S}{\Jok{\Gamma}{\EKill S}}\qquad\frac{\Jok{\Gamma}{S_{1}}\quad\Jok{\Gamma}{S_{2}}}{\Jok{\Gamma}{\CSeq{S_{1}}{S_{2}}}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_28">\[
\frac{\Gamma'=\Gamma,x:\mathsf{facet}\quad\Jok{\Gamma'}A\quad(\Jok{\Gamma'}D\wedge\Jok{\mathit{extend}(\Gamma',\FORMALS D)}{\CPr})\quad\cdots\quad\Jok{\Gamma'}S}{\Jok{\Gamma}{\EFacet x{A\CEndpoint D{\CPr}\;\dots}S}}
\]
</div>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_29">\[
\frac{\Gamma'=\Gamma,x:\mathsf{facet}\quad\Jok{\Gamma'}A\quad\Jok{\Gamma'}D\quad\cdots\quad\Jok{\Gamma'}S}{\Jok{\Gamma}{\EFacetStop x{A\;D\;\dots}S}}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>24</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Well-formedness-judgements"></a>Well-formedness judgments<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_5_5_0_0_32">Reduction of <span class="small-caps">Syndicate/λ</span> programs can stop for many reasons. First of all, as in practically all interesting uses of <span class="lyx-mathjax mathjax-inline">$\lambda$</span>-calculus-like machinery, certain primitive operations may be partial functions. The classic example is arithmetic division, undefined at a zero denominator. This partiality manifests via <span class="lyx-mathjax mathjax-inline">$\FDELTALName$</span> and <span class="lyx-mathjax mathjax-inline">$\FDELTAName$</span> yielding no answer. In turn, this affects most of the other core metafunctions as well as the lion's share of the reduction rules.</p>
<div class="footnote" id="fn_5_59"><span class="counter footnote-counter"><span>59</span></span>As a matter of practicality, the <span class="small-caps">Syndicate</span> prototypes, both untyped, ignore this error, treating it as a no-op.<span class="plain-layout-boundary"></span></div><p id="x_5_5_0_0_34">More interesting are type errors. Certain errors, such as attempts to call a non-procedure or invoke an arithmetic primitive with a non-numeric value, may be prevented by developing a conventional type system <span class="citation citep">(<a class="citation" id="cite-108" href="#bib-Pierce2002">Pierce 2002</a>)</span>. Standard techniques also exist for enforcing exhaustive pattern-matching in procedures. Other errors are peculiar to <span class="small-caps">Syndicate/λ</span>. Figures <a class="cross-reference" href="#fig:Types,-type-environments">23</a> and <a class="cross-reference" href="#fig:Well-formedness-judgements">24</a> sketch a “well-formedness” judgment <span class="lyx-mathjax mathjax-inline">$\Jok{\Gamma}{\CPr}$</span> intended to catch three kinds of scope error: reference to an unbound variable, field, or facet; update to a name that is non-existent or not a field; and inappropriate use of a facet name in a <span class="lyx-mathjax mathjax-inline">$\DStop$</span> command. For an example of the latter, consider the two programs
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_33">\begin{align*}
&amp; \CFacet x{\emptyset\CEndpoint{\DStart}{\left(\CStop x{\left(\CStop x{\CInert}\right)}\right)}}\\
&amp; \CFacet x{\emptyset\CEndpoint{\DStart}{\CFacet y{\emptyset\CEndpoint{\DStart}{\left(\CStop x{\left(\CStop y{\CInert}\right)}\right)}}}}
\end{align*}
</div>In the first, the outer <span class="lyx-mathjax mathjax-inline">$\DStop$</span> terminates the facet <span class="lyx-mathjax mathjax-inline">$x$</span>, effectively replacing it with <span class="lyx-mathjax mathjax-inline">$\CStop x{\CInert}$</span>, which is stuck because it is not contained in an <span class="lyx-mathjax mathjax-inline">$\EFacet x{\cdots}{\hole}$</span> context. Similarly, in the second, the outer <span class="lyx-mathjax mathjax-inline">$\DStop$</span> terminates <span class="lyx-mathjax mathjax-inline">$x$</span> but also all its child facets, including <span class="lyx-mathjax mathjax-inline">$y$</span>. Ultimately, reduction becomes stuck at <span class="lyx-mathjax mathjax-inline">$\CStop y{\CInert}$</span> for lack of a <span class="lyx-mathjax mathjax-inline">$\EFacet y{\cdots}{\hole}$</span> context.<label class="footnote-number" for="fn_5_59">59</label> The well-formedness judgment aims to prevent such errors by removing all facet names from the type environment when checking the bodies of <span class="lyx-mathjax mathjax-inline">$\KSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\KDataspace$</span> commands and by removing facet names <em>at</em> or <em>below</em> a certain name when checking the continuation of each <span class="lyx-mathjax mathjax-inline">$\DStop$</span> command.</p>
<div class="footnote" id="fn_5_60"><span class="counter footnote-counter"><span>60</span></span>In section <a class="cross-reference" href="#sec:PLLAMBDA-derived-forms">5.7</a> we will introduce a more elegant approach to programming such services.<span class="plain-layout-boundary"></span></div><p id="x_5_5_0_0_36">Going beyond simple scope errors, <span class="small-caps">Syndicate/λ</span> programs can fail in two important ways relating to the assertions they exchange with peers via the shared dataspace. First, programs may make simple data-type errors in their assertions and subscriptions. For example, a particular protocol may require that peers interact by asserting and expressing interest in tuples <span class="lyx-mathjax mathjax-inline">$\left(\mathsf{square},n,m\right)$</span>, where <span class="lyx-mathjax mathjax-inline">$n,m\in\mathbb{N}$</span> and <span class="lyx-mathjax mathjax-inline">$m=n^{2}$</span>. It is an error, then, for a program to assert <span class="lyx-mathjax mathjax-inline">$\left(\mathsf{square},\mathtt{"a"},\mathtt{"aa"}\right)$</span>, to misspell <span class="lyx-mathjax mathjax-inline">$\mathsf{square}$</span>, or to assert a tuple such as <span class="lyx-mathjax mathjax-inline">$\left(\mathsf{square},10,1000\right)$</span>. Second, the metafunction <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> signals an exception when the set of relevant matches to a given pattern is infinite. Consider the following program, which computes and asserts squares in response to detected interest:<label class="footnote-number" for="fn_5_60">60</label>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_35">\[
\CSpawn{\CFacet{\mathit{squareServer}}{\emptyset\CEndpoint{\DAsserted{\Obs{\left(\mathsf{square},\CVar x,\star\right)}}}{\CFacet{\mathit{ans}}{\begin{array}{l}
\emptyset\cup\left(\mathsf{square},x,x\times x\right)\\
\left(\DRetracted{\Obs{\left(\mathsf{square},x,\star\right)}}\;\left(\CStop{\mathit{ans}}{\CInert}\right)\right)
\end{array}}}}}
\]
</div>All is well if some peer includes an endpoint <span class="lyx-mathjax mathjax-inline">$\left(\DAsserted{\left(\mathsf{square},3,\CVar{\mathit{nine}}\right)}\;\CPr\right)$</span>. But if a programmer makes an error, violating our square-computing protocol by attempting to enumerate all squares using an endpoint <span class="lyx-mathjax mathjax-inline">$\left(\DAsserted{\left(\mathsf{square},\star,\CVar v\right)}\;\CPr\right)$</span>, the resulting assertion of interest, <span class="lyx-mathjax mathjax-inline">$\Obs{\left(\mathsf{square},\star,\star\right)}$</span>, causes <span class="lyx-mathjax mathjax-inline">$\mathit{squareServer}$</span> to signal an exception as it <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>s that infinite set against the pattern <span class="lyx-mathjax mathjax-inline">$\Obs{\left(\mathsf{square},\CVar x,\star\right)}$</span>. Even though the client was at fault, the server is the component which crashes, since the server is the component relying upon the finiteness of a certain subspace of assertions. Ongoing research investigates type-system-based approaches to ruling out these forms of assertion-set-related error <span class="citation citep">(<a class="citation" id="cite-109" href="#bib-Caldwell2017">Caldwell, Garnock-Jones and Felleisen 2017</a>)</span>.</p>
<figure class="fullwidth" id="x_5_5_0_0_41"><a name="fig:int-ext-reduction"></a>
<p class="align-center" id="x_5_5_0_0_40">
<div class="frameless-box" id="x_5_5_0_0_39">
<div class="frameless-box" id="x_5_5_0_0_38">
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_37">\[
\begin{array}{cccccccc}
\Machine{\cdot}{\emptyset}{\emptyset}{\cdot}{\CPr} &amp; \longrightarrow^{*} &amp; \Machine{\CStore}{\emptyset}{\ROUTES_{o}}{\VECOF a}{\CSI} &amp; &amp; \Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}'}{\cdot}S &amp; \longrightarrow^{*} &amp; \Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}''}{\VECOF a'}{\CSI'}\\
&amp; &amp; \downarrow &amp; &amp; \uparrow &amp; &amp; \downarrow\\
&amp; &amp; \VECOF a\Delta,\Machine{\CStore}{\emptyset}{\ROUTES_{o}'}{\cdot}{\CSI} &amp; \dashrightarrow &amp; \epsilon,\Machine{\CStore}{\emptyset}{\ROUTES_{o}'}{\cdot}{\CSI} &amp; &amp; \VECOF a'\Delta',\Machine{\CStore'}{\ROUTES_{i}}{\ROUTES_{o}'''}{\cdot}{\CSI'} &amp; \dashrightarrow
\end{array}
\]
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>25</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:int-ext-reduction"></a>Internal reduction and external interaction<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="lyx-mathjax mathjax-definitions" id="x_5_5_0_0_42">\(\newcommand{\RInteract}{\RULENAME{interact}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_5_5_0_0_43">\(\newcommand{\IOREL}{\longrightarrow_{\mathsf{IO}}}
\)</div><p id="x_5_5_0_0_44">In order to use our well-formedness judgment to work towards a statement of overall soundness, we need to account for the way an actor transmits actions to its environment and receives events in reply. Figure <a class="cross-reference" href="#fig:int-ext-reduction">25</a> illustrates the alternation between the reduction relation explored in this chapter (upper row) and the exchange of information with an actor's surrounding dataspace, as explored in chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> (lower row). Setting aside cases where an actor exits because of a signaled exception or termination of all of its facets, we can abbreviate the excursions to the lower row of the figure as a pseudo-reduction-rule. From the actor's perspective, it is as if an oracle supplies a fresh (relevant) event <span class="lyx-mathjax mathjax-inline">$\epsilon$</span> at just the right moment, as the actor achieves an inert configuration:</p>
<div class="theorem-like numbered definition named" id="x_5_5_0_0_47">
<p id="x_5_5_0_0_46"><span class="counter numbered definition"><span>5.32</span></span><span class="lyx-argument">Pseudo-rule <span class="lyx-mathjax mathjax-inline">$\RInteract$</span><span class="plain-layout-boundary"></span></span>
<div class="lyx-mathjax mathjax-display" id="x_5_5_0_0_45">\begin{align*}
\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{\CSI} &amp; \longrightarrow\Machine{\CStore}{\ROUTES_{i}'}{\ROUTES_{o}'}{\cdot}{\FINJECT{\ROUTES_{i}}{\ROUTES_{i}'}{\CStore}{\epsilon}{\CSI}} &amp; &amp; (\RInteract)\\
\text{where } &amp; (\ROUTES_{o}',\Delta)=\FPATCH{\CStore}{\ROUTES_{o}}{\CSI}\\
&amp; \ROUTES_{i}'=\ROUTES_{i}\pm\epsilon
\end{align*}
</div>The uses of <span class="lyx-mathjax mathjax-inline">$\pm$</span> (definition <a class="cross-reference" href="#def:mf:pm">5.29</a>), <span class="lyx-mathjax mathjax-inline">$\FPATCHName$</span> (definition <a class="cross-reference" href="#def:mf:patch">5.7</a>) and <span class="lyx-mathjax mathjax-inline">$\FINJECTName$</span> (definition <a class="cross-reference" href="#def:mf:inject">5.30</a>) here show that the rule is effectively an “inlining” of <span class="lyx-mathjax mathjax-inline">$\FHLL$</span> (definition <a class="cross-reference" href="#def:mf:interp">5.31</a>).</p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_5_5_0_0_49">
<p id="x_5_5_0_0_48"><span class="counter numbered definition"><span>5.33</span></span><span class="lyx-argument">Extended reduction relation<span class="plain-layout-boundary"></span></span>We will write <span class="lyx-mathjax mathjax-inline">$\IOREL$</span> to mean the reduction relation <span class="lyx-mathjax mathjax-inline">$\longrightarrow$</span> extended with the <span class="lyx-mathjax mathjax-inline">$\RInteract$</span> pseudo-rule.</p><span class="halmos"></span></div>
<div class="theorem-like numbered conjecture" id="x_5_5_0_0_55">
<p id="x_5_5_0_0_54"><span class="counter numbered conjecture"><span>5.34</span></span><a class="label-anchor" href="#thm:PLLAMBDA-progress"></a><a name="thm:PLLAMBDA-progress"></a>If <span class="lyx-mathjax mathjax-inline">$\Jok{\cdot}{\CPr}$</span> and <span class="lyx-mathjax mathjax-inline">$\Machine{\cdot}{\emptyset}{\emptyset}{\cdot}{\CPr}\IOREL^{*}\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{\CS}$</span>, then either
<ol id="x_5_5_0_0_53"><li id="x_5_5_0_0_50"><span class="lyx-mathjax mathjax-inline">$S\in\TTreeI$</span>; or</li><li id="x_5_5_0_0_51"><span class="lyx-mathjax mathjax-inline">$S=E\left[\CErr\right]$</span> for some <span class="lyx-mathjax mathjax-inline">$E$</span>; or</li><li id="x_5_5_0_0_52"><span class="lyx-mathjax mathjax-inline">$\CS\notin\TTreeI$</span> and there exists a unique <span class="lyx-mathjax mathjax-inline">$M'$</span> such that <span class="lyx-mathjax mathjax-inline">$\Machine{\CStore}{\ROUTES_{i}}{\ROUTES_{o}}{\VECOF a}{\CS}\longrightarrow M'$</span>.</li></ol></p><span class="halmos"></span></div><p id="x_5_5_0_0_56">That is, at every step in a reduction chain, one of three conditions holds. First, the facet tree <span class="lyx-mathjax mathjax-inline">$\CS$</span> may be inert, in which case the actor terminates (<span class="lyx-mathjax mathjax-inline">$\CS=\CInert$</span>) or yields to its dataspace (<span class="lyx-mathjax mathjax-inline">$\CS\not=\CInert$</span>). Second, the facet tree may have a signaled exception as its selected redex, in which case it is terminated abruptly. Third, the tree may be neither inert nor in an exception state, in which case there is always another non-<span class="lyx-mathjax mathjax-inline">$\RInteract$</span> reduction step that may be taken.</p><p id="x_5_5_0_0_57">Examination of the reduction rules and metafunctions shows that <span class="lyx-mathjax mathjax-inline">$\CErr$</span> is signaled in two situations: when use of a primitive function yields no result, either due to intrinsic partiality or a type error, and when <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> encounters an infinite set of matching assertions. The well-formedness judgment rules out stuckness from misuse of names. If a program makes a simple data-type error in the content of an assertion, a number of consequences may unfold: the actor may simply sit inert forever, having failed to solicit events from peers; the actor may later receive events containing information it is not prepared to handle, resulting in an exception; or the actor may unintentionally trigger crashes in its peers, having supplied them with incoherent information.</p>
<h4 id="x_5_6_0_0_1"><a name="toc_5.6"></a><span class="counter section"><span>5.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Atomicity-and-isolation"></a><a name="sec:Atomicity-and-isolation"></a>Atomicity and isolation</span></h4><p id="x_5_6_0_0_2">With fields, we have introduced mutable state, opening the door to potential unpredictability. <span class="small-caps">Syndicate</span> mitigates this unpredictability by limiting the scope of mutability to individual actors. In addition, <span class="small-caps">Syndicate</span>'s facet model enforces three kinds of atomicity that together help the programmer in reasoning about field updates. First, an actor's behavior function is never preempted. As a result, events internal to an actor occur “infinitely quickly” from the perspective of the surrounding dataspace. This yields “synchrony” similar to that of languages such as Esterel <span class="citation citep">(<a class="citation" id="cite-110" href="#bib-Berry1992">Berry and Gonthier 1992</a>)</span> and Céu <span class="citation citep">(<a class="citation" id="cite-111" href="#bib-SantAnna2015">Sant'Anna, Ierusalimschy and Rodriguez 2015</a>)</span>. Second, each actor's private state is not only isolated but threaded through its behavior function in a linear fashion. This yields a natural boundary within which private state may safely be updated via mutation. Third, exceptions during event processing tear down the entire actor at once, including its private state. The same happens for deliberate termination of an actor. Termination is again instantaneous, and damaged private state cannot affect peers. This yields a form of “fail-stop” programming <span class="citation citep">(<a class="citation" id="cite-112" href="#bib-Schlichting1983">Schlichting and Schneider 1983</a>)</span>. Together, these forms of atomicity allow facet fields to be mutable, while events continue to be handled with sequential code, resolving all questions of internal consistency in the face of imperative updates.</p><p id="x_5_6_0_0_3">By coalescing adjacent patch actions with <span class="lyx-mathjax mathjax-inline">$\FEMIT$</span> during reduction, the <span class="small-caps">Syndicate/λ</span> semantics hides momentary “glitches” from observers. This allows actors to stop one facet and start another publishing the same assertion(s) without observers ever detecting the change, and without being forced to explicitly indicate that a smooth changeover is desired. Contrast this automatic ability to seamlessly delegate responsibility to a new facet with the equivalent ability for glitch-free handover of assertions to a new <em>actor</em>. In the latter case, programmers must explicitly make use of the “initial assertion set” field in the <span class="lyx-mathjax mathjax-inline">$\AActorName$</span> action describing the new actor as described in section <a class="cross-reference" href="#sec:Formal-DS-semantics">4.2</a>.</p>
<div class="footnote" id="fn_5_61"><span class="counter footnote-counter"><span>61</span></span>Both <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span> fastidiously maintain this phase distinction. However, as each integrates <span class="small-caps">Syndicate</span> features with an imperative host language, a loophole remains where field updates during computation of <em>pattern</em> expressions evaluated during planning may affect later stages. In practice, this seems not to occur.<span class="plain-layout-boundary"></span></div><p id="x_5_6_0_0_4">Events are dispatched to facets all at once: the metafunction <span class="lyx-mathjax mathjax-inline">$\FINJECTName$</span> matches each event against all endpoints of an actor's facets simultaneously. Actors thus make all decisions about which event-handlers are to run before any particular event-handler begins execution. This separation of a planning phase from an execution phase helps reduce dependence on order-of-operations (cf. section <a class="cross-reference" href="#sec:Syndicate-design-principles">2.6</a>) by ensuring no field updates can occur during planning.<label class="footnote-number" for="fn_5_61">61</label></p>
<h4 id="x_5_7_0_0_1"><a name="toc_5.7"></a><span class="counter section"><span>5.7</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:PLLAMBDA-derived-forms"></a><a name="sec:PLLAMBDA-derived-forms"></a>Derived forms: <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> and <span class="lyx-mathjax mathjax-inline">$\KSelect$</span></span></h4>
<div class="footnote" id="fn_5_62"><span class="counter footnote-counter"><span>62</span></span>The new forms <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> and <span class="lyx-mathjax mathjax-inline">$\KSelect$</span> can be compared to similar features of the fact space model, namely its <em>rule-based sub-language</em> and its <span class="normal"><em>reactive context-aware collections</em> <span class="citation citep">(<a class="citation" id="cite-113" href="#bib-Mostinckx2007">Mostinckx et al. 2007</a>; <a class="citation" id="cite-114" href="#bib-Mostinckx2008a">Mostinckx, Lombide Carreton and De Meuter 2008</a>)</span>.</span><span class="plain-layout-boundary"></span></div><p id="x_5_7_0_0_2">Examples <a class="cross-reference" href="#example:hll:demand-matcher">5.2</a> and <a class="cross-reference" href="#example:hll:roomnames">5.25</a> highlight two common idioms in <span class="small-caps">Syndicate</span> programming worthy of promotion to language feature. In example <a class="cross-reference" href="#example:hll:demand-matcher">5.2</a>, we saw a scenario in which appearance of an assertion led to creation of a resource—in this case, a separate actor—and disappearance of the same assertion led to the resource's release. In example <a class="cross-reference" href="#example:hll:roomnames">5.25</a>, we saw a scenario in which an actor aggregated specific information from a set of assertions into a local set data structure held in a field. <span class="small-caps">Syndicate</span> offers support for the former scenario via a new form of endpoint called <span class="lyx-mathjax mathjax-inline">$\KDuring$</span>, and support for the latter via a family of forms called <span class="lyx-mathjax mathjax-inline">$\KSelect$</span>.<label class="footnote-number" for="fn_5_62">62</label></p>
<h6 class="unnumbered" id="x_5_7_0_0_3"><a name="toc_5.7"></a><span class="heading-text paragraph">“<span class="lyx-mathjax mathjax-inline">$\KDuring$</span>” endpoints.</span></h6><p id="x_5_7_0_0_5">In a facet template <span class="lyx-mathjax mathjax-inline">$\CFacet x{A\CEndpoint D{\CPr}\;\dots}$</span>, each <span class="lyx-mathjax mathjax-inline">$(D\;\CPr)$</span> declares a single event-handling endpoint. We add <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> to the language by extending the class of event patterns:
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_4">\[
\textrm{Event patterns }D\in\TEPat:=\dots\;|\;\CDuring P
\]
</div></p><p id="x_5_7_0_0_8">We interpret the new construct in terms of existing syntax. An endpoint <span class="lyx-mathjax mathjax-inline">$(\CDuring P\;\CPr)$</span> is interpreted as if the programmer had written
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_6">\[
(\DAsserted P\;\CFacet x{\emptyset\CEndpoint{\DStart}{\CPr}\CEndpoint{\DRetracted{P'}}{\left(\CStop x{\CInert}\right)}})
\]
</div>where <span class="lyx-mathjax mathjax-inline">$x$</span> is fresh and <span class="lyx-mathjax mathjax-inline">$P'$</span> is <span class="lyx-mathjax mathjax-inline">$P$</span> with each binder <span class="lyx-mathjax mathjax-inline">$\CVar z$</span> rewritten to <span class="lyx-mathjax mathjax-inline">$z$</span>, a reference to the specific value bound at that position during the firing of the <span class="lyx-mathjax mathjax-inline">$\KAsserted$</span> event pattern. As an example, a program that asserts <span class="lyx-mathjax mathjax-inline">$\left(\mathtt{room},\mathit{roomName}\right)$</span> whenever some assertion <span class="lyx-mathjax mathjax-inline">$\left(\mathit{userName},\mathtt{in},\mathit{roomName}\right)$</span> exists in the dataspace might be written
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_7">\[
\CFacet{\mathit{listRooms}}{\emptyset\CEndpoint{\CDuring{\left(\star,\mathtt{in},\CVar r\right)}}{\CFacet{\mathit{entry}}{\emptyset\cup\left(\mathtt{room},r\right)}}}
\]
</div></p><p id="x_5_7_0_0_10">Concrete syntax aside, <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> is reminiscent of a form of <em>logical implication</em>
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_9">\[
\forall u,r.\left(u,\mathtt{in},r\right)\implies\left(\mathtt{room},r\right)
\]
</div>where assertions are interpreted as ground facts.</p><p id="x_5_7_0_0_12">A related derived event pattern, <span class="lyx-mathjax mathjax-inline">$\CDuringSpawn P$</span>, is able to help us with our demand-matcher example <a class="cross-reference" href="#example:hll:demand-matcher">5.2</a>, where <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> is not directly applicable. In contrast to <span class="lyx-mathjax mathjax-inline">$\CDuring P$</span>, the event pattern <span class="lyx-mathjax mathjax-inline">$\CDuringSpawn P$</span> does not create a facet but instead spawns an entire sibling actor to handle each assertion matching <span class="lyx-mathjax mathjax-inline">$P$</span>. The critical difference concerns failure. While a failure in a <span class="lyx-mathjax mathjax-inline">$\CDuring P$</span> endpoint tears down the current actor, a failure in a <span class="lyx-mathjax mathjax-inline">$\CDuringSpawn P$</span> endpoint terminates the separate actor, leaving its siblings and parent intact. Equipped with this new construct, we may reformulate example <a class="cross-reference" href="#example:hll:demand-matcher">5.2</a> as just
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_11">\[
\CSpawn{\CFacet{\mathit{demandMatcher}}{\emptyset\CEndpoint{\CDuringSpawn{\left(\mathtt{hello},\CVar x\right)}}{\dots}}}
\]
</div></p>
<h6 class="unnumbered" id="x_5_7_0_0_13"><a name="toc_5.7"></a><span class="heading-text paragraph">“<span class="lyx-mathjax mathjax-inline">$\KSelect$</span>” expressions.</span></h6><p id="x_5_7_0_0_15">The ability of facets to automatically update published assertions in response to changes in fields provides a unidirectional link from the local state of an actor to the shared state held in its dataspace. To establish a bidirectional link, we require a construct describing a local data structure to maintain in response to changes in observed assertions:
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_14">\[
\textrm{Programs }\CPr\in\TPr:=\dots\;|\;\CSelect Px{\{e\}}{\CPr}
\]
</div></p><p id="x_5_7_0_0_17">Like <span class="lyx-mathjax mathjax-inline">$\KDuring$</span>, the new <span class="lyx-mathjax mathjax-inline">$\KSelect$</span> construct is interpreted in terms of existing syntax. A program <span class="lyx-mathjax mathjax-inline">$\CSelect Px{\{e\}}{\CPr}$</span> is interpreted as if it were written
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_16">\begin{align*}
\CField x{\emptyset}{\left(\CSeq{\CFacet y{\begin{array}{ll}
\emptyset\\
(\DAsserted P &amp; (\CUpdate x{x\cup\{e\}}))\\
(\DRetracted P &amp; (\CUpdate x{x-\{e\}}))
\end{array}}}{\CPr}\right)}
\end{align*}
</div>where <span class="lyx-mathjax mathjax-inline">$y$</span> is fresh. The expression <span class="lyx-mathjax mathjax-inline">$e$</span> may refer to bindings introduced by pattern <span class="lyx-mathjax mathjax-inline">$P$</span>.</p><p id="x_5_7_0_0_19">The new construct allows us to recast example <a class="cross-reference" href="#example:hll:roomnames">5.25</a> as just
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_18">\[
\CSelect{\left(\star,\mathtt{in},\CVar r\right)}{\mathit{rooms}}{\{r\}}{\CInert}
\]
</div></p><p id="x_5_7_0_0_21">We may usefully generalize <span class="lyx-mathjax mathjax-inline">$\KSelect$</span> from maintenance of fields containing sets to fields containing hash-tables, counts of matching rows, sums of matching rows, and other forms of aggregate summary of a set of assertions:
<div class="lyx-mathjax mathjax-display" id="x_5_7_0_0_20">\begin{align*}
\textrm{Hash table: } &amp; \CSelect Px{\{e\mapsto e\}}{\CPr}\\
\textrm{Count: } &amp; \CSelect Px{\mathsf{count}\left(e\right)}{\CPr}\\
\textrm{Sum: } &amp; \CSelect Px{\mathsf{sum}\left(e\right)}{\CPr}\\
&amp; \vdots
\end{align*}
</div>The interpretations of these forms in terms of <span class="lyx-mathjax mathjax-inline">$\KAsserted$</span> and <span class="lyx-mathjax mathjax-inline">$\KRetracted$</span> endpoints should follow that of the form for sets, <em>mutatis mutandis</em>.</p><p id="x_5_7_0_0_22">Finally, while event-handling endpoints in <span class="small-caps">Syndicate/λ</span> allow a program to react to changes in shared assertions, there is no general symmetric ability in this minimal language for a program to directly react to changes in local fields. The only such reaction available is the automatic republication of assertions depending on field values. We will see in chapter <a class="cross-reference" href="#CHAP:TUTORIAL">6</a> a more general form of reaction to field changes that allows the programmer to express dataflow-style dependencies on and among fields. In our example here, this ability might find use in reacting to changes in the set-valued field <span class="lyx-mathjax mathjax-inline">$\mathit{rooms}$</span>, updating a graphical display of the room list.</p>
<h4 id="x_5_8_0_0_1"><a name="toc_5.8"></a><span class="counter section"><span>5.8</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:PLLAMBDA-properties"></a><a name="sec:PLLAMBDA-properties"></a>Properties</span></h4><p id="x_5_8_0_0_2">While <span class="small-caps">Syndicate/λ</span> is a mathematical fiction used to explain a language design, it highlights a number of properties that a <span class="small-caps">Syndicate</span> implementation must enjoy in order to satisfy a programmer's expectations. First of all, when extending a host language with <span class="small-caps">Syndicate</span> features, care must be taken to reconcile the host language's own soundness property with the invariants demanded by constructs such as facet creation and termination, field allocation, reference and update, and so on. If the errors discussed in section <a class="cross-reference" href="#sec:Well-formedness-and-errors">5.5</a> cannot be ruled out statically, they should be checked for dynamically. Of particular importance is the check for a finite result set in <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span>; experience writing <span class="small-caps">Syndicate</span> programs thus far suggests that programmer errors of this kind are not uncommon while designing a new protocol.</p><p id="x_5_8_0_0_3">Second, with the introduction of mutable state and sequencing comes the obligation to offer programmers a comprehensible model of order-of-evaluation and of visibility of intra-actor side-effects from the perspective of an actor's peers. As section <a class="cross-reference" href="#sec:Atomicity-and-isolation">5.6</a> explains, <span class="small-caps">Syndicate/λ</span> supports reasoning about various kinds of atomicity preserved during evaluation. Whichever guarantees about order-of-evaluation and transactionality a host language offers should be extended to <span class="small-caps">Syndicate</span> features so as to preserve these forms of atomicity.</p><p id="x_5_8_0_0_4">Finally, programmers rely on theorem <a class="cross-reference" href="#thm:conversational-sound-complete">4.35</a>'s promise of the conversational cooperation of the dataspace connecting a group of actors. In the same way, they rely on an extension of this promise to include <span class="small-caps">Syndicate/λ</span>'s endpoints. An implementation of <span class="small-caps">Syndicate</span> must ensure that the event-handling code associated with an endpoint runs <em>only</em> for relevant events, for <em>every</em> relevant event, and never <em>redundantly</em> for the same piece of knowledge. In particular, the notion of <em>necessity</em> developed in lemma <a class="cross-reference" href="#lem:mrscn-necessity">4.42</a> must be adapted in the setting of facets and endpoints to account for the way in which <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> elides irrelevant detail from incoming patch events.</p></p>
<h2 id="x_5_0_0_0_1"><a name="toc_III"></a><span class="counter part"><span>III</span></span><span class="heading-text part">Practice</span></h2>
<h3 class="unnumbered" id="x_5_0_0_0_2"><a name="toc_5"></a><span class="heading-text chapter">Overview</span></h3><p id="x_5_0_0_0_3">In order to evaluate the <span class="small-caps">Syndicate</span> design, we must be able to write programs using it. In order to write programs, we need three things: algorithms, data structures and implementation techniques allowing us to realize the language design; a concrete instance of integration of the design with a host language; and a number of illustrative examples.</p><p id="x_5_0_0_0_4">Chapter <a class="cross-reference" href="#CHAP:TUTORIAL">6</a> builds on the formal models of chapters <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> and <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a>, presenting <span class="small-caps">Syndicate/rkt</span>, an extension of the Racket programming language with <span class="small-caps">Syndicate</span> features.</p><p id="x_5_0_0_0_5">Chapter <a class="cross-reference" href="#CHAP:IMPLEMENTATION">7</a> then discusses general issues related to <span class="small-caps">Syndicate</span> implementation. First, it presents a new data structure, the <em>assertion trie</em>, important for efficient representation and manipulation of the sets of assertions ubiquitous to the dataspace model. Second, it turns to techniques for implementation and integration of <span class="small-caps">Syndicate</span> with a host language. Third, it describes some experimental tools for visualization and debugging of <span class="small-caps">Syndicate</span> programs.</p><p id="x_5_0_0_0_6">Finally, chapter <a class="cross-reference" href="#CHAP:IDIOMATIC-SYNDICATE">8</a> presents a large number of examples demonstrating <span class="small-caps">Syndicate</span> idioms.</p><p id="x_6_6_0_0_18">
<h3 id="x_6_0_0_0_1"><a name="toc_6"></a><span class="counter chapter"><span>6</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:TUTORIAL"></a><a name="CHAP:TUTORIAL"></a><span class="small-caps">Syndicate/rkt</span> Tutorial</span></h3>
<div class="footnote" id="fn_6_63"><span class="counter footnote-counter"><span>63</span></span>A brief overview of <span class="small-caps">Syndicate/js</span> is given in appendix <a class="cross-reference" href="#APPENDIX:PLJS-SYNTAX">A</a>.<span class="plain-layout-boundary"></span></div><p id="x_6_0_0_0_2">Now that we have explored the details of the <span class="small-caps">Syndicate</span> design in the abstract, it is time to apply the design ideas to a concrete language. This chapter introduces <span class="small-caps">Syndicate/rkt</span>, a language which extends Racket <span class="citation citep">(<a class="citation" id="cite-115" href="#bib-plt-tr1">Flatt and PLT 2010</a>)</span> with <span class="small-caps">Syndicate</span> language features. The aim of the chapter is to explain <span class="small-caps">Syndicate/rkt</span> in enough detail to allow the reader to appreciate the implementation ideas of chapter <a class="cross-reference" href="#CHAP:IMPLEMENTATION">7</a> and engage with the examples of chapter <a class="cross-reference" href="#CHAP:IDIOMATIC-SYNDICATE">8</a>.<label class="footnote-number" for="fn_6_63">63</label></p>
<h4 id="x_6_1_0_0_1"><a name="toc_6.1"></a><span class="counter section"><span>6.1</span></span><span class="heading-text section">Installation and brief example</span></h4>
<div class="footnote" id="fn_6_64"><span class="counter footnote-counter"><span>64</span></span>It is also available for download separately. See <a href="http://syndicate-lang.org/">http://syndicate-lang.org/</a> for details.<span class="plain-layout-boundary"></span></div><p id="x_6_1_0_0_2">The Racket-based <span class="small-caps">Syndicate</span> implementation is supplied as a Racket package.<label class="footnote-number" for="fn_6_64">64</label> After installing Racket itself, use the command-line or DrRacket-based interactive package management tool to install the <tt>syndicate</tt> package. For example, on a Unix-like system, run the command</p><p id="x_6_1_0_0_4">
<p class="align-center" id="x_6_1_0_0_3"><tt>raco pkg install syndicate</tt></p></p><p id="x_6_1_0_0_5">The implementation uses Racket's <tt>#lang</tt> facility to provide a custom language dialect with <span class="small-caps">Syndicate</span> language features built-in. A Racket source file starting with</p><p id="x_6_1_0_0_7">
<p class="align-center" id="x_6_1_0_0_6"><tt>#lang syndicate</tt></p></p><p id="x_6_1_0_0_8">declares itself to be a <span class="small-caps">Syndicate</span> program. Before we examine details of the language, a brief example demonstrates the big picture.</p>
<div class="theorem-like numbered example" id="x_6_1_0_0_18">
<p id="x_6_1_0_0_11"><span class="counter numbered example"><span>6.1</span></span><a class="label-anchor" href="#example:rkt-box-and-client"></a><a name="example:rkt-box-and-client"></a>Figure <a class="cross-reference" href="#fig:PLRACKET-box-and-client">26</a> shows a complete <span class="small-caps">Syndicate/rkt</span> program analogous to the box-and-client programs shown in previous chapters (examples <a class="cross-reference" href="#example:reference-cell">4.2</a> and <a class="cross-reference" href="#example:hll:reference-cell">5.1</a>). Typing it into a file and loading it into the DrRacket IDE or running it from the command line produces an unbounded stream of output that begins
<div class="verbatim" id="x_6_1_0_0_10">
<pre class="verbatim" id="x_6_1_0_0_9"><code>client: learned that box's value is now 0
box: taking on new-value 1
client: learned that box's value is now 1
box: taking on new-value 2
...
</code></pre></div></p>
<figure id="x_6_1_0_0_13"><a name="fig:PLRACKET-box-and-client"></a>
<pre class="listing" id="x_6_1_0_0_12"><code>#lang syndicate
(message-struct set-box (new-value))
(assertion-struct box-state (value))
(spawn (field [current-value 0])
(assert (box-state (current-value)))
(on (message (set-box $new-value))
(printf "box: taking on new-value ~v\n" new-value)
(current-value new-value)))
(spawn (on (asserted (box-state $v))
(printf "client: learned that box's value is now ~v\n" v)
(send! (set-box (+ v 1)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>26</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLRACKET-box-and-client"></a><span class="small-caps">Syndicate/rkt</span> box-and-client example<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p id="x_6_1_0_0_14"></p>
<p id="x_6_1_0_0_15">Line 1 declares that the module is written using <span class="small-caps">Syndicate/rkt</span>. Lines 2 and 3 declare Racket structures: <tt>set-box</tt> is declared as a structure to be used as a <em>message</em>, and <tt>box-state</tt> to be used as an <em>assertion</em>. Lines 48 and 911 start two actors together in the same dataspace. The first actor provides a mutable reference cell service, and the second accesses the cell.</p>
<p id="x_6_1_0_0_16">The cell initially contains the value <tt>0</tt> (line 4). It publishes its value as a <tt>box-state</tt> record in the shared dataspace (line 5). When it hears a <tt>set-box</tt> message (line 6), it prints a message to the console and updates its <tt>current-value</tt> field. This leads to automatic update of the assertion of line 5. The cell actor is the only party able to alter the <tt>box-state</tt> assertion in the dataspace: peers may submit <em>requests</em> to change the assertion, but cannot themselves change the value.</p>
<p id="x_6_1_0_0_17">The client actor begins its life waiting to hear about the assertion of <tt>box-state</tt> records. When it learns that a new record has been <tt>asserted</tt>, it prints a message to the console and sends a <tt>set-box</tt> message, which causes the cell to update itself, closing the loop.</p><span class="halmos"></span></div>
<h4 id="x_6_2_0_0_1"><a name="toc_6.2"></a><span class="counter section"><span>6.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:rkt:ground-and-drivers"></a><a name="sec:rkt:ground-and-drivers"></a>The structure of a running program: ground dataspace, driver actors</span></h4>
<figure id="x_6_2_0_0_3"><a name="fig:PLRACKET-Running-Structure"></a><img id="x_6_2_0_0_2" src="Figures/running-program-structure.svg"/><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>27</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLRACKET-Running-Structure"></a>The structure of a running <span class="small-caps">Syndicate/rkt</span> program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_6_2_0_0_4">Figure <a class="cross-reference" href="#fig:PLRACKET-Running-Structure">27</a> shows a schematic of a running <span class="small-caps">Syndicate/rkt</span> program. The main thread drives execution of the <span class="small-caps">Syndicate</span> world, dispatching events to actors and collecting and interpreting the resulting actions. All actors and dataspaces are gathered into a single, special <em>ground dataspace</em> which connects <span class="small-caps">Syndicate</span> to the “outside world” of plain Racket and hence, indirectly, to the underlying operating system.</p><p id="x_6_2_0_0_5">The figure shows actors relating to the program itself—some of which are running in a nested dataspace—as well as actors supplying services offered by library modules. Two <em>driver actors</em> are shown alongside these. The role of a driver actor in <span class="small-caps">Syndicate/rkt</span> is to offer an assertion- and message-based <span class="small-caps">Syndicate</span> perspective on some external service—the “hardware” to the actor's “driver”. Such driver actors call ordinary Racket library code, spawning Racket-level threads to perform long-lived, CPU-intensive or I/O-heavy tasks. Such threads may inject events—“hardware interrupts”—to the ground dataspace as if they were peers in some surrounding dataspace.</p><p id="x_6_2_0_0_6">For example, the <span class="small-caps">Syndicate/rkt</span> TCP driver interacts with peers via a protocol of assertions and messages describing TCP/IP sockets and transmitted and received TCP segments. When a socket is requested, the driver spawns not only a <span class="small-caps">Syndicate/rkt</span> actor but also a Racket-level thread. The thread uses Racket's native event libraries to wait for activity on the TCP/IP socket, and sends <span class="small-caps">Syndicate</span> messages describing received packets, errors, or changes in socket state. These messages are delivered to the <span class="small-caps">Syndicate/rkt</span> actor corresponding to the socket, which translates them and forwards them on to the driver's peers.</p><p id="x_6_2_0_0_7">Similarly, the Timer driver responds to <span class="small-caps">Syndicate/rkt</span> messages requesting its services by updating a priority-queue of pending timers which it shares with a Racket-level thread. The thread interfaces with Racket's native timer mechanisms. Each time it is signaled by Racket, it delivers an appropriate event to the ground dataspace, which is picked up by the Timer driver and forwarded to the original requesting actor.</p><p id="x_6_2_0_0_8"><span class="small-caps">Syndicate/rkt</span>'s driver model is inspired by Erlang's “ports” model for I/O <span class="citation citep">(<a class="citation" id="cite-116" href="#bib-OtpDesignPrinciples">Erlang/OTP Design Principles 2012</a>)</span>. The layer of indirection that a driver actor introduces between a user program and some external facility serves not only to isolate the external facility from user program failures and vice versa but also to separate concerns. The driver actor's responsibility is to implement the access protocol for the external service, no matter how complex and stateful, exposing its features in terms of a <span class="small-caps">Syndicate</span> protocol. The user program may thus concentrate on its own responsibilities, delegating management of the external service to the driver. If either party should fail, the other may gracefully shut down or take some compensating action.</p>
<h4 id="x_6_3_0_0_1"><a name="toc_6.3"></a><span class="counter section"><span>6.3</span></span><span class="heading-text section">Expressions, values, mutability, and data types</span></h4><p id="x_6_3_0_0_2">Expressions in <span class="small-caps">Syndicate/rkt</span> are ordinary Racket expressions. While <span class="small-caps">Syndicate/λ</span> maintains a strict separation between commands and expressions, <span class="small-caps">Syndicate/rkt</span> inherits Racket's expression-oriented approach. Racket's functions replace <span class="small-caps">Syndicate/λ</span>'s procedures. Ordinary Racket side-effects are available, and Racket's sequencing and order-of-evaluation are used unchanged.</p>
<div class="footnote" id="fn_6_65"><span class="counter footnote-counter"><span>65</span></span>In this, <span class="small-caps">Syndicate/rkt</span> follows many implementations of the actor model for previously-existing languages.<span class="plain-layout-boundary"></span></div><p id="x_6_3_0_0_3">Values in <span class="small-caps">Syndicate/rkt</span> are ordinary Racket values. This includes values used as assertions and message bodies. While <span class="small-caps">Syndicate/λ</span> forbids higher-order and mutable values in fields and assertions, <span class="small-caps">Syndicate/rkt</span> makes no such restriction, trusting the programmer to avoid problematic situations.<label class="footnote-number" for="fn_6_65">65</label> Actors may exchange mutable data or use Racket's mutable variables as required, though programmers are encouraged to design protocols that honor the spirit of <span class="small-caps">Syndicate</span> by eschewing mutable structures.</p><p id="x_6_3_0_0_4">The <span class="small-caps">Syndicate/rkt</span> implementation of the dataspace model must be able to inspect the elements of compound data types such as lists, vectors and records in order to fulfill its pattern-matching obligations. Racket's <tt>struct</tt> record facility defaults to creation of “opaque” records which cannot be inspected in the necessary way. While <span class="small-caps">Syndicate/rkt</span> does not forbid use of such <tt>struct</tt> definitions—in fact, their opacity is beneficial in certain circumstances (see section <a class="cross-reference" href="#subsec:Assertions">7.2.1</a>)—it is almost always better to use Racket's “prefab” structures, which allow the right kind of introspection.</p><p id="x_6_3_0_0_5">The special dataspace model observation constructor <span class="lyx-mathjax mathjax-inline">$\Obs{\cdot}$</span> and the cross-layer constructors <span class="lyx-mathjax mathjax-inline">$\Out{\cdot}$</span> and <span class="lyx-mathjax mathjax-inline">$\In{\cdot}$</span> are represented in <span class="small-caps">Syndicate/rkt</span> as instances of <tt>struct</tt>s named <tt>observe</tt>, <tt>outbound</tt> and <tt>inbound</tt>, respectively.</p><p id="x_6_3_0_0_8">
<p class="align-center" id="x_6_3_0_0_7">
<div class="tabular" id="x_6_3_0_0_6"><table class="tabular"><tr><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true leftline-true rightline-true usebox-none">Mathematical notation (figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a>)<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true leftline-true usebox-none"><span class="lyx-mathjax mathjax-inline">$\Obs c$</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true leftline-true usebox-none"><span class="lyx-mathjax mathjax-inline">$\Out c$</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true leftline-true rightline-true usebox-none"><span class="lyx-mathjax mathjax-inline">$\In c$</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none"><span class="small-caps">Syndicate/rkt</span> notation<span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><tt>(observe</tt> <span class="lyx-mathjax mathjax-inline">$c$</span><tt>)</tt><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><tt>(outbound</tt> <span class="lyx-mathjax mathjax-inline">$c$</span><tt>)</tt><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none"><tt>(inbound</tt> <span class="lyx-mathjax mathjax-inline">$c$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr></table></div></p></p>
<h4 id="x_6_4_0_0_1"><a name="toc_6.4"></a><span class="counter section"><span>6.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:rkt-Core-forms"></a><a name="sec:rkt-Core-forms"></a>Core forms</span></h4><p id="x_6_4_0_0_2">Each of the constructs of the formal model in chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> maps to a feature of the implementation. In some cases, a built-in Racket language feature corresponds well to a <span class="small-caps">Syndicate</span> feature, and is used directly. In others, a feature is provided by way of a Racket library exposing new functions and data structures. In yet others, new syntax is required, and Racket's <tt>syntax-parse</tt> facility <span class="citation citep">(<a class="citation" id="cite-117" href="#bib-Culpepper2010">Culpepper and Felleisen 2010</a>)</span> is brought to bear. Figure <a class="cross-reference" href="#fig:PLRACKET-syntax-core">28</a> summarizes the core forms added to Racket to yield <span class="small-caps">Syndicate/rkt</span>; figure <a class="cross-reference" href="#fig:Approximate-translation-from-PLL-to-rkt">29</a> sketches a rough rubric allowing interpretation of the syntax of <span class="small-caps">Syndicate/λ</span> in terms of <span class="small-caps">Syndicate/rkt</span>.</p>
<figure id="x_6_4_0_0_3"><a name="fig:PLRACKET-syntax-core"></a><pre class="wikihtml"> <span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">module-level-form</span></span> := ...
| (require/activate <span class="wikitex-italic">require-spec </span>...)
| <span class="wikitex-italic">struct-declaration</span>
| <span class="wikitex-italic">spawn</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">struct-declaration</span></span> := ...
| (message-struct <span class="wikitex-italic">name </span>(<span class="wikitex-italic">field </span>...))
| (assertion-struct <span class="wikitex-italic">name </span>(<span class="wikitex-italic">field </span>...))
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">spawn</span></span> := (spawn {#:name <span class="wikitex-italic">expr</span>} <span class="wikitex-italic">facet-setup-expr </span>...)
| (spawn* {#:name <span class="wikitex-italic">expr</span>} <span class="wikitex-italic">script-expr </span>...)
| (dataspace {#:name <span class="wikitex-italic">expr</span>} <span class="wikitex-italic">script-expr </span>...)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">facet-setup-expr</span></span> := <span class="wikitex-italic">expr</span>
| <span class="wikitex-italic">field-declaration</span>
| <span class="wikitex-italic">endpoint-expr</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">field-declaration</span></span> := (field [<span class="wikitex-italic">field-name </span><span class="wikitex-italic">initial-value</span>] ...)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">expr</span></span> := ...
| (current-facet-id)
| (observe <span class="wikitex-italic">expr</span>)
| (outbound <span class="wikitex-italic">expr</span>)
| (inbound <span class="wikitex-italic">expr</span>)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">script-expr</span></span> := <span class="wikitex-italic">expr</span>
| (react <span class="wikitex-italic">facet-setup-expr </span>...)
| (stop-facet <span class="wikitex-italic">expr </span><span class="wikitex-italic">script-expr </span>...)
| (stop-current-facet)
| <span class="wikitex-italic">field-declaration</span>
| <span class="wikitex-italic">spawn</span>
| (send! <span class="wikitex-italic">script-expr</span>)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">endpoint-expr</span></span> := (assert {#:when <span class="wikitex-italic">test-expr</span>} <span class="wikitex-italic">pattern</span>)
| (on-start <span class="wikitex-italic">script-expr </span>...)
| (on-stop <span class="wikitex-italic">script-expr </span>...)
| (on {#:when <span class="wikitex-italic">test-expr</span>} <span class="wikitex-italic">event-pattern </span><span class="wikitex-italic">script-expr </span>...)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">event-pattern</span></span> := (asserted <span class="wikitex-italic">pattern</span>)
| (retracted <span class="wikitex-italic">pattern</span>)
| (message <span class="wikitex-italic">pattern</span>)
</pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>28</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLRACKET-syntax-core"></a>Core <span class="small-caps">Syndicate/rkt</span> forms<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_6_4_0_0_6"><a name="fig:Approximate-translation-from-PLL-to-rkt"></a>
<div class="tabular" id="x_6_4_0_0_5"><table class="tabular"><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CInert$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(void)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CSeq{\CPr_{1}}{\CSeq{\cdots}{\CPr_{n}}}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(begin</tt> <span class="lyx-mathjax mathjax-inline">$\CPr_{1}$</span> <span class="lyx-mathjax mathjax-inline">$\cdots$</span> <span class="lyx-mathjax mathjax-inline">$\CPr_{n}$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CCall{e_{1}}{e_{2}}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(</tt><span class="lyx-mathjax mathjax-inline">$e_{1}$</span> <span class="lyx-mathjax mathjax-inline">$e_{2}$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CBind xe{\CPr}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(let ((</tt><span class="lyx-mathjax mathjax-inline">$x$</span> <span class="lyx-mathjax mathjax-inline">$e$</span><tt>))</tt> <span class="lyx-mathjax mathjax-inline">$\CPr$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CField xe{\CPr}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(begin (field [</tt><span class="lyx-mathjax mathjax-inline">$x$</span> <span class="lyx-mathjax mathjax-inline">$e$</span><tt>])</tt> <span class="lyx-mathjax mathjax-inline">$\CPr$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CUpdate xe$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(</tt><span class="lyx-mathjax mathjax-inline">$x$</span> <span class="lyx-mathjax mathjax-inline">$e$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CSend e$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(send!</tt> <span class="lyx-mathjax mathjax-inline">$e$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CSpawn{\CPr}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(spawn*</tt> <span class="lyx-mathjax mathjax-inline">$\CPr$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CDS{\CPr}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(dataspace</tt> <span class="lyx-mathjax mathjax-inline">$CPr$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CFacet x{A\CEndpoint{\DStart}{\CPr_{\DStart}}\CEndpoint{\DStop}{\CPr_{\DStop}}\CEndpoint D{\CPr}\;\cdots}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none">
<div class="frameless-box" id="x_6_4_0_0_4"><tt>(react (define</tt> <span class="lyx-mathjax mathjax-inline">$x$</span> <tt>(current-facet-id))</tt><span class="plain-layout-boundary"></span><tt>       (assert</tt> <span class="lyx-mathjax mathjax-inline">$A$</span>)<span class="plain-layout-boundary"></span><tt>       (on-start</tt> <span class="lyx-mathjax mathjax-inline">$\CPr_{\DStart}$</span><tt>)</tt><span class="plain-layout-boundary"></span><tt>       (on-stop</tt> <span class="lyx-mathjax mathjax-inline">$\CPr_{\DStop}$</span><tt>)</tt><span class="plain-layout-boundary"></span><tt>       (on</tt> <span class="lyx-mathjax mathjax-inline">$D$</span> <span class="lyx-mathjax mathjax-inline">$\CPr$</span><tt>) <span class="lyx-mathjax mathjax-inline">$\cdots$</span>)</tt><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-right valignment-top width-0pt alignment-right valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\CStop x{\CPr}$</span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt alignment-left valignment-top usebox-none"><tt>(stop-facet</tt> <span class="lyx-mathjax mathjax-inline">$x$</span> <span class="lyx-mathjax mathjax-inline">$\CPr$</span><tt>)</tt><span class="plain-layout-boundary"></span></td></tr></table></div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>29</span></span><span class="figcaption-text"><span class="lyx-argument">Approximate translation from <span class="small-caps">Syndicate/λ</span> to <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Approximate-translation-from-PLL-to-rkt"></a>Approximate translation from <span class="small-caps">Syndicate/λ</span> syntax to <span class="small-caps">Syndicate/rkt</span> syntax<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h6 class="unnumbered" id="x_6_4_0_0_7"><a name="toc_6.4"></a><span class="heading-text paragraph">Programs and modules.</span></h6><p id="x_6_4_0_0_8">A module written in the <tt>syndicate</tt> dialect not only provides constants, functions, and structure type definitions to its clients, as ordinary Racket modules do, but also offers <em>services</em> in the form of actors to be started when the module is <em>activated</em>. Thus, each module does double duty, serving as either or both of a unit of program composition and a unit of <em>system</em> composition. In order to start a <span class="small-caps">Syndicate/rkt</span> program running, a user specifies a module to serve as the entry point. That module is activated in a fresh, empty dataspace, along with any actors created during activation of service modules it depends upon.</p><p id="x_6_4_0_0_9">The nonterminal <em>module-level-form </em>in figure <a class="cross-reference" href="#fig:PLRACKET-syntax-core">28</a> specifies the <span class="small-caps">Syndicate/rkt</span> extensions to Racket's module-level language. A client may <tt>require</tt> a module, as usual, or may require and activate it by using the <tt>require/activate</tt> form. Activation is idempotent within a given program: a particular module's services are only started once.</p>
<div class="footnote" id="fn_6_66"><span class="counter footnote-counter"><span>66</span></span>The current implementation does not enforce the distinction: in fact, the definitions of <tt>message-struct</tt> and <tt>assertion-struct</tt> are identical. They are both equivalent to <tt>(struct</tt><em> name </em><tt>(</tt><em>field ...</em><tt>)</tt> <tt>#:prefab)</tt>.<span class="plain-layout-boundary"></span></div><p id="x_6_4_0_0_10">The module-level language is also extended with two new structure-definition forms (nonterminal <em>struct-declaration</em>), <tt>message-struct</tt> and <tt>assertion-struct</tt>. The former is intended to declare structures for use in <em>messages</em>, while the latter declares structures for <em>assertions</em>.<label class="footnote-number" for="fn_6_66">66</label><em> </em>Each is a thin veneer over Racket's “prefab” structure definition facility.</p>
<h6 class="unnumbered" id="x_6_4_0_0_11"><a name="toc_6.4"></a><span class="heading-text paragraph">Abstraction facilities.</span></h6><p id="x_6_4_0_0_12">In order to remain minimal, <span class="small-caps">Syndicate/λ</span> includes little in the way of abstraction facilities. However, in <span class="small-caps">Syndicate/rkt</span>, we wish to permit abstraction over field declaration, assertion- and event-handling endpoint installation, and facet creation and tear-down, as well as the usual forms of abstraction common to Racket programming. Therefore, we make abstraction facilities like <tt>define</tt>, <tt>let</tt>, <tt>define-syntax</tt> and <tt>let-syntax</tt> available throughout the <span class="small-caps">Syndicate/rkt</span> language. </p><p id="x_6_4_0_0_13">However, not all <span class="small-caps">Syndicate</span> constructs make sense in all contexts. For example, it is nonsensical to attempt to declare an endpoint outside a facet. <span class="small-caps">Syndicate/λ</span> includes special syntactic positions for declaration of endpoints, keeping them clearly (and statically) distinct from positions for specifying commands. This approach conflicts with the desire to reuse Racket's abstraction facilities in all such syntactic positions. <span class="small-caps">Syndicate/rkt</span> therefore brings most <span class="small-caps">Syndicate</span> constructs into a single syntactic class—that of expressions—and relies on a dynamic mechanism to rule out inappropriate usage of <span class="small-caps">Syndicate</span> constructs. An internal flag keeps track of whether the program is in “script” or “facet setup” context.</p>
<div class="footnote" id="fn_6_67"><span class="counter footnote-counter"><span>67</span></span>The script/facet distinction is reminiscent of, and partially inspired by, the “step/process” distinction of Hancock's FLOGO II language <span class="citation citep">(<a class="citation" id="cite-118" href="#bib-Hancock2003">Hancock 2003</a> <span class="citation-after">chapter 5</span>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_6_4_0_0_14">Figure <a class="cross-reference" href="#fig:PLRACKET-syntax-core">28</a> reflects this dynamic context in its use of nonterminals <em>script-expr</em> and <em>facet-setup-expr</em>. Script expressions may only be used within event-handlers and in ordinary straight-line Racket code. They include expressions which perform side effects such as spawning other actors or sending messages. Facet setup expressions may only be used in contexts where a new facet is being configured. They include expressions which construct both assertion and event-handling endpoints.<label class="footnote-number" for="fn_6_67">67</label></p>
<h6 class="unnumbered" id="x_6_4_0_0_15"><a name="toc_6.4"></a><span class="heading-text paragraph">Sending messages.</span></h6><p id="x_6_4_0_0_16">The <tt>send!</tt> form broadcasts its argument to peers via the dataspace. That is, a message action is enqueued for transmission to the dataspace when the actor's behavior function eventually returns. Message sending, like all other actions, is thus <em>asynchronous</em> from the perspective of the <span class="small-caps">Syndicate/rkt</span> programmer.</p>
<h6 class="unnumbered" id="x_6_4_0_0_17"><a name="toc_6.4"></a><span class="heading-text paragraph">Spawning actors and dataspaces.</span></h6><p id="x_6_4_0_0_18">The nonterminal <em>spawn</em> in figure <a class="cross-reference" href="#fig:PLRACKET-syntax-core">28</a> is available not only at the module level but also anywhere a <em>script-expr</em> is permitted within a running actor. The three forms <tt>spawn</tt>, <tt>spawn*</tt>, and <tt>dataspace</tt> correspond to the <span class="small-caps">Syndicate/λ</span> commands <span class="lyx-mathjax mathjax-inline">$\KSpawn$</span> and <span class="lyx-mathjax mathjax-inline">$\KDataspace$</span>. Each of the first two, like <span class="small-caps">Syndicate/λ</span>'s <span class="lyx-mathjax mathjax-inline">$\KSpawn$</span>, constructs a sibling actor in the current dataspace; the third, a nested dataspace whose initial actor runs the <em>script-expr</em>s specified. The two variations <tt>spawn</tt> and <tt>spawn*</tt> relate to each other as follows:</p><p id="x_6_4_0_0_20">
<p class="align-center" id="x_6_4_0_0_19"><tt>(spawn</tt> <em>facet-setup-expr</em> ...<tt>) </tt><span class="lyx-mathjax mathjax-inline">$\triangleq$</span><tt> (spawn* (react</tt><em> facet-setup-expr </em>...<tt>))</tt></p></p><p id="x_6_4_0_0_21">Initially, <span class="small-caps">Syndicate/rkt</span> included only <tt>spawn*</tt> (written, at the time, “<tt>spawn</tt>”); a survey of programs showed that the overwhelming majority of uses of <tt>spawn*</tt> were of the form that the current <tt>spawn</tt> abbreviates, namely an actor with a single initial facet.</p><p id="x_6_4_0_0_22">If a <tt>spawn</tt>, <tt>spawn*</tt>, or <tt>dataspace</tt> is supplied with a <tt>#:name</tt> clause, the result of the corresponding <em>expr</em> is attached to the created actor as its name for debugging and tracing purposes. The name is never made available to peers via assertions or messages in the dataspace.</p>
<h6 class="unnumbered" id="x_6_4_0_0_23"><a name="toc_6.4"></a><span class="heading-text paragraph">Facet creation and termination.</span></h6><p id="x_6_4_0_0_24">The <tt>react</tt> form causes addition of a new facet to the currently-running actor, nested beneath the currently-active facet, or as the root of the actor's facet tree if used immediately within <tt>spawn*</tt>. The body of the <tt>react</tt> form is in “facet setup” context, and declares the new facet's endpoints. Unlike in <span class="small-caps">Syndicate/λ</span>, the facet's name is not manifest in the syntax. Instead, a facet may retrieve its system-generated name with a call to the procedure <tt>current-facet-id</tt>. Facet IDs may be freely stored in variables, passed as procedure arguments, and so on.</p><p id="x_6_4_0_0_25">A facet ID must be supplied as the first argument to a <tt>stop-facet</tt> form, which is the <span class="small-caps">Syndicate/rkt</span> analogue of <span class="small-caps">Syndicate/λ</span>'s <span class="lyx-mathjax mathjax-inline">$\DStop$</span>. For example, the following program starts an actor whose root facet immediately terminates itself:</p><p id="x_6_4_0_0_27">
<p class="align-center" id="x_6_4_0_0_26"><tt>(spawn (on-start (stop-facet (current-facet-id))))</tt></p></p><p id="x_6_4_0_0_29">The program is analogous to the <span class="small-caps">Syndicate/λ</span> program
<div class="lyx-mathjax mathjax-display" id="x_6_4_0_0_28">\[
\CSpawn{\CFacet{\mathit{root}}{\emptyset\CEndpoint{\DStart}{\left(\CStop{\mathit{root}}{\CInert}\right)}}}
\]
</div>The shortcut</p><p id="x_6_4_0_0_31">
<p class="align-center" id="x_6_4_0_0_30"><tt>(stop-current-facet</tt> <em>script-expr ...</em><tt>) <span class="lyx-mathjax mathjax-inline">$\triangleq$</span> (stop-facet (current-facet-id)</tt> <em>script-expr ...</em><tt>)</tt></p></p><p id="x_6_4_0_0_32">captures a common form of use of <tt>stop-facet</tt> and <tt>current-facet-id</tt>.</p><p id="x_6_4_0_0_33">A <tt>stop-facet</tt> form includes an optional sequence of <em>script-expr</em>s. These are executed <em>outside</em> the stopping facet, once its subscriptions and assertions have been completely withdrawn, in the context of the facet's own containing facet (if any). That is, an expression such as</p><p id="x_6_4_0_0_35">
<p class="align-center" id="x_6_4_0_0_34"><tt>(react (on (message 'x) (stop-facet (current-facet-id) (react </tt><em>...</em><tt>))))</tt></p></p><p id="x_6_4_0_0_36">(1) creates a facet, which upon receipt of a message <tt>'x</tt> (2) terminates itself, and (3) effectively <em>replaces</em> itself with another facet, whose body is shown as an ellipsis. Compare to</p><p id="x_6_4_0_0_38">
<p class="align-center" id="x_6_4_0_0_37"><tt>(react (on (message 'x) (react </tt><em>...</em><tt>)))</tt></p></p><p id="x_6_4_0_0_39">which upon receipt of each <tt>'x</tt> creates an additional, nested subfacet; and</p><p id="x_6_4_0_0_41">
<p class="align-center" id="x_6_4_0_0_40"><tt>(react (on (message 'x) (stop-current-facet) (react </tt><em>...</em><tt>)))</tt></p></p><p id="x_6_4_0_0_42">which not only terminates itself when it receives an <tt>'x</tt> message but also creates a nested subfacet, which is shortly thereafter destroyed as a consequence of the termination of its parent.</p>
<h6 class="unnumbered" id="x_6_4_0_0_43"><a name="toc_6.4"></a><span class="heading-text paragraph">Field declaration, access and update.</span></h6><p id="x_6_4_0_0_44"><span class="small-caps">Syndicate/rkt</span> allows declaration of fields in both “script” and “facet setup” contexts. The <tt>field</tt> form borrows its syntactic shape from Racket's support for object-oriented programming; it acts as a <tt>define</tt> of the supplied <em>field-name</em>s, initializing each with its <em>initial-value</em>.</p><p id="x_6_4_0_0_45">Fields are represented as <em>procedures</em> in <span class="small-caps">Syndicate/rkt</span>. When called with no arguments, a field procedure returns the field's current value; when called with a single argument, the field procedure updates the field's value to the given argument value.</p>
<h6 class="unnumbered" id="x_6_4_0_0_46"><a name="toc_6.4"></a><span class="heading-text paragraph">Endpoint declaration.</span></h6><p id="x_6_4_0_0_47">In facet setup context, the forms <tt>assert</tt>, <tt>on-start</tt>, <tt>on-stop</tt>, and <tt>on</tt> are available for creation of assertion and event-handling endpoints.</p><p id="x_6_4_0_0_48">The <tt>assert</tt> form allows a facet to place assertions into the shared dataspace. For example, given the following structure definitions,</p>
<div class="verbatim" id="x_6_4_0_0_50">
<pre class="verbatim" id="x_6_4_0_0_49"><code>(assertion-struct user-present (user-name))
(message-struct say-to (user-name utterance))
</code></pre></div><p id="x_6_4_0_0_51">the endpoint</p><p id="x_6_4_0_0_53">
<p class="align-center" id="x_6_4_0_0_52"><tt>(assert (user-present 'Alice))</tt></p></p><p id="x_6_4_0_0_54">asserts a <tt>user-present</tt> record, keeping it there until the endpoint's facet is terminated.</p><p id="x_6_4_0_0_55">The <tt>on</tt> form allows facets to react to events described by the <em>event-pattern</em> nonterminal. Each possibility corresponds to the analogous event-pattern in <span class="small-caps">Syndicate/λ</span>. For example,</p>
<div class="verbatim" id="x_6_4_0_0_57">
<pre class="verbatim" id="x_6_4_0_0_56"><code>(on (asserted (user-present $name))
(send! (say-to name "Hello!")))
</code></pre></div><p id="x_6_4_0_0_58">reacts to the assertion of <tt>(user-present 'Alice)</tt> with a message, <tt>(say-to 'Alice "Hello!")</tt>.</p><p id="x_6_4_0_0_59">Both <tt>assert</tt> and <tt>on</tt> forms take a <em>pattern</em>, within which most Racket expressions are permitted. Use of the discard operator (<tt>_</tt>) in a pattern corresponds to <span class="small-caps">Syndicate/λ</span>'s <span class="lyx-mathjax mathjax-inline">$\star$</span>; that is, to a <em>wildcard</em> denoting the universe of assertion values. In an <tt>on</tt> form, it acts to accept and ignore arbitrary structure in matched assertions or messages. Variables <tt>x</tt> introduced via binders <tt>$x</tt> embedded in an <tt>on</tt> form's pattern are available in the form's <em>script-expr</em>s; it is an error to include a binder in a pattern in an <tt>assert</tt> form. Patterns may make reference to current field values, and any fields accessed are called the endpoint's <em>dependent fields</em>.</p><p id="x_6_4_0_0_60">A pattern is evaluated to yield a set of assertions, both initially and every time a dependent field is updated. For <tt>on</tt> forms, an <tt>observe</tt> structure constructor is added to each assertion in the denoted set. This process of assertion-set extraction is analogous to <span class="small-caps">Syndicate/λ</span>'s use of the <span class="lyx-mathjax mathjax-inline">$\FASSERTIONSName$</span> metafunction of figure <a class="cross-reference" href="#fig:mf:assertions">19</a>.</p><p id="x_6_4_0_0_61">Whenever an endpoint's pattern is re-evaluated, the resulting assertions are placed in the surrounding dataspace by way of a state-change notification action. However, if a <tt>#:when</tt> clause is present in the <tt>assert</tt> or <tt>on</tt> form, the corresponding <em>test-expr</em> is evaluated just before actually issuing the action. If <em>test-expr</em> yields a false value, no action is produced. This allows <em>conditional</em> assertion and <em>conditional</em> subscription. In particular, a <tt>#:when</tt> clause <em>test-expr</em> may depend on field values; if it does, the fields are considered part of the dependent fields.</p><p id="x_6_4_0_0_62">The <tt>on-start</tt> and <tt>on-stop</tt> forms introduce facet-startup and -shutdown event handlers. The former are executed once the block of <em>facet-setup-expr</em>s has finished configuring the endpoints of the facet and after the facet's new assertions (including its subscriptions) have been sent to the surrounding dataspace. The latter are executed just prior to withdrawal of the facet's endpoint subscriptions during the facet shutdown process.</p><p id="x_6_4_0_0_63">An <tt>on-start</tt> form may be used to send a message in a context where a corresponding reply-listener is guaranteed to be active and listening; for example, in</p>
<div class="verbatim" id="x_6_4_0_0_65">
<pre class="verbatim" id="x_6_4_0_0_64"><code>(react (on-start (send! 'request))
(on (message 'reply ...)))
</code></pre></div>
<div class="footnote" id="fn_6_68"><span class="counter footnote-counter"><span>68</span></span>In fact, <tt><span class="normal">on-start</span></tt><span class="normal"> is the only way to send a message or spawn an actor during facet startup. Both <tt>send!</tt> and <tt>spawn</tt> are <em>script-expr</em>s, not <em>facet-setup-expr</em>s.</span><span class="plain-layout-boundary"></span></div><p id="x_6_4_0_0_66">the <tt>'request</tt> is guaranteed to be sent only after the subscription to the <tt>'reply</tt> has been established, ensuring that the requesting party will receive the reply even if the replying party responds immediately.<label class="footnote-number" for="fn_6_68">68</label></p><p id="x_6_4_0_0_67">An <tt>on-stop</tt> form may be used to perform cleanup actions just prior to the end of the conversational context modeled by a facet; for example, in</p>
<div class="verbatim" id="x_6_4_0_0_69">
<pre class="verbatim" id="x_6_4_0_0_68"><code>(react (on (retracted 'connection) (stop-current-facet))
(on-stop (send! 'goodbye)))
</code></pre></div><p id="x_6_4_0_0_70">the <tt>'goodbye</tt> message is guaranteed to be sent before the subscription to <tt>'connection</tt> assertions is withdrawn. Any number of <tt>on-start</tt> and <tt>on-stop</tt> forms may be added during facet setup.</p>
<h4 id="x_6_5_0_0_1"><a name="toc_6.5"></a><span class="counter section"><span>6.5</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:rkt:Derived-and-additional"></a><a name="sec:rkt:Derived-and-additional"></a>Derived and additional forms</span></h4><p id="x_6_5_0_0_2">Figure <a class="cross-reference" href="#fig:PLRACKET-syntax-derived">30</a> summarizes derived forms that build upon the core forms to allow concise expression of frequently-employed concepts.</p>
<figure id="x_6_5_0_0_3"><a name="fig:PLRACKET-syntax-derived"></a><pre class="wikihtml"> <span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">script-expr</span></span> := ...
| <span class="wikitex-italic">blocking-facet-expr</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">facet-setup-expr</span></span> := ...
| <span class="wikitex-italic">derived-endpoint-expr</span>
| <span class="wikitex-italic">dataflow-expr</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">derived-endpoint-expr</span></span> := (stop-when {#:when <span class="wikitex-italic">expr</span>} <span class="wikitex-italic">event-pattern </span><span class="wikitex-italic">script-expr </span>...)
| (stop-when-true <span class="wikitex-italic">expr </span><span class="wikitex-italic">script-expr </span>...)
| (during <span class="wikitex-italic">pattern </span><span class="wikitex-italic">facet-setup-expr </span>...)
| (during/spawn <span class="wikitex-italic">pattern </span>{#:name <span class="wikitex-italic">expr</span>} <span class="wikitex-italic">script-expr </span>...)
| <span class="wikitex-italic">query-endpoint-expr</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">query-endpoint-expr</span></span> :=
(define/query-value <span class="wikitex-italic">field-name </span><span class="wikitex-italic">expr </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">add/remove</span>)
| (define/query-set <span class="wikitex-italic">field-name </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">add/remove</span>)
| (define/query-hash <span class="wikitex-italic">field-name </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">add/remove</span>)
| (define/query-hash-set <span class="wikitex-italic">field-name </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">add/remove</span>)
| (define/query-count <span class="wikitex-italic">field-name </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">add/remove</span>)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">add/remove</span></span> := {#:on-add <span class="wikitex-italic">script-expr</span>} {#:on-remove <span class="wikitex-italic">script-expr</span>}
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">blocking-facet-expr</span></span> := (react/suspend (<span class="wikitex-italic">id</span>) <span class="wikitex-italic">facet-setup-expr </span>...)
| (until <span class="wikitex-italic">event-pattern </span><span class="wikitex-italic">facet-setup-expr </span>...)
| (flush!)
| <span class="wikitex-italic">immediate-query</span>
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">dataflow-expr</span></span> := (begin/dataflow <span class="wikitex-italic">script-expr </span>...)
| (define/dataflow <span class="wikitex-italic">field-name </span><span class="wikitex-italic">script-expr </span>{#:default <span class="wikitex-italic">expr</span>})
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">immediate-query</span></span> := (immediate-query <span class="wikitex-italic">query-spec </span>...)
<span class="wikitex-right"><span class="wikitex-backdrop"> </span><span class="wikitex-italic">query-spec</span></span> := (query-value <span class="wikitex-italic">expr </span><span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr</span>)
| (query-set <span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr</span>)
| (query-hash <span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">script-expr</span>)
| (query-hash-set <span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr </span><span class="wikitex-italic">script-expr</span>)
| (query-count <span class="wikitex-italic">pattern </span><span class="wikitex-italic">script-expr</span>)
</pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>30</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLRACKET-syntax-derived"></a>Derived and additional <span class="small-caps">Syndicate/rkt</span> forms<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h6 class="unnumbered" id="x_6_5_0_0_4"><a name="toc_6.5"></a><span class="heading-text paragraph">Facet termination.</span></h6><p id="x_6_5_0_0_5">A common idiom is to terminate a facet in response to an event. The abbreviation <tt>stop-when</tt> is intended for this case:</p><p id="x_6_5_0_0_7">
<p class="align-center" id="x_6_5_0_0_6"><tt>(stop-when</tt> <em>P E ...</em><tt>) </tt><span class="lyx-mathjax mathjax-inline">$\triangleq$</span><tt> (on</tt> <em>P</em> <tt>(stop-facet (current-facet-id)</tt> <em>E ...</em><tt>))</tt></p></p><p id="x_6_5_0_0_8">The <em>script-expr</em>s (<em>E ...</em>) are placed inside the <tt>stop-facet</tt> command, and so are executed outside the stopping facet. The example from above could be written</p><p id="x_6_5_0_0_10">
<p class="align-center" id="x_6_5_0_0_9"><tt>(react (stop-when (message 'x) (react </tt><em>...</em><tt>)))</tt></p></p><p id="x_6_5_0_0_11">This style of use of <tt>stop-when</tt> gives something of the flavor of a state-transition in a state machine, since the <em>script-expr</em>s are in a kind of “tail position” with respect to the stopping facet.</p>
<h6 class="unnumbered" id="x_6_5_0_0_12"><a name="toc_6.5"></a><span class="heading-text paragraph">Sub-conversations and subfacets.</span></h6><p id="x_6_5_0_0_13">A second, even more common idiom is that of <span class="small-caps">Syndicate/λ</span>'s <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> (section <a class="cross-reference" href="#sec:PLLAMBDA-derived-forms">5.7</a>), which introduces a nested subfacet to an actor for the duration of each assertion matching a given pattern. The triggering assertion acts as a <em>conversational frame</em>, delimiting a sub-conversation. The <span class="small-caps">Syndicate/rkt</span> <tt>during</tt> form corresponds to a stereotypical usage of core forms:</p><p id="x_6_5_0_0_15">
<p class="align-center" id="x_6_5_0_0_14"><tt>(during</tt><em> <span class="lyx-mathjax mathjax-inline">$P$</span> <span class="lyx-mathjax mathjax-inline">$E$</span> ...</em><tt>) <span class="lyx-mathjax mathjax-inline">$\triangleq$</span> (on (asserted</tt><em> </em><tt><span class="lyx-mathjax mathjax-inline">$P$</span>) (react (stop-when (retracted</tt><em> <span class="lyx-mathjax mathjax-inline">$P'$</span></em><tt>))</tt><em> <span class="lyx-mathjax mathjax-inline">$E$</span> ...</em><tt>))</tt></p></p><p id="x_6_5_0_0_16">where <span class="lyx-mathjax mathjax-inline">$P'$</span> is derived from <span class="lyx-mathjax mathjax-inline">$P$</span> by replacing every binder <tt>$x</tt> in <span class="lyx-mathjax mathjax-inline">$P$</span> with the corresponding <tt>x</tt>.</p><p id="x_6_5_0_0_17">Just as <span class="small-caps">Syndicate/λ</span>'s <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> had a spawning variant, so <span class="small-caps">Syndicate/rkt</span> has <tt>during/spawn</tt>. The variant form spawns an actor in the dataspace instead of creating a subfacet, confining the scope of failure to an individual sub-conversation rather than allowing a crashing sub-conversation to terminate the actor as a whole.</p>
<h6 class="unnumbered" id="x_6_5_0_0_18"><a name="toc_6.5"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Streaming-queries"></a><a name="par:Streaming-queries"></a>Streaming queries.</span></h6><p id="x_6_5_0_0_19">The <tt>assert</tt> form allows actors to construct shared assertions from values of local fields. To operate in the other direction, updating a field based on some aggregate function over a set of assertions, <span class="small-caps">Syndicate/rkt</span> offers a suite of <tt>define/query-*</tt> forms. For example, given a structure definition</p><p id="x_6_5_0_0_21">
<p class="align-center" id="x_6_5_0_0_20"><tt>(assertion-struct mood (user-name description))</tt></p></p><p id="x_6_5_0_0_22">representing a user's mood, we may declare a field that tracks the set of all user names that have an associated mood via</p><p id="x_6_5_0_0_24">
<p class="align-center" id="x_6_5_0_0_23"><tt>(define/query-set moody-users (mood $n _) n)</tt></p></p><p id="x_6_5_0_0_25">or a field that collects all available mood descriptions into a local hash table via</p><p id="x_6_5_0_0_27">
<p class="align-center" id="x_6_5_0_0_26"><tt>(define/query-hash all-moods (mood $n $m) n m)</tt></p></p><p id="x_6_5_0_0_28">The resulting fields contain ordinary Racket sets and hash tables. In cases where only a single assertion matching a given pattern is expected, the <tt>define/query-value</tt> form extracts that single value, falling back on a default during periods when no matching assertion exists in the shared dataspace:</p><p id="x_6_5_0_0_30">
<p class="align-center" id="x_6_5_0_0_29"><tt>(define/query-value alice-mood 'unknown (mood 'Alice $m) m)</tt></p></p><p id="x_6_5_0_0_31">If an <tt>#:on-add</tt> or <tt>#:on-remove</tt> clause is supplied to a <tt>define/query-*</tt> form, the corresponding expressions are evaluated immediately prior to updating the form's associated field upon receiving a relevant change notification.</p>
<h6 class="unnumbered" id="x_6_5_0_0_32"><a name="toc_6.5"></a><span class="heading-text paragraph">General-purpose field dependencies.</span></h6><p id="x_6_5_0_0_33">The <span class="small-caps">Syndicate/rkt</span> implementation uses a simple dependency-tracking mechanism to determine which endpoint patterns depend on which fields, and exposes this mechanism to the programmer. Each <tt>begin/dataflow</tt> form in a facet setup context introduces a block of code that may depend on zero or more fields. Like an endpoint's pattern, it is executed once at startup and then every time one of its dependent fields is changed. For example, the following prints a message each time Alice's mood changes in the dataspace:</p>
<div class="verbatim" id="x_6_5_0_0_35">
<pre class="verbatim" id="x_6_5_0_0_34"><code>(react (define/query-value alice-mood 'unknown (mood 'Alice $m) m)
(begin/dataflow
(printf "Alice's mood is now: ~a\n" (alice-mood))))
</code></pre></div><p id="x_6_5_0_0_36">Of course, for a simple example like this there are many alternative approaches, including use of <tt>during</tt> with an <tt>on-start</tt> handler:</p>
<div class="verbatim" id="x_6_5_0_0_38">
<pre class="verbatim" id="x_6_5_0_0_37"><code>(react (during (mood 'Alice $m)
(on-start (printf "Alice's mood is now: ~a\n" (alice-mood)))))
</code></pre></div><p id="x_6_5_0_0_39">or use of an <tt>#:on-add</tt> clause in <tt>define/query-value</tt>:</p>
<div class="verbatim" id="x_6_5_0_0_41">
<pre class="verbatim" id="x_6_5_0_0_40"><code>(react (define/query-value alice-mood 'unknown (mood 'Alice $m) m
#:on-add (printf "Alice's mood is now: ~a\n" (alice-mood))))
</code></pre></div><p id="x_6_5_0_0_42">An important difference between the latter two and the first variation is that only the first variation prints a message if <em>some other</em> piece of code updates the <tt>alice-mood</tt> field. It is this ability to react to field changes <em>specifically</em>, rather than to dataspace assertion changes generally, that makes <tt>begin/dataflow</tt> useful.</p><p id="x_6_5_0_0_43">The form <tt>define/dataflow</tt> is an abbreviation for definition of a field whose value directly depends on the values of other fields and that should be updated whenever its dependents change:</p><p id="x_6_5_0_0_45">
<p class="align-center" id="x_6_5_0_0_44"><tt>(define/dataflow</tt><em> F E</em><tt>) <span class="lyx-mathjax mathjax-inline">$\triangleq$</span> (begin (field [</tt><em>F </em><tt>#f]) (begin/dataflow (</tt><em>F E</em><tt>)))</tt></p></p><p id="x_6_5_0_0_46">and the form <tt>stop-when-true</tt> is an abbreviation useful for terminating a facet in response to a predicate over a collection of fields becoming true:</p><p id="x_6_5_0_0_48">
<p class="align-center" id="x_6_5_0_0_47"><tt>(stop-when-true</tt><em> test-expr E ...</em><tt>) <span class="lyx-mathjax mathjax-inline">$\triangleq$</span><br/>(begin/dataflow (when</tt><em> test-expr </em><tt>(stop-facet (current-facet-id)</tt><em> E ...</em><tt>)))</tt></p></p>
<h6 class="unnumbered" id="x_6_5_0_0_49"><a name="toc_6.5"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Blocking-expressions"></a><a name="par:Blocking-expressions"></a>Blocking expressions.</span></h6><p id="x_6_5_0_0_50">The uniformly event-driven style of <span class="small-caps">Syndicate</span> can make it difficult to express certain patterns of control-flow involving <em>blocking requests</em>. Absent special support, the programmer must fall back on manual conversion to continuation-passing style followed by defunctionalization of the resulting continuations, yielding an event-driven state machine <span class="citation citep">(<a class="citation" id="cite-119" href="#bib-Felleisen1988a">Felleisen et al. 1988</a>)</span>. Fortunately, Racket includes a rich library supporting delimited continuations <span class="citation citep">(<a class="citation" id="cite-120" href="#bib-Felleisen1988">Felleisen 1988</a>; <a class="citation" id="cite-121" href="#bib-Flatt2007">Flatt et al. 2007</a>)</span>. <span class="small-caps">Syndicate/rkt</span> allows event-handlers to capture their continuation up to invocation of the event-handler body and no further, replacing it by a nested subfacet. The subfacet may, in response to a later event, restore the suspended continuation, resuming its computation. This allows the programmer to use a blocking style to describe remote-procedure-call-like interactions with an actor's peers, reminiscent of the style made available by a similar use of continuations in the context of web applications <span class="citation citep">(<a class="citation" id="cite-122" href="#bib-Queinnec2000">Queinnec 2000</a>; <a class="citation" id="cite-123" href="#bib-Graunke2001">Graunke et al. 2001</a>)</span>.</p><p id="x_6_5_0_0_51">The <tt>react/suspend</tt> form suspends the active event-handler, binds the suspended continuation to identifier <em>id</em>, and adds a new subfacet configured with the form's <em>facet-setup-expr</em>s. If one of the new subfacet's endpoints later invokes the continuation in <em>id</em>, the subfacet is terminated, and the arguments to <em>id</em> are returned as the result of the <tt>react/suspend</tt> form. For example,</p><p id="x_6_5_0_0_53">
<p class="align-center" id="x_6_5_0_0_52"><tt>(printf "Received: ~a" (react/suspend (k) (on (message (say-to 'Alice $v) (k v))))</tt></p></p><p id="x_6_5_0_0_54">waits for the next message sent to <tt>'Alice</tt>, and when one arrives, prints it out.</p><p id="x_6_5_0_0_55">The <tt>until</tt> form is built on <tt>react/suspend</tt>, and allows temporary establishment of a set of endpoints until some event occurs. It is defined as</p><p id="x_6_5_0_0_57">
<p class="align-center" id="x_6_5_0_0_56"><tt>(until</tt><em> E F ...</em><tt>) <span class="lyx-mathjax mathjax-inline">$\triangleq$</span> (react/suspend (k) (stop-when</tt><em> E </em><tt>(k (void)))</tt><em> F ...</em><tt>)</tt></p></p><p id="x_6_5_0_0_58"><a class="label-anchor" href="#example:rkt:sleep-definition"></a><a name="example:rkt:sleep-definition"></a>As an example of its use, the following <span class="small-caps">Syndicate/rkt</span> library procedure interacts with a timer service and causes a running event-handler to pause for a set number of seconds:</p>
<div class="verbatim" id="x_6_5_0_0_60">
<pre class="verbatim" id="x_6_5_0_0_59"><code>(define (sleep sec)
(define timer-id (gensym 'sleep))
(until (message (timer-expired timer-id _))
(on-start (send! (set-timer timer-id (* sec 1000.0) 'relative)))))
</code></pre></div><p id="x_6_5_0_0_61">An important consideration when programming with <tt>react/suspend</tt> and its derivatives is that the world may change during the time that an event-handler is “blocked”. For example, the following actor has no guarantee that the two messages it prints display the same value:</p>
<div class="verbatim" id="x_6_5_0_0_63">
<pre class="verbatim" id="x_6_5_0_0_62"><code>(message-struct request-printout ())
(message-struct increment-counter ())
(spawn (field [counter 0])
(on (message (increment-counter))
(counter (+ (counter) 1))))
(on (message (request-printout))
(printf "Counter (before sleep): ~a\n" (counter))
(sleep 1)
(printf "Counter (after sleep): ~a\n" (counter))))
</code></pre></div>
<h6 class="unnumbered" id="x_6_5_0_0_64"><a name="toc_6.5"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Point-in-time-queries"></a><a name="par:Point-in-time-queries"></a>Point-in-time queries.</span></h6><p id="x_6_5_0_0_65">The <tt>define/query-*</tt> forms allow an actor to reflect a set of assertions into a local field on an ongoing basis. However, some programs call for sampling of the set of assertions present at a given moment in time, rather than establishment of a long-running streaming query. For these programs, <span class="small-caps">Syndicate/rkt</span> offers the <tt>immediate-query</tt> form, built atop a construct called <tt>flush!</tt>. The latter is approximately defined as</p><p id="x_6_5_0_0_67">
<p class="align-center" id="x_6_5_0_0_66"><tt>(flush!) </tt><span class="lyx-mathjax mathjax-inline">$\triangleq$</span><tt> (let ((x (gensym))) (until (message x) (on-start (send! x))))</tt></p></p>
<div class="footnote" id="fn_6_69"><span class="counter footnote-counter"><span>69</span></span>The notion can usefully be generalized to perform a round-trip to some <em>other</em> distinct locus of state than the dataspace. For example, consider an actor managing a connection to an external SQL database. A form of “flush” that performed a round-trip communication with that actor would assure the caller that all previous commands for the actor had been seen and (presumably) interpreted. Further examples that aim at connected but distinct loci of state can be seen in 80x86 <tt>MFENCE</tt> instruction, the <tt>fflush(3)</tt>, <tt>fsync(2)</tt> and <tt>sync(2)</tt> POSIX library routines, and the “force unit access” variations on SATA write commands <span class="citation citep">(<a class="citation" id="cite-124" href="#bib-IEEE-9945-2009">IEEE 2009</a>; <a class="citation" id="cite-125" href="#bib-T13:1699D">INCITS T13 Committee 2006</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_6_5_0_0_68">and acts to force all preceding actions to the dataspace and allow them to take effect before proceeding. In particular, if new endpoints have established subscriptions to some set of assertions, then <tt>flush!</tt> allows the dataspace a chance to transmit matching assertions to those endpoints before execution of the continuation of <tt>flush!</tt> proceeds.<label class="footnote-number" for="fn_6_69">69</label></p><p id="x_6_5_0_0_69">The <tt>immediate-query</tt> form makes use of <tt>flush!</tt> by establishing a temporary subfacet using <tt>react/suspend</tt>, creating temporary fields tracking the requested information, and performing a single <tt>flush!</tt> round in an <tt>on-start</tt> handler before releasing its suspended continuation. For example,</p>
<div class="verbatim" id="x_6_5_0_0_71">
<pre class="verbatim" id="x_6_5_0_0_70"><code>(immediate-query [query-value 'unknown (mood 'Alice $m) m])
= (react/suspend (k)
(define/query-value v 'unknown (mood 'Alice $m) m)
(on-start (flush!) (k (v))))
</code></pre></div><p id="x_6_5_0_0_72">retrieves the <em>current</em> mood of <tt>'Alice</tt> without setting up a facet to track it over the long term. Likewise,</p>
<div class="verbatim" id="x_6_5_0_0_74">
<pre class="verbatim" id="x_6_5_0_0_73"><code>(immediate-query [query-set (mood $n _) n])
= (react/suspend (k)
(define/query-set v (mood $n _) n)
(on-start (flush!) (k (v))))
</code></pre></div><p id="x_6_5_0_0_75">retrieves the names of all users with some mood recorded at the time of the query.</p><p id="x_6_5_0_0_76">Users of <tt>immediate-query</tt> should remain aware that the world may change during the time the query is executing, since it is based on <tt>react/suspend</tt>. Because <tt>immediate-query</tt> yields to the dataspace, other events may arrive between the moment the query is issued and the moment it completes.</p>
<div class="theorem-like numbered example" id="x_6_5_0_0_90">
<p id="x_6_5_0_0_77"><span class="counter numbered example"><span>6.2</span></span><a class="label-anchor" href="#example:flip-flop"></a><a name="example:flip-flop"></a>Figure <a class="cross-reference" href="#fig:example:flip-flop">31</a> demonstrates a number of the language features just introduced. The program starts four actors: a <tt>printer</tt> (line 6), which displays messages on the standard output; a <tt>flip-flop</tt> (line 9), which transitions back and forth between active and inactive states in response to a <tt>toggle</tt> message, and which asserts an <tt>active</tt> record only when active; a <tt>monitor-flip-flop</tt> actor (line 18), which displays a message (via the <tt>printer</tt>) every time the <tt>flip-flop</tt> changes state; and a <tt>periodic-toggle</tt> actor (line 21), which interfaces to the system timer driver and arranges for delivery of a <tt>toggle</tt> message every second. Figure <a class="cross-reference" href="#fig:Flip-flop-running-structure">32</a> shows the structure of the running program.</p>
<figure id="x_6_5_0_0_79"><a name="fig:example:flip-flop"></a>
<pre class="listing" id="x_6_5_0_0_78"><code>#lang syndicate
(require/activate syndicate/drivers/timestate)
(assertion-struct active ())
(message-struct toggle ())
(message-struct stdout-message (body))
(spawn #:name 'printer
(on (message (stdout-message $body))
(displayln body)))
(spawn* #:name 'flip-flop
(define (active-state)
(react (assert (active))
(stop-when (message (toggle))
(inactive-state))))
(define (inactive-state)
(react (stop-when (message (toggle))
(active-state))))
(inactive-state))
(spawn #:name 'monitor-flip-flop
(on (asserted (active)) (send! (stdout-message "Flip-flop is active")))
(on (retracted (active)) (send! (stdout-message "Flip-flop is inactive"))))
(spawn #:name 'periodic-toggle
(field [next-toggle-time (current-inexact-milliseconds)])
(on (asserted (later-than (next-toggle-time)))
(send! (toggle))
(next-toggle-time (+ (next-toggle-time) 1000))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>31</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:example:flip-flop"></a>Flip-flop example<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_6_5_0_0_82"><a name="fig:Flip-flop-running-structure"></a>
<p class="align-center" id="x_6_5_0_0_81"><img id="x_6_5_0_0_80" src="Figures/flip-flop-program-structure.svg" style="width: auto; height: 10cm;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>32</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Flip-flop-running-structure"></a>The structure of the running flip-flop example<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p id="x_6_5_0_0_83"></p>
<p id="x_6_5_0_0_84">The <tt>flip-flop</tt> actor makes use of <span class="small-caps">Syndicate/rkt</span>'s abstraction facility to define two local procedures, <tt>active-state</tt> and <tt>inactive-state</tt> (lines 10 and 14, respectively). When called, <tt>active-state</tt> constructs a facet that asserts the <tt>active</tt> record (line 11) and waits for a <tt>toggle</tt> message (line 12). When such a message arrives, the facet terminates itself using <tt>stop-when</tt> and performs the action of calling the <tt>inactive-state</tt> procedure. In effect, when toggled, an active facet <em>replaces</em> itself with an inactive facet, demonstrating the state-transition-like nature of <tt>stop-when</tt> endpoints. The <tt>inactive-state</tt> procedure is similar, omitting only the assertion of the <tt>active</tt> record.</p>
<p id="x_6_5_0_0_85">Despite its lack of explicit fields, the <tt>flip-flop</tt> actor is stateful. Its state is implicit in its facet structure. Each time it transitions from inactive to active state, or vice versa, the facet tree that forms part of the actor's implicit <em>control</em> state is updated.</p>
<p id="x_6_5_0_0_88">Only one of the four actors, <tt>periodic-toggle</tt>, maintains explicit state. Its <tt>next-toggle-time</tt> field keeps track of the next moment that a <tt>toggle</tt> message should be transmitted. Each time the field is updated (line 25), <span class="small-caps">Syndicate/rkt</span>'s change-propagation mechanism ensures that the assertion resulting from the subscription of line 23, namely<p id="x_6_5_0_0_87">
<p class="align-center" id="x_6_5_0_0_86"><tt>(observe (later-than (next-toggle-time)))</tt></p></p></p>
<div class="footnote" id="fn_6_70"><span class="counter footnote-counter"><span>70</span></span>See the implementation of the timestate protocol in example <a class="cross-reference" href="#example:timestate-impl">8.12</a> in section <a class="cross-reference" href="#sec:I/O,-time,-timers">8.4</a>.<span class="plain-layout-boundary"></span></div>
<p id="x_6_5_0_0_89">is updated in the dataspace. The service actor started by the timestate driver,<label class="footnote-number" for="fn_6_70">70</label> activated by the <tt>require/activate</tt> form on line 2, is observing <em>observers</em> of <tt>later-than</tt> records, and coordinates with the underlying Racket timer mechanism to ensure that an appropriate record is asserted once the moment of interest has passed.</p><span class="halmos"></span></div>
<h4 id="x_6_6_0_0_1"><a name="toc_6.6"></a><span class="counter section"><span>6.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Ad-hoc-assertions"></a><a name="sec:Ad-hoc-assertions"></a>Ad-hoc assertions</span></h4><p id="x_6_6_0_0_2">From time to time, it is convenient to augment the set of assertions currently expressed by an actor without constructing an endpoint or even a whole facet to maintain the new assertions. <span class="small-caps">Syndicate/rkt</span> provides two imperative commands, <tt>assert!</tt> and <tt>retract!</tt> which allow ad-hoc addition and removal of assertions. While most programs will never use these commands, they occasionally greatly simplify certain tasks.</p>
<figure id="x_6_6_0_0_4"><a name="fig:File-system-using-during"></a>
<pre class="listing" id="x_6_6_0_0_3"><code>(assertion-struct file (name content))
(message-struct save (name content))
(message-struct delete (name))
(spawn (field [files (hash)])
(during (observe (file $name _))
(assert (file name (hash-ref (files) name #f))))
(on (message (save $name $content))
(files (hash-set (files) name content)))
(on (message (delete $name))
(files (hash-remove (files) name))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>33</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:File-system-using-during"></a>“File system” using <tt>during</tt><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_6_6_0_0_6"><a name="fig:File-system-using-assert-and-retract"></a>
<pre class="listing" id="x_6_6_0_0_5"><code>(spawn (field [files (hash)] [monitored (set)])
(on (asserted (observe (file $name _)))
(assert! (file name (hash-ref (files) name #f)))
(monitored (set-add (monitored) name)))
(on (retracted (observe (file $name _)))
(retract! (file name (hash-ref (files) name #f)))
(monitored (set-remove (monitored) name)))
(on (message (save $name $content))
(when (set-member? (monitored) name)
(retract! (file name (hash-ref (files) name #f)))
(assert! (file name content)))
(files (hash-set (files) name content)))
(on (message (delete $name))
(when (set-member? (monitored) name)
(retract! (file name (hash-ref (files) name #f)))
(assert! (file name #f)))
(files (hash-remove (files) name))))
</code></pre><figcaption><span class="counter figure"><span>34</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:File-system-using-assert-and-retract"></a>“File system” using <tt>assert!</tt> and <tt>retract!</tt><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_6_6_0_0_7">Consider figure <a class="cross-reference" href="#fig:File-system-using-during">33</a>, which implements a simple “file system” abstraction using the protocol structures defined on lines 13. Clients assert interest in <tt>file</tt> records, and in response the server examines its database (the hash table held in its <tt>files</tt> field) and supplies the record of interest. Because the server uses <tt>during</tt> (line 5), each distinct file name results in a distinct <em>sub-conversation</em> responsible for maintaining a single assertion (line 6). Subsequent <tt>save</tt> or <tt>delete</tt> requests (lines 710) update the <tt>files</tt> table, which automatically causes recomputation of the assertions resulting from different instances of line 6.</p><p id="x_6_6_0_0_8">An alternative approach is shown in figure <a class="cross-reference" href="#fig:File-system-using-assert-and-retract">34</a>. Here, conversational state is explicitly maintained in a new field, <tt>monitored</tt>, which holds a set of the file names known to be of current interest. In response to a newly-appeared assertion of interest (line 2), the server updates <tt>monitored</tt> (line 4) but also uses <tt>assert!</tt> to publish an initial response record in the dataspace. Subsequent <tt>save</tt> or <tt>delete</tt> requests (lines 817) <em>replace</em> this record by using <tt>retract!</tt> followed by <tt>assert!</tt>, but only do so if the modified file is known to be of interest.</p>
<figure id="x_6_6_0_0_10"><a name="fig:Semaphore-protocol"></a>
<pre class="listing" id="x_6_6_0_0_9"><code>(assertion-struct lease-request (resource-id request-id))
(assertion-struct lease-assignment (resource-id request-id))
(define (spawn-resource resource-id total-available-leases)
(spawn (field [waiters (make-queue)]
[free-lease-count total-available-leases])
(on (asserted (lease-request resource-id $w))
(cond [(positive? (free-lease-count))
(assert! (lease-assignment resource-id w))
(free-lease-count (- (free-lease-count) 1))]
[else
(waiters (enqueue (waiters) w))]))
(on (retracted (lease-request resource-id $w))
(waiters (queue-filter (lambda (x) (not (equal? w x)))
(waiters)))
(retract! (lease-assignment resource-id w)))
(on (retracted (lease-assignment resource-id $w))
(cond [(queue-empty? (waiters))
(free-lease-count (+ (free-lease-count) 1))]
[else
(define-values (w remainder) (dequeue (waiters)))
(assert! (lease-assignment resource-id w))
(waiters remainder)]))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>35</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Semaphore-protocol"></a>“Semaphore” protocol, suitable for implementing Dining Philosophers<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_6_6_0_0_11">A second example of the use of <tt>assert!</tt> and <tt>retract!</tt> is shown in figure <a class="cross-reference" href="#fig:Semaphore-protocol">35</a>. The program implements something like a counting semaphore. Here, <tt>assert!</tt> and <tt>retract!</tt> are used to maintain up to <tt>total-available-leases</tt> separate <tt>lease-assignment</tt> records describing parties requesting use of the semaphore. The first-in, first-out nature of the lease assignment process does not naturally correspond to a nested facet structure; no obvious solution using <tt>during</tt> springs to mind. A remarkable aspect of this program is the use of <tt>retract!</tt> on line 15, in response to a withdrawn lease request. The party withdrawing its request may <em>or may not</em> currently hold one of the available resources. If it does, the <tt>retract!</tt> corresponds to a previous <tt>assert!</tt> (on either line 8 or line 21) and so results in a patch transmitted to the dataspace and a corresponding triggering of the endpoint on line 16; if it does not, then the <tt>retract!</tt> has no effect on the actor's assertion set, since set subtraction is idempotent, and therefore the lease request vanishes without disturbing the rest of the state of the system.</p><p id="x_6_6_0_0_12">The <tt>assert!</tt> and <tt>retract!</tt> commands manipulate a “virtual” endpoint which is considered to exist alongside the real endpoints within the actor's facets. The effects of the commands are therefore only visible to the extent they do not interfere with assertions made by other facets in the actor. For example, if an actor has an existing facet that has an endpoint <tt>(assert</tt> <tt>1)</tt>, and it subsequently performs <tt>(assert!</tt> <tt>1)</tt> and <tt>(assert!</tt> <tt>2)</tt> in response to some event, the patch action sent to the dataspace contains only <tt>2</tt>, since <tt>1</tt> was previously asserted by the assertion endpoint. If, later still, it performs <tt>(retract!</tt> <tt>1)</tt> and <tt>(retract!</tt> <tt>2)</tt>, the resulting patch action will again only mention <tt>2</tt>, since <tt>1</tt> remains asserted by the assertion endpoint.</p><p id="x_6_6_0_0_13">Very few programs make use of this feature; it is not implemented at all in <span class="small-caps">Syndicate/js</span>. Usually, given freedom to design a protocol appropriate for <span class="small-caps">Syndicate</span>, pervasive use of assertions over messages allows <tt>during</tt> and nested facets in general to be used instead of <tt>assert!</tt> and <tt>retract!</tt>. Setting aside the unusual case of the “semaphore” of figure <a class="cross-reference" href="#fig:Semaphore-protocol">35</a>, there are two general areas in which the two commands are helpful:</p>
<ol id="x_6_6_0_0_16"><li id="x_6_6_0_0_14">They can be used to react to the <em>absence</em> of particular assertions in the dataspace (as seen in the “loading indicator” example discussed in section <a class="cross-reference" href="#sec:The-cancellation-pattern">9.6</a>).</li><li id="x_6_6_0_0_15">They are useful in cases where <span class="small-caps">Syndicate</span> implements a protocol not designed with dataspaces in mind, where <em>messages</em> in the <em>foreign</em> protocol update conversational state that corresponds to <em>assertions</em> on the <span class="small-caps">Syndicate</span> side.</li></ol>
<div class="footnote" id="fn_6_71"><span class="counter footnote-counter"><span>71</span></span><span>Source code file <a href="https://github.com/tonyg/syndicate/blob/master/racket/syndicate/drivers/irc.rkt"><tt>racket/syndicate/drivers/irc.rkt</tt></a> in the <span class="small-caps">Syndicate</span> repository.</span><span class="plain-layout-boundary"></span></div><p id="x_6_6_0_0_17">An example of this latter is the IRC client driver.<label class="footnote-number" for="fn_6_71">71</label> When a user joins an IRC channel, the IRC protocol requires that the server send a list of existing members of the channel to the new user using special syntax—zero or more <tt>353</tt> messages containing nicknames, followed by a <tt>366</tt> message to signal the end of the list—before transitioning into an incremental group-maintenance phase, where separate <tt>JOIN</tt> and <tt>PART</tt> messages signal the appearance and disappearance of channel members. The <span class="small-caps">Syndicate</span> protocol for participating in an IRC channel, however, maintains assertions describing the membership of each channel. The mismatch between the IRC protocol's use of messages and the <span class="small-caps">Syndicate</span> protocol's use of assertions is addressed by trusting the server to send appropriate messages, and reflecting each <tt>353</tt>, <tt>JOIN</tt>, and <tt>PART</tt> into appropriate <tt>assert!</tt> and <tt>retract!</tt> actions.</p></p><p id="x_7_4_2_0_14">
<h3 id="x_7_0_0_0_1"><a name="toc_7"></a><span class="counter chapter"><span>7</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:IMPLEMENTATION"></a><a name="CHAP:IMPLEMENTATION"></a>Implementation</span></h3><p id="x_7_0_0_0_2">So far, our discussion of <span class="small-caps">Syndicate</span> has been abstract in order to concentrate on the essence of the programming model, with just enough concrete detail provided to allow us to examine small, realistic examples. Now it is time to turn to techniques for making implementations of <span class="small-caps">Syndicate</span> suitable for exploration of the model using practical programs.</p><p id="x_7_0_0_0_3">The notion of sets of assertions is at the heart of the dataspace model. The formal models presented in chapters <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> and <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> rely on representations of potentially-infinite assertion sets that are amenable to efficient implementations of set union, intersection, complement, and subtraction. These operations are the foundations of the set comprehensions used extensively in the metafunctions used throughout chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>. For these reasons, I will begin by examining a trie-based data structure I have developed, that I call an <em>assertion trie</em> (section <a class="cross-reference" href="#sec:Representing-Assertion-Sets">7.1</a>), which represents and allows efficient operation on assertion sets. After presenting the data structure in the abstract, I will turn to concrete details of its implementation.</p><p id="x_7_0_0_0_4">With a suitable data structure in hand, producing an implementation of the dataspace model can be as simple as following the formal model of chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>. Section <a class="cross-reference" href="#sec:implementing-dataspaces">7.2</a> gives an overview of the core of an implementation of the dataspace model.</p><p id="x_7_0_0_0_5">In addition, <span class="small-caps">Syndicate</span> offers not only a means of structuring interactions among groups of components, but also features for structuring state and reactions within a single component, as presented in chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a>. Section <a class="cross-reference" href="#sec:implementing-PLLAMBDA">7.3</a> describes implementation of the full design.</p><p id="x_7_0_0_0_6">Finally, by directly representing structures from the formal model in an implementation, we unlock the possibility of reflecting on running programs in terms of the concepts of the formal model. Section <a class="cross-reference" href="#sec:Programming-tools">7.4</a> describes initial steps toward programming tools that exploit this connection to assist in visualization and debugging of <span class="small-caps">Syndicate</span> programs.</p>
<div class="footnote" id="fn_7_72"><span class="counter footnote-counter"><span>72</span></span>The formal claims and proofs from previous chapters do not depend on anything in this chapter. Instead, the proofs there use the semantics of sets directly, and remain agnostic to concrete representations of the sets concerned.<span class="plain-layout-boundary"></span></div><p id="x_7_0_0_0_7">While it is both intuitively apparent and borne out by experience that assertion tries are able to faithfully reflect the semantics of a certain kind of sets, and that the prototype <span class="small-caps">Syndicate</span> implementations as a whole live up to the formal models of previous chapters, this chapter will not go beyond making informal claims about these issues. The level of rigor of the implementation work thus far is the usual informal connection to what is proposed to be an underlying formal model. To get to the level of rigor of, say, VLISP <span class="citation citep">(<a class="citation" id="cite-126" href="#bib-Oliva1995">Oliva, Ramsdell and Wand 1995</a>)</span>, we would have to formalize the claims and prove them; to get to the level of CompCert <span class="citation citep">(<a class="citation" id="cite-127" href="#bib-Leroy2009">Leroy 2009</a>)</span>, we would have to mechanize the claims and proofs.<label class="footnote-number" for="fn_7_72">72</label></p>
<h4 id="x_7_1_0_0_1"><a name="toc_7.1"></a><span class="counter section"><span>7.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Representing-Assertion-Sets"></a><a name="sec:Representing-Assertion-Sets"></a>Representing Assertion Sets</span></h4><p id="x_7_1_0_0_2">As the model shows, evaluation of <span class="small-caps">Syndicate</span> programs involves frequent and complex manipulation of sets of assertions. While the grammar and reduction rules of the calculus itself depend on only a few elements of the syntax of assertions, namely the unary constructors <span class="lyx-mathjax mathjax-inline">$\downharpoonleft$</span>, <span class="lyx-mathjax mathjax-inline">$\upharpoonleft$</span>, and <span class="lyx-mathjax mathjax-inline">$?$</span>, much of the power of the system comes from the ability to use a wildcard <span class="lyx-mathjax mathjax-inline">$\star$</span> in user programs specifying sets of assertions to be placed in a dataspace. The wildcard symbol is interpreted as <em>the infinite set of all possible assertions</em>. This leads us to a central challenge: the choice of representation for assertion sets in implementations of <span class="small-caps">Syndicate</span>.</p><p id="x_7_1_0_0_3">There are a number of requirements that must be satisfied by our representation.</p>
<dl id="x_7_1_0_0_12"><dt id="x_7_1_0_0_4">Efficient&nbsp;computation&nbsp;of&nbsp;metafunctions.</dt><dd id="x_7_1_0_0_5"> Metafunctions such as <span class="lyx-mathjax mathjax-inline">$\FBCDName$</span>, <span class="lyx-mathjax mathjax-inline">$\FINP$</span>, and <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> (section <a class="cross-reference" href="#sec:incremental-DS">4.6</a>) must have efficient and accurate implementations in order to deliver correct SCN events to the correct subset of actors in a dataspace in response to a SCN action, without wasting time examining assertions made by actors that are not interested in the change represented by the SCN action.</dd><dt id="x_7_1_0_0_6">Efficient&nbsp;message&nbsp;routing.</dt><dd id="x_7_1_0_0_7"> Some <span class="small-caps">Syndicate</span> programs make heavy use of message sending. For these programs, it is important to be able to quickly discover the set of actors interested in a given message.</dd><dt id="x_7_1_0_0_8">Compactness.</dt><dd id="x_7_1_0_0_9"> The representation of the dataspace must not grow unreasonably large as time goes by. In particular, many <span class="small-caps">Syndicate</span> programs assert and retract the same assertions over and over as they proceed, and it is important that the representation of the dataspace not grow without bound in this case.</dd><dt id="x_7_1_0_0_10">Generality.</dt><dd id="x_7_1_0_0_11"> Assertions are the data structures of <span class="small-caps">Syndicate</span> programming. The representation of assertion sets must handle structures rich enough to support the protocols designed by <span class="small-caps">Syndicate</span> programmers. Likewise, it must support embedding wildcards in assertions in a general enough way that common uses of wildcard are not ruled out.</dd></dl><p id="x_7_1_0_0_13">In this section, I will present <em>Assertion Tries. </em>An Assertion Trie is a data structure based on a <em>trie</em> that satisfies these requirements, offering support for semi-structured <em>S-expression</em> assertions with embedded wildcards, sufficient for the examples and case studies presented in this dissertation. In an implementation of <span class="small-caps">Syndicate</span>, these tries are used in many different contexts. First and foremost, they are used to index dataspaces, mapping assertions to actor identities, but they are also used to represent sets of assertions alone, mapping assertions to the unit value, and therefore to represent both monolithic and incremental SCNs (patches).</p>
<h5 id="x_7_1_1_0_1"><a name="toc_7.1.1"></a><span class="counter subsection"><span>7.1.1</span></span><span class="heading-text subsection">Background</span></h5><p id="x_7_1_1_0_2">A <em>trie</em> <span class="citation citep">(<a class="citation" id="cite-128" href="#bib-DelaBriandais1959">de la Briandais 1959</a>; <a class="citation" id="cite-129" href="#bib-Fredkin1960">Fredkin 1960</a>)</span>, also known as a <em>radix tree</em> or <em>prefix tree</em>, is a kind of search tree keyed by sequences of symbols. Each edge in the trie is labeled with a particular symbol, and searches proceed from the root down toward a leaf, following each symbol in turn from the sequence comprising the key being searched for. Tries are commonly used in applications such as phone switches for routing telephone calls, and in publish/subscribe messaging middleware <span class="citation citep">(<a class="citation" id="cite-130" href="#bib-Ionescu2010">Ionescu 2010</a>; <a class="citation" id="cite-131" href="#bib-Ionescu2011">Ionescu 2011</a>)</span> for routing messages to subscribers. In the former case, the phone number is used as a key, and each digit is one symbol; in the latter, some property of the message itself, commonly its “topic”, serves as the key. In both cases, tries are a good fit because they permit rapid discarding of irrelevant portions of the search space. Standard data structures texts give a good overview of the basics (for example, <span class="citation citealp"><a class="citation" id="cite-132" href="#bib-Cormen2009">Cormen et al. 2009</a></span>, section 2-12).</p><p id="x_7_1_1_0_3">Each trie node logically has a finite number of edges emanating from it, making tries directly applicable to tasks such as phone call routing, where the set of symbols at each step is finite and small. They also work well for cases of message routing where, while the set of possible symbols at each step is not finite, each <em>subscription</em> involves a specific sequence of symbols without wildcards.</p><p id="x_7_1_1_0_4">Given two tries, interpreting each as the set of keys that it matches, it is straightforward and efficient to compute the trie corresponding to the set union, set intersection, or set difference of the inputs. However, set <em>complement</em> poses a problem: tries cannot represent <em>cofinite</em> sets of edges emanating from a node. This poses a difficulty for supporting wildcards, since a wildcard is supposed to correspond to the set of all possible symbols, a special case of a cofinite set.</p><p id="x_7_1_1_0_5">Finally, tries work well where edges are labeled with <em>unstructured</em> symbols. Tries cannot easily represent patterns over semi-structured data such as S-expressions.</p><p id="x_7_1_1_0_6">The data structure must be adapted in order to properly handle both semi-structured keys and wildcards.</p>
<h5 id="x_7_1_2_0_1"><a name="toc_7.1.2"></a><span class="counter subsection"><span>7.1.2</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Semi-structured-assertions"></a><a name="subsec:Semi-structured-assertions"></a>Semi-structured assertions &amp; wildcards</span></h5>
<div class="footnote" id="fn_7_73"><span class="counter footnote-counter"><span>73</span></span>This approach is inspired by Alur and Madhusudans work on <em>nested-word automata</em> <span class="citation citep">(<a class="citation" id="cite-133" href="#bib-Alur2009">Alur and Madhusudan 2009</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_7_1_2_0_2">While a trie must use sequences of tokens as keys, we wish to key on trees. Hence, we must map our tree-shaped assertions, which have both hierarchical and linear structure, to sequences of tokens that encode both forms of structure.<label class="footnote-number" for="fn_7_73">73</label> To this end, we reinterpret assertions as sequences of tokens by reading them left to right and inserting a distinct <em>tuple-marker</em> token <span class="lyx-mathjax mathjax-inline">$\LL n$</span> labeled with the <em>arity</em> of the tuple it introduces to mark entry to a nested subsequence.</p><p id="x_7_1_2_0_4">Let us limit our attention to S-expressions over atoms, sometimes extended with a wildcard marker, <span class="lyx-mathjax mathjax-inline">$\star\notin\ATOM$</span>:
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_3">\begin{align*}
\textrm{Atoms }x,y,z\in\ATOM\phantom{^{+}} &amp; =\mathbb{Z}\cup\mathbf{String}\cup\mathbf{Symbol}\cup\dots\\
\textrm{S-expressions }v,w\in\SEXP\phantom{^{+}} &amp; :=x\ |\;(v,w,\dots)\\
\textrm{Wild S-expressions }v^{+},w^{+}\in\SEXP^{+} &amp; :=x\;|\;(v^{+},w^{+},\dots)\;|\;\star\\
\text{Sets of S-expressions }V\in\SETOF{\SEXP}
\end{align*}
</div></p><p id="x_7_1_2_0_5">Wildcards are not the only option for matching multiple values. In principle, any (decidable) predicate can be used, so long as it can be indexed suitably efficiently. As examples of something narrower than wildcard, but more general than matching specific values, consider <em>range queries</em> over integers and <em>type predicates</em>. Range queries such as <span class="lyx-mathjax mathjax-inline">$\lambda x.\left(10\leq x\wedge x&lt;20\right)$</span> can be used in protocols involving contiguous <em>message identifiers</em> for bulk acknowledgement as well as for flow control. Type predicates such as Racket's <tt>number?</tt> and <tt>string?</tt> can extend our language of assertion patterns with something reminiscent of <em>occurrence typing </em><span class="citation citep">(<a class="citation" id="cite-134" href="#bib-Tobin-Hochstadt2008">Tobin-Hochstadt and Felleisen 2008</a>)</span>.</p>
<div class="theorem-like numbered definition named" id="x_7_1_2_0_8">
<p id="x_7_1_2_0_7"><span class="counter numbered definition"><span>7.1</span></span><span class="lyx-argument">Meaning of wild S-expressions<span class="plain-layout-boundary"></span></span>Each element of <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span> has a straightforward interpretation as a set of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s:
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_6">\begin{align*}
\MEANINGName &amp; :\SEXP^{+}\rightarrow\SETOF{\SEXP}\\
\MEANING x &amp; =\{x\}\\
\MEANING{(v^{+},w^{+},\dots)} &amp; =\{(v',w',\dots)\;|\;v'\in\MEANING{v^{+}},w'\in\MEANING{w^{+}},\dots)\\
\MEANING{\star} &amp; =\SEXP
\end{align*}
</div></p><span class="halmos"></span></div><p id="x_7_1_2_0_10">The alphabet of tokens we will use, <span class="lyx-mathjax mathjax-inline">$\TOK$</span>, consists of the atoms, plus a family of tuple-markers (not themselves <span class="lyx-mathjax mathjax-inline">$\ATOM$</span>s), each subscripted with its arity: <span class="lyx-mathjax mathjax-inline">$\LL0$</span> is the token introducing a 0-ary tuple, <span class="lyx-mathjax mathjax-inline">$\LL1$</span> a unary tuple, <span class="lyx-mathjax mathjax-inline">$\LL2$</span> a pair, and so on. Matching <span class="lyx-mathjax mathjax-inline">$\gg$</span> “pop” tokens are not included: they follow implicitly from arities used on tuple-markers in sequences of tokens. We will write <span class="lyx-mathjax mathjax-inline">$\ARITY t$</span> for the arity of a given token: for all atoms, <span class="lyx-mathjax mathjax-inline">$\ARITY x=0$</span>; for all tuple-markers, <span class="lyx-mathjax mathjax-inline">$\ARITY{\LL n}=n$</span>. We will sometimes want to extend the set of tokens with our wildcard marker; we will write <span class="lyx-mathjax mathjax-inline">$\TOK^{+}$</span> for this set.
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_9">\begin{align*}
\textrm{Tokens }s,t\in\TOK\phantom{^{+}} &amp; =\ATOM\cup\{\ll_{0},\ll_{1},\ll_{2},\dots\}\\
\textrm{Wild tokens }s^{+},t^{+}\in\TOK^{+} &amp; =\TOK\cup\{\star\}
\end{align*}
</div></p>
<div class="theorem-like numbered definition named" id="x_7_1_2_0_13">
<p id="x_7_1_2_0_12"><span class="counter numbered definition"><span>7.2</span></span><span class="lyx-argument">Serialization of S-expressions<span class="plain-layout-boundary"></span></span>We now have the ingredients we need to read S-expressions as sequences of tokens using the following definition, and the analogous <span class="lyx-mathjax mathjax-inline">$\SER{\cdot}^{+}$</span> extended to wild S-expressions and wild tokens by <span class="lyx-mathjax mathjax-inline">$\SER{\star}^{+}=\star$</span>:
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_11">\begin{align*}
\SER{\cdot} &amp; \;:\;\SEXP\rightarrow\overrightarrow{\TOK}\\
\SER x &amp; =x\\
\SER{(v,w,\dots)} &amp; =\ \LL n\;\SER v\;\SER w\ \dots\textrm{ where }n=|(v,w,...)|
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_7_1_2_0_16">
<p id="x_7_1_2_0_15"><span class="counter numbered example"><span>7.3</span></span>The S-expression <span class="lyx-mathjax mathjax-inline">$(\mathtt{sale},\mathtt{milk},(1,\mathtt{pt}),(1.17,\mathtt{usd}))$</span> translates to the following token sequence:
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_14">\begin{align*}
\SER{(\mathtt{sale},\mathtt{milk},(1,\mathtt{pt}),(1.17,\mathtt{usd}))}\\
=\ \LL4\ \mathtt{sale}\ \mathtt{milk}\ \LL2\ 1\ \mathtt{pt}\ \LL2\ 1.17\ \mathtt{usd}
\end{align*}
</div></p><span class="halmos"></span></div><p id="x_7_1_2_0_17">The correctness of some of our operations on assertion tries depends on the idea of a <em>well-formed</em> sequence of tokens; namely, one that corresponds to some <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>.</p>
<div class="theorem-like numbered definition named" id="x_7_1_2_0_19">
<p id="x_7_1_2_0_18"><span class="counter numbered definition"><span>7.4</span></span><span class="lyx-argument">Parsing of token sequences<span class="plain-layout-boundary"></span></span>We define the (partial) function <span class="lyx-mathjax mathjax-inline">$\DESER{\cdot}$</span> (and its obvious extension <span class="lyx-mathjax mathjax-inline">$\DESER{\cdot}^{+}$</span>, <span class="lyx-mathjax mathjax-inline">$\DESER{\star\;t\dots}^{+}=(\star,t\dots)$</span>) to parse a sequence of tokens into a <span class="lyx-mathjax mathjax-inline">$\SEXP$</span> and an unconsumed portion of the input:</p><span class="halmos"></span></div><p id="x_7_1_2_0_21">
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_20">\begin{align*}
\DESER{\cdot} &amp; :\ \overrightarrow{\TOK}\rightharpoonup\SEXP\times\overrightarrow{\TOK}\\
\DESER{x\ t\dots} &amp; =(x,t\dots)\\
\DESER{\LL n\ t_{0}\dots} &amp; =((v_{1},v_{2},\dots,v_{n}),t_{n}\dots)\\
\textrm{where }(v_{1},t_{1}\dots) &amp; =\DESER{t_{0}\dots}\\
(v_{2},t_{2}\dots) &amp; =\DESER{t_{1}\dots}\\
&amp; \vdots\\
(v_{n},t_{n}\dots) &amp; =\DESER{t_{n-1}\dots}
\end{align*}
</div></p><p id="x_7_1_2_0_22">We extend <span class="lyx-mathjax mathjax-inline">$\DESER{\cdot}$</span> and <span class="lyx-mathjax mathjax-inline">$\DESER{\cdot}^{+}$</span> to sequences of tokens representing an <span class="lyx-mathjax mathjax-inline">$n$</span>-tuple of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s with <span class="lyx-mathjax mathjax-inline">$\DESER{t\dots}_{n}=\DESER{\LL nt\dots}$</span> and <span class="lyx-mathjax mathjax-inline">$\DESER{t\dots}_{n}^{+}=\DESER{\LL nt\dots}^{+}$</span>.</p>
<div class="theorem-like numbered definition named" id="x_7_1_2_0_25">
<p id="x_7_1_2_0_24"><span class="counter numbered definition"><span>7.5</span></span><span class="lyx-argument">Well-formed token sequences<span class="plain-layout-boundary"></span></span> Exactly those token sequences for which <span class="lyx-mathjax mathjax-inline">$\DESER{\cdot}_{n}$</span> is defined and yields an empty remainder are the <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed token sequences:
<div class="lyx-mathjax mathjax-display" id="x_7_1_2_0_23">\[
\begin{gathered}\WFn n{t\dots}\iff\exists v.\;\DESER{t\dots}_{n}=(v,\cdot)\\
\WFnplus n{t^{+}\dots}\iff\exists v^{+}.\;\DESER{t^{+}\dots}_{n}^{+}=(v^{+},\cdot)
\end{gathered}
\]
</div>We write <span class="lyx-mathjax mathjax-inline">$\WF{t\dots}$</span> to mean <span class="lyx-mathjax mathjax-inline">$\WFn1{t\dots}$</span> and <span class="lyx-mathjax mathjax-inline">$\WFplus{t^{+}\dots}$</span> to mean <span class="lyx-mathjax mathjax-inline">$\WFnplus1{t^{+}\dots}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered proposition" id="x_7_1_2_0_27">
<p id="x_7_1_2_0_26"><span class="counter numbered proposition"><span>7.6</span></span>For all <span class="lyx-mathjax mathjax-inline">$v$</span>, <span class="lyx-mathjax mathjax-inline">$\DESER{\SER v}=(v,\cdot)$</span> and likewise for <span class="lyx-mathjax mathjax-inline">$v^{+}$</span>, <em>mutatis mutandis.</em></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_7_1_2_0_29">
<p id="x_7_1_2_0_28"><span class="counter unnumbered proof"><span>7.6</span></span>By induction on <span class="lyx-mathjax mathjax-inline">$v$</span> (respectively <span class="lyx-mathjax mathjax-inline">$v^{+}$</span>).</p><span class="halmos"></span></div>
<div class="theorem-like numbered proposition" id="x_7_1_2_0_31">
<p id="x_7_1_2_0_30"><span class="counter numbered proposition"><span>7.7</span></span>For all <span class="lyx-mathjax mathjax-inline">$(t\dots)$</span>, if <span class="lyx-mathjax mathjax-inline">$\DESER{t\dots}=(v,\cdot)$</span> then <span class="lyx-mathjax mathjax-inline">$\SER v=(t\dots)$</span>, and likewise for <span class="lyx-mathjax mathjax-inline">$(t^{+}\dots)$</span>, <em>mutatis mutandis.</em></p><span class="halmos"></span></div>
<div class="theorem-like unnumbered proof" id="x_7_1_2_0_33">
<p id="x_7_1_2_0_32"><span class="counter unnumbered proof"><span>7.7</span></span>By induction on <span class="lyx-mathjax mathjax-inline">$\DESER{t\dots}$</span> (respectively <span class="lyx-mathjax mathjax-inline">$\DESER{t^{+}\dots}^{+}$</span>).</p><span class="halmos"></span></div>
<h5 id="x_7_1_3_0_1"><a name="toc_7.1.3"></a><span class="counter subsection"><span>7.1.3</span></span><span class="heading-text subsection">Assertion trie syntax</span></h5><p id="x_7_1_3_0_3">Tries <span class="lyx-mathjax mathjax-inline">$T$</span> themselves are polymorphic in the values carried at their leaves, and consist of the following recursive definitions:
<div class="lyx-mathjax mathjax-display" id="x_7_1_3_0_2">\begin{align*}
\textrm{Tries }T,W\in\TRIE A &amp; :=\MT\ |\ \OK{\alpha}\ |\ \BRx WM\qquad\textrm{where }\alpha\in\mathbf{A}\\
\text{Branch nodes }M\in\NODE A &amp; =\TOK\rightarrow_{\mathit{finite}}\TRIE A
\end{align*}
</div>There are three types of node: <span class="lyx-mathjax mathjax-inline">$\MT$</span> denotes an empty trie, a failing match; <span class="lyx-mathjax mathjax-inline">$\OK{\alpha}$</span> denotes a leaf node carrying a value, a (potentially) successful match; and <span class="lyx-mathjax mathjax-inline">$\BRx WM$</span> an internal node with a <em>default</em> branch <span class="lyx-mathjax mathjax-inline">$W$</span> and a finite collection of <em>token-labeled </em>branches <span class="lyx-mathjax mathjax-inline">$(s\mapsto T)\in M$</span>. Key to the interpretation of this syntax is that the wildcard branch <span class="lyx-mathjax mathjax-inline">$W$</span> represents the trie to be associated with any token <span class="lyx-mathjax mathjax-inline">$s'$</span> not mentioned, <span class="lyx-mathjax mathjax-inline">$s'\notin\mathsf{dom}(M)$</span>. A sequence of tokens stretching from the root of a trie to one of its leaves represents an assertion, if every followed edge is token-labeled, or a set of assertions, if any default branches are taken.</p><p id="x_7_1_3_0_4">The notion of well-formedness developed for token sequences generalizes to assertion tries by reading token sequences along the edges in a trie stretching from the root to each leaf. The intuition is that if a path in an <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed trie ends at an <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> node, then the tokens labeling that path denote exactly <span class="lyx-mathjax mathjax-inline">$n$</span> <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span>s. In addition, all paths in an <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed trie should be no longer than necessary. That is, if we traverse <span class="lyx-mathjax mathjax-inline">$n$</span> <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span>s' worth of edges from the root of an <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed trie, we will either arrive “early” at an <span class="lyx-mathjax mathjax-inline">$\MT$</span> node, or “exactly on time” at an <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> or an <span class="lyx-mathjax mathjax-inline">$\MT$</span> node, but will never end up at a <span class="lyx-mathjax mathjax-inline">$\BRname$</span> node. </p>
<div class="theorem-like numbered definition named" id="x_7_1_3_0_12">
<p id="x_7_1_3_0_11"><span class="counter numbered definition"><span>7.8</span></span><span class="lyx-argument">Well-formed tries<span class="plain-layout-boundary"></span></span>We reuse the notation <span class="lyx-mathjax mathjax-inline">$\WFname_{n}$</span> for tries. We will again write <span class="lyx-mathjax mathjax-inline">$\WF T$</span> for <span class="lyx-mathjax mathjax-inline">$\WFn1T$</span>. The predicate <span class="lyx-mathjax mathjax-inline">$\WFn nT$</span> is defined by structural induction on <span class="lyx-mathjax mathjax-inline">$T$</span> by three cases:
<ol id="x_7_1_3_0_8"><li id="x_7_1_3_0_5"><span class="lyx-mathjax mathjax-inline">$\WFn n{\MT}$</span>; that is, <span class="lyx-mathjax mathjax-inline">$\MT$</span> is <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed for all <span class="lyx-mathjax mathjax-inline">$n$</span>.</li><li id="x_7_1_3_0_6"><span class="lyx-mathjax mathjax-inline">$\WFn0{\OK{\alpha}}$</span>; that is, an <span class="lyx-mathjax mathjax-inline">$\OK{\alpha}$</span> trie is only ever <span class="lyx-mathjax mathjax-inline">$0$</span>-well-formed.</li><li id="x_7_1_3_0_7"><span class="lyx-mathjax mathjax-inline">$\WFn{n+1}{\BRx WM}$</span> if both <span class="lyx-mathjax mathjax-inline">$\WFn nW$</span> and <span class="lyx-mathjax mathjax-inline">$\forall s\in\mathsf{dom}(M).\WFn{n+\ARITY s}{M(s)}$</span>; that is, <span class="lyx-mathjax mathjax-inline">$\BRx WM$</span> is <span class="lyx-mathjax mathjax-inline">$\left(n+1\right)$</span>-well-formed if <span class="lyx-mathjax mathjax-inline">$W$</span> is <span class="lyx-mathjax mathjax-inline">$n$</span>-well-formed and every <span class="lyx-mathjax mathjax-inline">$M(s)$</span> is <span class="lyx-mathjax mathjax-inline">$\left(n+\ARITY s\right)$</span>-well-formed for every <span class="lyx-mathjax mathjax-inline">$s$</span>-labeled edge leading away from the <span class="lyx-mathjax mathjax-inline">$\BRname$</span> node.</li></ol><p id="x_7_1_3_0_10">This definition deserves an illustration. Following our intuition, the trie
<div class="lyx-mathjax mathjax-display" id="x_7_1_3_0_9">\[
\BR{\MT}{\LL2\mapsto\BR{\MT}{\mathtt{X}\mapsto\BR{\MT}{\mathtt{Y}\mapsto\OK{\alpha}}}}
\]
</div>should be <span class="lyx-mathjax mathjax-inline">$\WFname_{1}$</span> because the token sequence <span class="lyx-mathjax mathjax-inline">$\LL2\mathtt{X}\ \mathtt{Y}$</span> along the path leading to <span class="lyx-mathjax mathjax-inline">$\OK{\alpha}$</span> denotes one <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>, <span class="lyx-mathjax mathjax-inline">$(\mathtt{X},\mathtt{Y})$</span>. Following the definition of <span class="lyx-mathjax mathjax-inline">$\WFname_{n}$</span>, however, it is <span class="lyx-mathjax mathjax-inline">$\WFname_{1}$</span> because <span class="lyx-mathjax mathjax-inline">$\WFn0{\MT}$</span> and <span class="lyx-mathjax mathjax-inline">$\WFn2{\BR{\MT}{\mathtt{X}\mapsto\BR{\MT}{\mathtt{Y}\mapsto\OK{\alpha}}}}$</span>. As we traversed the <span class="lyx-mathjax mathjax-inline">$\LL2$</span> edge, we added <span class="lyx-mathjax mathjax-inline">$\ARITY{\LL2}\;=2$</span> to <span class="lyx-mathjax mathjax-inline">$n$</span>, taking into account the nesting structure implied by the tuple-marker.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered definition named" id="x_7_1_3_0_19">
<figure class="fullwidth" id="x_7_1_3_0_17"><a name="fig:Interpretation-of-assertion-tries"></a>
<p class="align-center" id="x_7_1_3_0_16">
<div class="frameless-box" id="x_7_1_3_0_15">
<div class="frameless-box" id="x_7_1_3_0_14">
<div class="lyx-mathjax mathjax-display" id="x_7_1_3_0_13">\begin{align*}
\MEANINGName &amp; :\WFn nT\implies n:\mathbb{N}\times T:\TRIE A\rightarrow\SETOF{\SEXP\times\mathbf{A}}\\
\MEANINGn nT &amp; =\COLLECT{\cdot}{\emptyset}Tn\\
\COLLECTname &amp; :\mathbb{N}\times\VECOF{\TOK^{+}}\times\SETOF{\SEXP}\times\TRIE A\rightarrow\SETOF{\SEXP\times\mathbf{A}}\\
\COLLECT{t^{+}\dots}V{\MT}n &amp; =\emptyset\\
\COLLECT{t^{+}\dots}V{\OK{\alpha}}n &amp; =(\MEANING{v^{+}}-V)\times\{\alpha\}\text{ where }(v^{+},\cdot)=\DESER{t^{+}\dots}_{n}^{+}\\
\COLLECT{t^{+}\dots}V{\BRx WM}n &amp; =\COLLECT{t^{+}\dots\star}{\left(V\cup\mathit{prefixe}s(n,t^{+}\dots,M)\right)}Wn\cup\bigcup_{{s\in\mathsf{dom}(M)}}\COLLECT{t^{+}\dots s}V{M(s)}n\\
\mathit{prefixes} &amp; :\mathbb{N}\times\VECOF{\TOK^{+}}\times\NODE A\rightarrow\SETOF{\SEXP}\\
\mathit{prefixes}(n,t^{+}\dots,M) &amp; =\left\{ v\;|\;v\in\MEANING{v^{+}},(v^{+},\cdot)=\DESER{t^{+}\dots s\;s'\dots}_{n}^{+},s\in\mathsf{dom}(M)\right\}
\end{align*}
</div><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>36</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Interpretation-of-assertion-tries"></a>Interpretation of assertion tries<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p id="x_7_1_3_0_18"><span class="counter numbered definition"><span>7.9</span></span><span class="lyx-argument">Meaning of <span class="lyx-mathjax mathjax-inline">$\WFname$</span> tries<span class="plain-layout-boundary"></span></span>Each element <span class="lyx-mathjax mathjax-inline">$T$</span> of <span class="lyx-mathjax mathjax-inline">$\TRIE A$</span> such that <span class="lyx-mathjax mathjax-inline">$\WFn nT$</span> has an interpretation as a set of pairs of <span class="lyx-mathjax mathjax-inline">$n$</span>-tuples of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s and elements of <span class="lyx-mathjax mathjax-inline">$\mathbf{A}$</span>, <span class="lyx-mathjax mathjax-inline">$\MEANINGn nT$</span>, defined in figure <a class="cross-reference" href="#fig:Interpretation-of-assertion-tries">36</a>. Intuitively, <span class="lyx-mathjax mathjax-inline">$\COLLECTname$</span> traverses the trie, accumulating not only token sequences along paths but also a set of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s that are “handled elsewhere”; when it reaches an <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> node, it interprets the sequence, and then rejects any <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s in the “handled elsewhere” set. When <span class="lyx-mathjax mathjax-inline">$\mathbf{A}=\mathbf{1}$</span>, a <span class="lyx-mathjax mathjax-inline">$\WFname_{n}$</span> trie represents a set of <span class="lyx-mathjax mathjax-inline">$n$</span>-tuples of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s.</p><span class="halmos"></span></div>
<h5 id="x_7_1_4_0_1"><a name="toc_7.1.4"></a><span class="counter subsection"><span>7.1.4</span></span><span class="heading-text subsection">Compiling patterns to tries</span></h5>
<figure id="x_7_1_4_0_3"><a name="fig:Compilation-of-wild-sexps"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_4_0_2">\begin{align*}
\PAT A{\cdot}{\cdot} &amp; :\ \mathbf{A}\rightarrow\SEXP^{+}\rightarrow\TRIE A\\
\PAT A{\alpha}{v^{+}} &amp; =\PATseq A{\OK{\alpha}}{\llbracket v^{+}\rrbracket^{+}}\\
\\
\PATseq A{\cdot}{\cdot} &amp; :\ \TRIE A\rightarrow\VECOF{\TOK^{+}}\rightarrow\TRIE A\\
\PATseq AT{\cdot} &amp; =T\\
\PATseq AT{\star\ t^{+}\dots} &amp; =\BR{\PATseq AT{t^{+}\dots}}{}\\
\PATseq AT{s\ t^{+}\dots} &amp; =\BR{\MT}{s\mapsto\PATseq AT{t^{+}\dots}}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>37</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Compilation-of-wild-sexps"></a>Compilation of wild S-expressions to tries<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_4_0_4">Equipped with syntax for tries, we may define a function <span class="lyx-mathjax mathjax-inline">$\PAT A{\alpha}{v^{+}}$</span> which translates wild S-expressions to tries (figure <a class="cross-reference" href="#fig:Compilation-of-wild-sexps">37</a>).</p>
<div class="theorem-like numbered claim" id="x_7_1_4_0_6">
<p id="x_7_1_4_0_5"><span class="counter numbered claim"><span>7.10</span></span>If <span class="lyx-mathjax mathjax-inline">$T=\PAT A{\alpha}{v^{+}}$</span>, then <span class="lyx-mathjax mathjax-inline">$\WF T$</span> and <span class="lyx-mathjax mathjax-inline">$\MEANINGn1T=\MEANING{v^{+}}\times\{\alpha\}$</span>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_7_1_4_0_9">
<p id="x_7_1_4_0_8"><span class="counter numbered example"><span>7.11</span></span>Consider the wild S-expression <span class="lyx-mathjax mathjax-inline">$(\mathtt{sale},\mathtt{milk},\star,\star)$</span>, representing the infinite set of all 4-ary tuple S-expressions with first element <span class="lyx-mathjax mathjax-inline">$\mathtt{sale}$</span> and second element <span class="lyx-mathjax mathjax-inline">$\mathtt{milk}$</span>. To translate this into an equivalent trie, also representing a simple set of assertions, we choose to instantiate <span class="lyx-mathjax mathjax-inline">$\TRIE{}$</span> with <span class="lyx-mathjax mathjax-inline">$\mathbf{A}=\mathbf{1}$</span>:
<div class="lyx-mathjax mathjax-display" id="x_7_1_4_0_7">\begin{align*}
\PAT1{()}{(\mathtt{sale},\mathtt{milk},\star,\star)}=\; &amp; \PATseq1{\OKunit}{\ll_{4}\ \mathtt{sale}\ \mathtt{milk}\ \star\ \star}\\
=\; &amp; \BR{\MT}{\ll_{4}\mapsto\PATseq1{\OKunit}{\mathtt{sale}\ \mathtt{milk}\ \star\ \star}}\\
\dots=\; &amp; \BR{\MT}{\ll_{4}\mapsto\BR{\MT}{\mathtt{sale}\mapsto\BR{\MT}{\mathtt{milk}\mapsto\BR{\BR{\OKunit}{}}{}}}}
\end{align*}
</div></p><span class="halmos"></span></div>
<h5 id="x_7_1_5_0_1"><a name="toc_7.1.5"></a><span class="counter subsection"><span>7.1.5</span></span><span class="heading-text subsection">Representing <span class="small-caps">Syndicate</span> data structures with assertion tries</span></h5><p id="x_7_1_5_0_2"><span class="small-caps">Syndicate</span> implementations use assertion tries in two ways. The first application is to represent a set of assertions. We use <span class="lyx-mathjax mathjax-inline">$\SETTRIE$</span>, where trie leaves are placeholders <span class="lyx-mathjax mathjax-inline">$\OKunit$</span>, for this purpose. For example, such tries represent assertion sets in patch events and actions. The second application is to represent the contents of a dataspace; namely, a set of pairs of assertions and actor IDs, or equivalently a map from assertions to sets of actor IDs. Here, we use <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span>, and leaves carry sets of actor IDs.</p><p id="x_7_1_5_0_4">A common operation in <span class="small-caps">Syndicate</span> implementations is <em>relabeling</em>, used among other things to convert back-and-forth between <span class="lyx-mathjax mathjax-inline">$\SETTRIE$</span> and <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span> instances:
<div class="lyx-mathjax mathjax-display" id="x_7_1_5_0_3">\begin{align*}
\RELABELname &amp; :\ (\mathbf{A}\rightarrow\mathbf{B})\rightarrow\TRIE A\rightarrow\TRIE B\\
\RELABEL f{\MT} &amp; =\MT\\
\RELABEL f{\OK{\alpha}} &amp; =\OK{f\ \alpha}\\
\RELABEL f{\BR T{s\mapsto T',\dots}} &amp; =\BR{\RELABEL fT}{s\mapsto\RELABEL f{T'},\dots}
\end{align*}
</div></p>
<div class="theorem-like numbered claim" id="x_7_1_5_0_6">
<p id="x_7_1_5_0_5"><span class="counter numbered claim"><span>7.12</span></span>If <span class="lyx-mathjax mathjax-inline">$\WFn nT$</span>, then <span class="lyx-mathjax mathjax-inline">$T'=\RELABEL fT$</span> implies <span class="lyx-mathjax mathjax-inline">$(v,\alpha)\in\MEANINGn nT$</span> iff <span class="lyx-mathjax mathjax-inline">$(v,f\;\alpha)\in\MEANINGn n{T'}$</span>.</p><span class="halmos"></span></div>
<h5 id="x_7_1_6_0_1"><a name="toc_7.1.6"></a><span class="counter subsection"><span>7.1.6</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Searching"></a><a name="subsec:Searching"></a>Searching</span></h5><p id="x_7_1_6_0_3">A straightforward adaptation of the usual trie-searching algorithm to take wildcards into account (figure <a class="cross-reference" href="#fig:search-trie">38</a>) allows discovery of the set of actors interested in receiving a copy of a given message. Given a candidate message and a trie representing a dataspace, we first convert the message to an equivalent sequence of tokens, and then walk the trie using the token-sequence as a key:
<div class="lyx-mathjax mathjax-display" id="x_7_1_6_0_2">\begin{align*}
R &amp; :\ \DSTRIE\\
m &amp; :\ \SEXP\\
\mathit{ids} &amp; :\ \SETOF{\LOC}\\
\mathit{ids} &amp; =\begin{cases}
\mathit{locs} &amp; \textrm{if }\SEARCH{\SETOF{\mathbf{Loc}}}{\SER m}R=\FOUND{\mathit{locs}}\\
\emptyset &amp; \textrm{if }\SEARCH{\SETOF{\mathbf{Loc}}}{\SER m}R=\NOTFOUND
\end{cases}
\end{align*}
</div> The key distinction from the normal trie-searching algorithm is the case where a token is not found in the trie. Normally, the search would yield failure at this point. Instead, we fall back on the <em>wildcard</em> case, following that branch as if the sought token had been present all along.</p>
<figure class="fullwidth" id="x_7_1_6_0_5"><a name="fig:search-trie"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_6_0_4">\begin{align*}
\SEARCH A{\cdot}{\cdot} &amp; :\ \overrightarrow{\TOK}\rightarrow\TRIE A\rightarrow\NOTFOUND+\FOUND{\mathbf{A}}\\
\SEARCH A{s\dots}{\MT} &amp; =\NOTFOUND\\
\SEARCH A{\cdot}{\OK{\alpha}} &amp; =\FOUND{\alpha}\\
\SEARCH A{s\ t\dots}{\OK{\alpha}} &amp; =\NOTFOUND\\
\SEARCH A{\cdot}{\BRx TM} &amp; =\NOTFOUND\\
\SEARCH A{s\ t\dots}{\BR T{s'\mapsto T',\dots}} &amp; =\begin{cases}
\SEARCH A{t\dots}{T''} &amp; \textrm{if }(s\mapsto T'')\in\{s'\mapsto T',\dots\}\\
\SEARCH A{t\dots}{\makeTail{\ARITY s}T} &amp; \textrm{otherwise}
\end{cases}\\
\\
\makeTail nT &amp; =\underset{n\textrm{ layers of }\BRname}{\underbrace{\BR{\BR{\dots\BR T{}\dots}{}}{}}}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>38</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:search-trie"></a>Searching an assertion trie<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered claim named" id="x_7_1_6_0_7">
<p id="x_7_1_6_0_6"><span class="counter numbered claim"><span>7.13</span></span><span class="lyx-argument">Sound searching<span class="plain-layout-boundary"></span></span> If <span class="lyx-mathjax mathjax-inline">$\WF{s\dots}$</span>, meaning that <span class="lyx-mathjax mathjax-inline">$\DESER{s\dots}=(v,\cdot)$</span> for some <span class="lyx-mathjax mathjax-inline">$v$</span>, and <span class="lyx-mathjax mathjax-inline">$\WF T$</span>, then both (a) <span class="lyx-mathjax mathjax-inline">$\SEARCH A{s\dots}T=\NOTFOUND$</span> iff there is no <span class="lyx-mathjax mathjax-inline">$\alpha$</span> such that <span class="lyx-mathjax mathjax-inline">$(v,\alpha)\in\MEANINGn 1T$</span>, and (b) <span class="lyx-mathjax mathjax-inline">$\SEARCH A{s\dots}T=\FOUND{\alpha}$</span> iff some unique <span class="lyx-mathjax mathjax-inline">$\alpha$</span> exists such that <span class="lyx-mathjax mathjax-inline">$(v,\alpha)\in\MEANINGn 1T$</span>.</p><span class="halmos"></span></div><p id="x_7_1_6_0_8">The algorithm can be further adapted to support wildcards embedded in <em>messages</em>, representing simultaneous searching for a particular infinite set of keys. This extended version of <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> has signature <span class="lyx-mathjax mathjax-inline">$\overrightarrow{\TOK^{+}}\rightarrow\TRIE A\rightarrow(\mathbf{A}\rightarrow\mathbf{A}\rightarrow\mathbf{A})\rightarrow\NOTFOUND+\FOUND{\mathbf{A}}$</span>, not only allowing <span class="lyx-mathjax mathjax-inline">$\star$</span> in the input token sequence but also demanding a function used to combine <span class="lyx-mathjax mathjax-inline">$\mathbf{A}$</span>s when a wildcard input matches more than one branch of the trie. Allowing wildcards in messages gives a flavor of broadcast messaging dual to the normal type: where usually a pattern declaring interest in messages admits multiple possible messages, and each delivery includes a single message, here we may use a group of patterns each declaring interest in a single message, while each delivery includes <em>multiple</em> messages, by way of the wildcard mechanism.</p><p id="x_7_1_6_0_9">Hybrids are also possible and useful. For example, consider an instant-messaging system where each connected user has asserted interest in the pair of their own name and the wildcard, for example <span class="lyx-mathjax mathjax-inline">$(\mathtt{Alice},\star)$</span> and <span class="lyx-mathjax mathjax-inline">$(\mathtt{Bob},\star)$</span>. Sending a wildcard message <span class="lyx-mathjax mathjax-inline">$\langle\star,\textrm{"Hello!"}\rangle$</span> delivers a greeting to all connected users, and sending a specifically-addressed message <span class="lyx-mathjax mathjax-inline">$\langle\mathtt{Alice},\textrm{"Hello, Alice!"}\rangle$</span> delivers the greeting to a single participant.</p><p id="x_7_1_6_0_10">The prototype <span class="small-caps">Syndicate</span> implementations use <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> in a few different ways. First, as discussed, to route a message to a set of actors. Here, the extension of <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> to wildcard-carrying messages is natural. Second, in <span class="small-caps">Syndicate</span> facets, <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> is used in the implementation of <span class="lyx-mathjax mathjax-inline">$\FPROJECTName$</span> (definition <a class="cross-reference" href="#def:mf:project">5.23</a>) to interrogate the actor's memory when a patch arrives, to see whether a given assertion of interest was “already known” or whether it is new to the actor concerned. Finally, <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> finds use in filtering of messages by “firewall” proxies; see section <a class="cross-reference" href="#par:Firewalls">11.3</a>.</p>
<h5 id="x_7_1_7_0_1"><a name="toc_7.1.7"></a><span class="counter subsection"><span>7.1.7</span></span><span class="heading-text subsection">Set operations</span></h5>
<figure class="fullwidth" id="x_7_1_7_0_4"><a name="fig:combine-function"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_2">\begin{align*}
\COMBINEname &amp; :\ \WF{T_{L}}\implies\WF{T_{r}}\implies(\WF{T_{\mathit{ans}}}\wedge\\
&amp; (\TRIE L\rightarrow\TRIE R\rightarrow\TRIE A)\\
&amp; \rightarrow(\TRIE L\rightarrow\TRIE A)\\
&amp; \rightarrow(\TRIE R\rightarrow\TRIE A)\\
&amp; \rightarrow(T_{L}:\TRIE L)\rightarrow(T_{R}:\TRIE R)\rightarrow(T_{\mathit{ans}}:\TRIE A))\\
\\
\COMBINE f{e_{L}}{e_{R}}{T_{L}}{T_{R}} &amp; =g\ T_{L}\ T_{R}\\
\textrm{where }g\ \OK{\alpha}\ T_{R} &amp; =f\ \OK{\alpha}\ T_{R}\\
g\ T_{L}\ \OK{\alpha} &amp; =f\ T_{L}\ \OK{\alpha}\\
g\ \MT\ T_{R} &amp; =\COLLAPSE{(e_{R}\ T_{R})}\\
g\ T_{L}\MT &amp; =\COLLAPSE{(e_{L}\ T_{L})}\\
g\ \BRx{W_{L}}{M_{L}}\ \BRx{W_{R}}{M_{R}} &amp; =\COLLAPSE{(\FOLDKEYS\ g\ \BRx{W_{L}}{M_{L}}\ \BRx{W_{R}}{M_{R}})}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_3">\begin{align*}
\FOLDKEYS &amp; :\ (\TRIE L\rightarrow\TRIE R\rightarrow\TRIE A)\\
&amp; \rightarrow\TRIE L\rightarrow\TRIE R\rightarrow\TRIE A\\
\\
\FOLDKEYS\ g\ \BRx{W_{L}}{M_{L}}\ \BRx{W_{R}}{M_{R}} &amp; =\BRx WM\\
\textrm{where }W &amp; =g\ W_{L}\ W_{R}\\
M &amp; =\{s\mapsto h(s)\ |\ s\in\mathsf{dom}(M_{L})\cup\mathsf{dom}(M_{R}),\\
&amp; \qquad\qquad\qquad h(s)\not=\makeTail{\ARITY s}W\}\\
h(s) &amp; =g\ (\LOOKUP\ M_{L}\ s\ W_{L})\ (\LOOKUP\ M_{R}\ s\ W_{R})\\
\\
\LOOKUP\ M\ s\ T &amp; =\begin{cases}
T' &amp; \textrm{if }(s\mapsto T')\in M\\
\makeTail{\ARITY s}T &amp; \textrm{otherwise}
\end{cases}\\
\\
\COLLAPSE T &amp; =\begin{cases}
\MT &amp; \textrm{if }T=\BR{\MT}{}\\
T &amp; \textrm{otherwise}
\end{cases}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>39</span></span><span class="figcaption-text"><span class="lyx-argument">The <span class="lyx-mathjax mathjax-inline">$\mathit{combine}$</span> function on assertion tries<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:combine-function"></a>The <span class="lyx-mathjax mathjax-inline">$\mathit{combine}$</span> function for performing set operations on assertion tries.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_7_0_5">Algorithms for computing set union, intersection, and difference on well-formed tries carrying various kinds of data in their <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> nodes can be formulated as specializations of a general <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> function (figure <a class="cross-reference" href="#fig:combine-function">39</a>).</p><p id="x_7_1_7_0_6">We are careful to specify that <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> may only be used with well-formed tries. This has an important consequence for the operation of the algorithm: during traversal of the two input tries, if one of the tries is an <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> node, then at the same moment, the other trie is either an <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> or an <span class="lyx-mathjax mathjax-inline">$\MT$</span> node. Since the function <span class="lyx-mathjax mathjax-inline">$f$</span> is called only when one or both of the tries is <span class="lyx-mathjax mathjax-inline">$\OK{}$</span>, we know that <span class="lyx-mathjax mathjax-inline">$f$</span> need only handle <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> and <span class="lyx-mathjax mathjax-inline">$\MT$</span> inputs, leaving treatment of <span class="lyx-mathjax mathjax-inline">$\BRname$</span> nodes entirely to the <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span>/<span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span> functions. The effect of <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> is to walk the interior nodes of the tries it is given, delegating processing of leaf nodes to the <span class="lyx-mathjax mathjax-inline">$f$</span> passed in. In addition, <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> itself produces a well-formed output, given a well-formed input and an <span class="lyx-mathjax mathjax-inline">$f$</span> that answers only <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> or <span class="lyx-mathjax mathjax-inline">$\MT$</span> nodes.</p><p id="x_7_1_7_0_7">The three set operations on <span class="lyx-mathjax mathjax-inline">$\SETTRIE$</span> instances are:</p><p id="x_7_1_7_0_12">
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_8">\begin{align*}
T_{1}\cup T_{2} &amp; =\COMBINE{f_{\mathit{un}}}{id}{id}{T_{1}}{T_{2}}\\
T_{1}\cap T_{2} &amp; =\COMBINE{f_{\mathit{int}}}{(\lambda x.\MT)}{(\lambda x.\MT)}{T_{1}}{T_{2}}\\
T_{1}-T_{2} &amp; =\COMBINE{f_{\mathit{sub}}}{id}{(\lambda x.\MT)}{T_{1}}{T_{2}}
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_9">\begin{align*}
f_{\mathit{un}}\ \OK{()}\ \OK{()} &amp; =\OK{()}\\
f_{\mathit{un}}\ \MT\ T &amp; =T\\
f_{\mathit{un}}\ T\ \MT &amp; =T
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_10">\begin{align*}
f_{\mathit{int}}\ \OK{()}\ \OK{()} &amp; =\OK{()}\\
f_{\mathit{int}}\ \MT\ T &amp; =f_{\mathit{int}}\ T\ \MT=\MT
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_11">\begin{align*}
f_{\mathit{sub}}\ \OK{()}\ \OK{()} &amp; =\MT\\
f_{\mathit{sub}}\ \MT\ T &amp; =\MT\\
f_{\mathit{sub}}\ T\ \MT &amp; =T
\end{align*}
</div></p><p id="x_7_1_7_0_13">The same operations have similar definitions for <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span> instances used to represent dataspace contents, with <span class="lyx-mathjax mathjax-inline">$f$</span> computing various functions over the sets carried in <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> nodes. It is also possible to use <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> asymmetrically, operating on a <span class="lyx-mathjax mathjax-inline">$\SETTRIE$</span> instance and a <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span> instance in various ways.</p>
<div class="theorem-like numbered claim" id="x_7_1_7_0_15">
<p id="x_7_1_7_0_14"><span class="counter numbered claim"><span>7.14</span></span>For each <span class="lyx-mathjax mathjax-inline">$R\in\{\cup,\cap,-\}$</span>, <span class="lyx-mathjax mathjax-inline">$\MEANINGn1{T_{1}\;R\;T_{2}}=\left(\MEANINGn1{T_{1}}\right)\;R\;\left(\MEANINGn1{T_{2}}\right)$</span>.</p><span class="halmos"></span></div><p id="x_7_1_7_0_17">In addition, complements of sets represented as <span class="lyx-mathjax mathjax-inline">$\TRIE1$</span> can be computed by exchanging <span class="lyx-mathjax mathjax-inline">$\MT$</span> nodes for <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> nodes:
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_16">\begin{align*}
\NEGTRIE{\cdot} &amp; :\ \TRIE1\rightarrow\TRIE1\\
\NEGTRIE{\MT} &amp; =\OKunit\\
\NEGTRIE{\OKunit} &amp; =\MT\\
\NEGTRIE{\BR T{s\mapsto T',\dots}} &amp; =\BR{\NEGTRIE T}{s\mapsto\NEGTRIE{T'},\dots}
\end{align*}
</div></p>
<div class="theorem-like numbered example" id="x_7_1_7_0_28">
<figure id="x_7_1_7_0_25"><a name="fig:simple-negation"></a>
<figure id="x_7_1_7_0_20">
<p class="align-center" id="x_7_1_7_0_19"><img id="x_7_1_7_0_18" src="Figures/simple-negated-pattern1.svg" style="width: auto; height: 1.7in;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>40(a)</span></span><span class="figcaption-text">Trie representing all tuples matching <span class="lyx-mathjax mathjax-inline">$(\star,1)$</span>.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_7_1_7_0_23">
<p class="align-center" id="x_7_1_7_0_22"><img id="x_7_1_7_0_21" src="Figures/simple-negated-pattern2.svg" style="width: auto; height: 1.7in;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>40(b)</span></span><span class="figcaption-text">Trie representing the complement of (a).<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p class="align-center" id="x_7_1_7_0_24">&emsp;</p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>40</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:simple-negation"></a>A trie and its complement<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p id="x_7_1_7_0_27"><span class="counter numbered example"><span>7.15</span></span>Consider the set of all tuples <em>not</em> matching <span class="lyx-mathjax mathjax-inline">$(\star,1)$</span>—that is, any assertion that is either not a tuple, not a pair, or has something other than <span class="lyx-mathjax mathjax-inline">$1$</span> as its second element (figure <a class="cross-reference" href="#fig:simple-negation">40</a>):
<div class="lyx-mathjax mathjax-display" id="x_7_1_7_0_26">\begin{align*}
&amp; \NEGTRIE{\PAT1{()}{(\star,1)}}\\
=\; &amp; \NEGTRIE{\BR{\MT}{\ll_{2}\mapsto\BR{\BR{\MT}{1\mapsto\OKunit}}{}}}\\
=\; &amp; \BR{\OKunit}{\ll_{2}\mapsto\BR{\BR{\OKunit}{1\mapsto\MT}}{}}
\end{align*}
</div></p><span class="halmos"></span></div>
<div class="theorem-like numbered claim" id="x_7_1_7_0_30">
<p id="x_7_1_7_0_29"><span class="counter numbered claim"><span>7.16</span></span>If <span class="lyx-mathjax mathjax-inline">$\WFn nT$</span> and <span class="lyx-mathjax mathjax-inline">$T'=\NEGTRIE T$</span> then <span class="lyx-mathjax mathjax-inline">$\MEANINGn n{T'}=\SEXP^{n}-\MEANINGn nT$</span>.</p><span class="halmos"></span></div>
<h5 id="x_7_1_8_0_1"><a name="toc_7.1.8"></a><span class="counter subsection"><span>7.1.8</span></span><span class="heading-text subsection">Projection</span></h5><p id="x_7_1_8_0_2">A key operation on assertion sets is <em>projection, </em>guided by a pattern with embedded binders. Projection is relevant both for the raw dataspace model and <span class="small-caps">Syndicate</span>'s proposed language extensions. Projection is to pattern-matching as sets are to elements of sets, and allows programs to specify and extract relevant portions of assertion sets for later processing.</p><p id="x_7_1_8_0_4">We call the patterns used in projection <em>specifications</em>. Projection specifications over <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span>s include <em>capture marks,</em> <span class="lyx-mathjax mathjax-inline">$\CAP$</span>, and a <em>discard</em> operator, <span class="lyx-mathjax mathjax-inline">$\DISCARD$</span>, both analogous to wildcard:
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_3">\[
\textrm{Projection specifications }p,q\in\PROJ=x\ |\ (p,q,\dots)\ |\ \DISCARD\ |\ \CAP
\]
</div></p><p id="x_7_1_8_0_5">A projection specification both <em>filters</em> and <em>reshapes</em> a given assertion set: it discards entire assertions if they fail to match its structure, and retains only the portions of assertions corresponding to its embedded capture marks.</p>
<figure id="x_7_1_8_0_8"><a name="fig:specification-of-projection"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_6">\begin{align*}
\PROJECTSPECname &amp; :\ \PROJ\rightarrow\SETOF{\SEXP}\rightarrow\SETOF{\SEXP}\\
\PROJECTSPEC p{\ROUTES} &amp; =\{w\ |\ v\in\ROUTES,w=\MATCH pv\}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_7">\begin{align*}
\MATCHname &amp; :\ \PROJ\rightarrow\SEXP^{+}\rightharpoonup\SEXP^{+}\\
\MATCH xx &amp; =()\\
\MATCH x{\star} &amp; =()\\
\MATCH{(p_{0},\dots,p_{n})}{(v_{0}^{+},\dots,v_{n}^{+})} &amp; =\MATCH{p_{0}}{v_{0}^{+}}\times\dots\times\MATCH{p_{n}}{v_{n}^{+}}\\
\MATCH{(p_{0},\dots,p_{n})}{\star} &amp; =\MATCH{p_{0}}{\star}\times\dots\times\MATCH{p_{n}}{\star}\\
\MATCH{\DISCARD}{v^{+}} &amp; =()\\
\MATCH{\CAP}{v^{+}} &amp; =(v^{+})
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>41</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:specification-of-projection"></a><span class="lyx-argument">Specification of <span class="lyx-mathjax mathjax-inline">$\mathit{project}$</span><span class="plain-layout-boundary"></span></span>Specification of <span class="lyx-mathjax mathjax-inline">$\PROJECTname$</span> in terms of sets of <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_8_0_11">Figure <a class="cross-reference" href="#fig:specification-of-projection">41</a> specifies the desired behavior of projection as a function <span class="lyx-mathjax mathjax-inline">$\PROJECTSPECname$</span>, in terms of mathematical sets and a partial function <span class="lyx-mathjax mathjax-inline">$\MATCHname$</span> that performs both filtering and reshaping. It is defined only for <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span>s that have the specified shape, and yields a tuple with an element for each capture mark. For example,
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_9">\begin{align*}
\MATCH{(\mathtt{present},\CAP)}{(\mathtt{present},a)} &amp; =(a)\\
\MATCH{(\mathtt{present},\CAP)}{(\mathtt{says},a,\textrm{"hello"})} &amp; \textrm{ is not defined}\\
\MATCH{(\mathtt{says},\CAP,\CAP)}{(\mathtt{present},a)} &amp; \textrm{ is not defined}\\
\MATCH{(\mathtt{says},\CAP,\CAP)}{(\mathtt{says},a,\textrm{"hello"})} &amp; =(a,\textrm{"hello"})
\end{align*}
</div>
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_10">\begin{align*}
\PROJECTSPEC{(\mathtt{says},\CAP,\CAP)}{\{(\mathtt{present},a),(\mathtt{present},b),(\mathtt{says},a,\textrm{"hello"})\}} &amp; =\{(a,\textrm{"hello"})\}\\
\PROJECTSPEC{(\mathtt{present},\CAP)}{\{(\mathtt{present},a),(\mathtt{present},b),(\mathtt{says},a,\textrm{"hello"})\}} &amp; =\{(a),(b)\}
\end{align*}
</div></p><p id="x_7_1_8_0_13">The implementation of projection is not quite so succinct as the specification. While the main function is simple, its helpers <span class="lyx-mathjax mathjax-inline">$\WALKname$</span> and <span class="lyx-mathjax mathjax-inline">$\WALKCname$</span> (figures <a class="cross-reference" href="#fig:project-walk">42</a> and <a class="cross-reference" href="#fig:project-capture">43</a>) are more complex:
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_12">\begin{align*}
\PROJECTname &amp; :\ \WF T\implies\PROJ\rightarrow T:\TRIE1\rightarrow\TRIE1\\
\PROJECT pT &amp; =\WALK{[p]}T{(\lambda T'.\ T')}
\end{align*}
</div></p>
<figure class="fullwidth" id="x_7_1_8_0_15"><a name="fig:project-walk"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_14">\begin{align*}
\WALKname &amp; :\ \LISTOF{\PROJ}\rightarrow\TRIE1\rightarrow(\TRIE1\rightarrow\TRIE1)\rightarrow\TRIE1\\
\WALK{[]}Tk &amp; =k\ T\\
\WALK{[p,\dots]}{\MT}k &amp; =\MT\\
\WALK{[p,\dots]}{\OKunit}k &amp; =\MT\\
\WALK{[x,p,\dots]}{\BRx TM}k &amp; =\WALK{(\LOOKUP\ M\ x\ T)}{[p,\dots]}k\\
\WALK{[(q_{0},\dots,q_{n}),p,\dots]}{\BRx TM}k &amp; =\WALK{(\LOOKUP\ M\ \LL n\ T)}{[q_{0},\dots,q_{n},p,\dots]}k\\
\WALK{[\DISCARD,p,\dots]}{\BRx TM}k &amp; =\WALK{[p,\dots]}Tk\ \cup\bigcup_{s\in\mathsf{dom}(M)}\WALK{[\underset{{\ARITY s\textrm{ discards}}}{\underbrace{\DISCARD,\DISCARD,\dots}},p,\dots]}{(\LOOKUP\ M\ s\ T)}k\\
\WALK{[\CAP,p,\dots]}{\BRx TM}k &amp; =\WALKC1{\BRx TM}{(\lambda T'.\ \WALK{[p,\dots]}{T'}k)}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>42</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:project-walk"></a>Skipping of unwanted structure during projection<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure class="fullwidth" id="x_7_1_8_0_17"><a name="fig:project-capture"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_8_0_16">\begin{align*}
\WALKCname &amp; :\ \mathbb{N}\rightarrow\TRIE1\rightarrow(\TRIE1\rightarrow\TRIE1)\rightarrow\TRIE1\\
\WALKC0Tk &amp; =k\ T\\
\WALKC{(n+1)}{\MT}k &amp; =\MT\\
\WALKC{(n+1)}{\OKunit}k &amp; =\MT\\
\WALKC{(n+1)}{\BRx TM}k &amp; =\COLLAPSE{\BRx{T'}{\{s\mapsto h(s)\ |\ s\in\mathsf{dom}(M),h(s)\not=\makeTail{\ARITY s}{T'}\}}}\\
&amp; \phantom{=\quad}\begin{aligned}\textrm{where }T' &amp; =\WALKC nTk\\
h(s) &amp; =\WALKC{(n+\ARITY{s)}}{(\LOOKUP\ M\ s\ T)}k
\end{aligned}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>43</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:project-capture"></a>Capturing of structure during projection<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_8_0_18">A precondition to <span class="lyx-mathjax mathjax-inline">$\PROJECTname$</span> is that the input trie be <span class="lyx-mathjax mathjax-inline">$\WFname$</span>; however, the trie that results from the projection is <span class="lyx-mathjax mathjax-inline">$\WFname_{n}$</span> where <span class="lyx-mathjax mathjax-inline">$n$</span> is the number of capture marks in the projection specification given to <span class="lyx-mathjax mathjax-inline">$\PROJECTname$</span>. The helper function <span class="lyx-mathjax mathjax-inline">$\WALKname$</span> follows the structure of the projection specifications in its first argument, discarding portions of the input trie that do not match. When it encounters a capture mark, it transitions to the <span class="lyx-mathjax mathjax-inline">$\WALKCname$</span> helper function, which copies one <span class="lyx-mathjax mathjax-inline">$\SEXP^{+}$</span>'s worth of structure from the input trie to the result. Both functions terminate early in cases of mismatch.</p>
<div class="theorem-like numbered claim" id="x_7_1_8_0_20">
<p id="x_7_1_8_0_19"><span class="counter numbered claim"><span>7.17</span></span>If <span class="lyx-mathjax mathjax-inline">$\WF T$</span> and <span class="lyx-mathjax mathjax-inline">$T'=\PROJECT pT$</span>, then <span class="lyx-mathjax mathjax-inline">$\MEANINGn n{T'}=\PROJECTSPEC p{\left(\MEANINGn1T\right)}$</span> and <span class="lyx-mathjax mathjax-inline">$\WFn n{T'}$</span>, where <span class="lyx-mathjax mathjax-inline">$n$</span> is the number of capture marks in <span class="lyx-mathjax mathjax-inline">$p$</span>.</p><span class="halmos"></span></div><p id="x_7_1_8_0_21">The implementations in <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span> extend the algorithm in two ways: first, they support <span class="lyx-mathjax mathjax-inline">$\TRIE A$</span> for any <span class="lyx-mathjax mathjax-inline">$\mathbf{A}$</span> rather than just <span class="lyx-mathjax mathjax-inline">$\TRIE1$</span>, by allowing customization of the union-function used in the discard case of <span class="lyx-mathjax mathjax-inline">$\WALKname$</span>; and second, they incorporate “and-patterns” in projection specifications, thus allowing the placement of structural conditions on the fragments of assertions to be captured by a capture mark. This latter mainly affects the structure of <span class="lyx-mathjax mathjax-inline">$\WALKCname$</span>, making it more similar to <span class="lyx-mathjax mathjax-inline">$\WALKname$</span>.</p>
<h5 id="x_7_1_9_0_1"><a name="toc_7.1.9"></a><span class="counter subsection"><span>7.1.9</span></span><span class="heading-text subsection">Iteration</span></h5><p id="x_7_1_9_0_2">We often want to examine the assertions in the set represented by some <span class="lyx-mathjax mathjax-inline">$\WFname_{n}$</span> assertion trie, one at a time, accumulating some result as we go. This is only possible when the set is finite, corresponding to a <em>structurally finite</em> trie:</p>
<div class="theorem-like numbered definition named" id="x_7_1_9_0_4">
<p id="x_7_1_9_0_3"><span class="counter numbered definition"><span>7.18</span></span><span class="lyx-argument">Structurally finite tries<span class="plain-layout-boundary"></span></span>A trie with every <span class="lyx-mathjax mathjax-inline">$\BRname$</span> node of the form <span class="lyx-mathjax mathjax-inline">$\BRx{\MT}M$</span> for some <span class="lyx-mathjax mathjax-inline">$M$</span> is called <em>structurally finite</em>.</p><span class="halmos"></span></div>
<div class="theorem-like numbered claim" id="x_7_1_9_0_6">
<p id="x_7_1_9_0_5"><span class="counter numbered claim"><span>7.19</span></span>If a trie <span class="lyx-mathjax mathjax-inline">$T$</span> is structurally finite and <span class="lyx-mathjax mathjax-inline">$\WFn nT$</span>, then <span class="lyx-mathjax mathjax-inline">$\MEANINGn nT$</span> is a finite set.</p><span class="halmos"></span></div>
<figure class="fullwidth" id="x_7_1_9_0_9"><a name="fig:tries-to-sets"></a>
<div class="lyx-mathjax mathjax-display" id="x_7_1_9_0_7">\begin{align*}
\KEYSETname &amp; :\ \WF T\implies T:\TRIE A\rightharpoonup\SETOF{\LISTOF{\SEXP}}\\
\KEYSET T &amp; =\TTAKE1T{[]}{k_{0}}\\
&amp; \phantom{=\quad}\begin{aligned}\textrm{where }k_{0}\ [v,\dots]\ \MT &amp; =\emptyset\\
k_{0}\ [v,\dots]\ \OK{\alpha} &amp; =[v,\dots]
\end{aligned}
\end{align*}
</div><span class="plain-layout-boundary"></span>
<div class="lyx-mathjax mathjax-display" id="x_7_1_9_0_8">\begin{align*}
\TTAKEname &amp; :\ \mathbb{N}\rightarrow\TRIE A\rightarrow\LISTOF{\SEXP}\\
&amp; \rightarrow([\SEXP]\rightarrow\TRIE A\rightharpoonup\SETOF{\LISTOF{\SEXP}})\\
&amp; \rightharpoonup\SETOF{\LISTOF{\SEXP}}\\
\TTAKE0T{vs[v,\dots]}k &amp; =k\ [v,\dots]\ T\\
\TTAKE{(n+1)}{\MT}{[v,\dots]}k &amp; =\emptyset\\
\TTAKE{(n+1)}{\BRx{\MT}M}{[v,\dots]}k &amp; =\bigcup_{(s\mapsto T)\in M}h(s,T)\\
&amp; \begin{aligned}\textrm{where }h(x,T) &amp; =\TTAKE nT{[v,\dots,x]}k\\
h(\LL m,T) &amp; =\TTAKE mT{[]}k'\\
k'([w,\dots],T') &amp; =\TTAKE n{T'}{[v,\dots,(w,\dots)]}k
\end{aligned}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>44</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:tries-to-sets"></a><span class="lyx-argument">Conversion of assertion tries to sets<span class="plain-layout-boundary"></span></span>Conversion of finite, <span class="lyx-mathjax mathjax-inline">$\WFname$</span> tries to sets of (lists of) <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_9_0_10">The partial function <span class="lyx-mathjax mathjax-inline">$\KEYSETname$</span> shown in figure <a class="cross-reference" href="#fig:tries-to-sets">44</a> traverses a <span class="lyx-mathjax mathjax-inline">$\WFname$</span> trie, reconstructing <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s from the tokens laid out along paths in the trie. Tuple-marker tokens cause construction of a nested <span class="lyx-mathjax mathjax-inline">$\SEXP$</span> tuple in the output. The function is defined only for structurally finite input tries. The well-formedness of the input ensures that <span class="lyx-mathjax mathjax-inline">$\TTAKEname$</span> and <span class="lyx-mathjax mathjax-inline">$k_{0}$</span> are exhaustively defined despite appearances:</p>
<ul id="x_7_1_9_0_13"><li id="x_7_1_9_0_11"><span class="lyx-mathjax mathjax-inline">$\OK{\alpha}$</span> cannot appear as second argument to <span class="lyx-mathjax mathjax-inline">$\TTAKEname$</span> except when the first argument is <span class="lyx-mathjax mathjax-inline">$0$</span>, because that would imply that the trie was “short”: that paths from the root to the <span class="lyx-mathjax mathjax-inline">$\OK{\alpha}$</span> node were not long enough for the original trie to be <span class="lyx-mathjax mathjax-inline">$\WFname$</span>.</li><li id="x_7_1_9_0_12">no <span class="lyx-mathjax mathjax-inline">$\BRname$</span> node can appear as argument to <span class="lyx-mathjax mathjax-inline">$k_{0}$</span>, because that would imply that the trie was “long”: that paths from the root included too many tokens for the original trie to be <span class="lyx-mathjax mathjax-inline">$\WFname$</span>.</li></ul>
<h5 id="x_7_1_10_0_1"><a name="toc_7.1.10"></a><span class="counter subsection"><span>7.1.10</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Implementation-Considerations"></a><a name="subsec:Implementation-Considerations"></a>Implementation considerations</span></h5>
<h6 class="unnumbered" id="x_7_1_10_0_2"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Just-in-time tokenization.</span></h6><p id="x_7_1_10_0_3">As presented, <span class="lyx-mathjax mathjax-inline">$\SEARCHname$</span> requires any sought <span class="lyx-mathjax mathjax-inline">$\SEXP$</span> to have been converted to a token sequence up-front. The implementations perform this conversion just-in-time, thereby avoiding the need to examine uninteresting portions of input <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s and the need to embed a trie in variable numbers of <span class="lyx-mathjax mathjax-inline">$\BRname$</span> wrappers in the case when a tuple-marker is not explicitly catered for in a <span class="lyx-mathjax mathjax-inline">$\BRname$</span> node.</p>
<h6 class="unnumbered" id="x_7_1_10_0_4"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Examination of only the smaller input.</span></h6><p id="x_7_1_10_0_6">The version of <span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span> shown in figure <a class="cross-reference" href="#fig:combine-function">39</a> captures the essence of the algorithm, but suffers from an inefficiency that is both avoidable and critically important to an efficient implementation of <span class="small-caps">Syndicate</span>. Consider a situation where a <span class="small-caps">Syndicate</span> program encodes actor-like point-to-point message delivery semantics, where each actor is addressed by a unique integer, and expresses interest in messages addressed to it by asserting <span class="lyx-mathjax mathjax-inline">$\{?(\mathit{id},\star)\}$</span>. In situations with a large number <span class="lyx-mathjax mathjax-inline">$n$</span> of running actors, the resulting tree is wide but shallow (figure <a class="cross-reference" href="#fig:wide-shallow-trie">45(a)</a>). Imagine now spawning a new actor with <span class="lyx-mathjax mathjax-inline">$\mathit{id}=n+1$</span>. The new actor asserts <span class="lyx-mathjax mathjax-inline">$\{?(n+1,\star)\}$</span> by issuing a patch containing the assertion trie
<div class="lyx-mathjax mathjax-display" id="x_7_1_10_0_5">\[
\PAT{\SETOF{\LOC}}{\{n+1\}}{("?",(n+1,\star))}
\]
</div>shown in figure <a class="cross-reference" href="#fig:wide-shallow-trie2">45(b)</a>.</p>
<figure id="x_7_1_10_0_16">
<figure id="x_7_1_10_0_9"><a name="fig:wide-shallow-trie"></a>
<p class="align-center" id="x_7_1_10_0_8"><img id="x_7_1_10_0_7" src="Figures/wide-actor-trie.svg" style="width: 4.36in; height: auto;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>45(a)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:wide-shallow-trie"></a>A wide but shallow routing trie<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_7_1_10_0_14"><a name="fig:wide-shallow-trie2"></a>
<p class="align-center" id="x_7_1_10_0_13">
<div class="frameless-box" id="x_7_1_10_0_12">
<p class="align-center" id="x_7_1_10_0_11"><img id="x_7_1_10_0_10" src="Figures/wide-actor-trie2.svg" style="width: 4.36in; height: auto;"/></p><span class="plain-layout-boundary"></span></div></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>45(b)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:wide-shallow-trie2"></a>Assertion trie produced by a new actor<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p class="align-center" id="x_7_1_10_0_15">&emsp;</p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>45</span></span><span class="figcaption-text">Wide, shallow assertion tries<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_10_0_17">Computing the union of these tries in order to update the containing dataspace involves consideration of <em>every</em> edge leading away from the node following the <tt>"?"</tt> edge in figure <a class="cross-reference" href="#fig:wide-shallow-trie">45(a)</a>—a total of <span class="lyx-mathjax mathjax-inline">$O(n)$</span> work. However, nothing along any of the existing branches changes. An efficient <span class="small-caps">Syndicate</span> implementation demands that it be possible to combine a smaller with a larger trie doing only an amount of work proportional to the size of the smaller trie.</p><p id="x_7_1_10_0_18">The key is to alter <span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span> so that it treats the larger of its two arguments as a base against which the smaller of the two is applied. Accordingly, <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> is modified to accept an additional pair of functions which, given the larger trie, determine the starting point for <span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span>. After these changes, set operations on tries take time at each step proportional to the number of edges leading away from the <em>smaller</em> of the two given <span class="lyx-mathjax mathjax-inline">$\BRname$</span> nodes.</p><p id="x_7_1_10_0_19">One consequence of this requirement is that it must be possible to efficiently count the number of edges leading away from a node. Not all hash-table or dictionary-like data structures offered by programming languages satisfy this requirement; some care must be taken in these cases.</p>
<h6 class="unnumbered" id="x_7_1_10_0_20"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Canonical constructors.</span></h6><p id="x_7_1_10_0_21">We use canonicalizing constructors extensively to enforce invariants that would otherwise be distributed throughout the codebase. For example, the uses of <span class="lyx-mathjax mathjax-inline">$\mathit{collapse}$</span> in <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> are implicit in our functions for constructing and extending <span class="lyx-mathjax mathjax-inline">$\BRname$</span> instances.</p>
<h6 class="unnumbered" id="x_7_1_10_0_22"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Hash-consing for cheap equality testing.</span></h6>
<div class="footnote" id="fn_7_74"><span class="counter footnote-counter"><span>74</span></span>According to <span class="citation citet"><a class="citation" id="cite-138" href="#bib-Baker1992a"><span>Baker<span class="parens"> (</span>1992<span class="parens">)</span></span></a></span>, “Hash consing was invented by Ershov <span class="citation citeyearpar"><a class="citation" id="cite-139" href="#bib-Ershov1958">1958</a></span> for the detection of common subexpressions in a compiler and popularized by Goto <span class="citation citeyearpar"><a class="citation" id="cite-140" href="#bib-Goto1976">1976</a></span> for use in a Lisp-based symbolic algebra systems.”<span class="plain-layout-boundary"></span></div><p id="x_7_1_10_0_23">Naively implemented, the side condition <span class="lyx-mathjax mathjax-inline">$h(s)\not=\makeTail{\ARITY s}W$</span> in the definition of <span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span> may examine a large amount of the structure of the tries on each side of the inequality. The time to decide this inequality is unacceptable, because the test is on the “hot” path of every set operation on assertion tries. Implementations must provide a cheap yet accurate way of testing equality between tries. In <span class="small-caps">Syndicate/rkt</span>, we hash-cons <span class="citation citep">(<a class="citation" id="cite-135" href="#bib-Ershov1958">Ershov 1958</a>; <a class="citation" id="cite-136" href="#bib-Goubault1994">Goubault 1994</a>; <a class="citation" id="cite-137" href="#bib-Filliatre2006">Filliâtre and Conchon 2006</a>)</span> to force pointer-equality (<tt>eq?</tt>) to hold exactly when set equality (<tt>equal?</tt>) holds for our tries.<label class="footnote-number" for="fn_7_74">74</label> </p><p id="x_7_1_10_0_24">Unfortunately, however, <span class="small-caps">Syndicate/js</span> cannot currently provide this optimization. If we implemented hash-consing in JavaScript, we would forfeit proper garbage-collection behavior because JavaScript lacks suitable hooks into the garbage-collection subsystem. The <tt>WeakMap</tt> and <tt>WeakSet</tt> objects provided by ECMAScript 6 are unsuited to the task, since they are keyed by object identity, not object structure. Therefore, <span class="small-caps">Syndicate/js</span> simply uses naive recursive structural comparison of tries in <span class="lyx-mathjax mathjax-inline">$\FOLDKEYS$</span>. The <span class="small-caps">Syndicate/js</span> programs we have written to date have performed well enough to be usable, despite the performance penalty.</p>
<h6 class="unnumbered" id="x_7_1_10_0_25"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Efficiently canonicalizable dictionaries.</span></h6>
<div class="footnote" id="fn_7_75"><span class="counter footnote-counter"><span>75</span></span><span class="citation citet"><a class="citation" id="cite-145" href="#bib-Sundar1989"><span>Sundar and Tarjan<span class="parens"> (</span>1989<span class="parens">)</span></span></a></span> discuss the <em>unique representation problem</em> for binary search trees; <span class="citation citet"><a class="citation" id="cite-146" href="#bib-Andersson1995"><span>Andersson and Ottmann<span class="parens"> (</span>1995<span class="parens">)</span></span></a></span> improve on Sundar and Tarjan's solution. The property of canonicity in our setting is also known as <em>history-independence</em>. Pugh's <em>skip lists</em> built with a deterministic hash function offer a potential alternative to our pseudo-randomized treaps <span class="citation citep">(<a class="citation" id="cite-147" href="#bib-Pugh1990">Pugh 1990</a>; <a class="citation" id="cite-148" href="#bib-Golovin2010">Golovin 2010</a>)</span>, though their pure-functional implementation may be challenging.<span class="plain-layout-boundary"></span></div><p id="x_7_1_10_0_26">Even when hash-consing can ensure that the results of <tt>eq?</tt> and <tt>equal?</tt> are identical, care must be taken in choosing a representation for <span class="lyx-mathjax mathjax-inline">$\BRname$</span> nodes. Initially, we used Racket's built-in hash tables. However, for nodes with many edges, the hash table itself grew large, resulting in a large amount of time spent in <tt>canonicalize</tt>. To avoid this problem we need a representation of collections of edges that can be efficiently searched, efficiently counted, and efficiently updated, while also admitting a canonical representation suitable for hash-consing. An ideal data structure for the situation where tokens can be represented as bit strings is the <em>crit-bit tree</em> <span class="citation citep">(<a class="citation" id="cite-141" href="#bib-Bernstein2004">Bernstein 2004</a>; <a class="citation" id="cite-142" href="#bib-Finch2016">Finch 2016</a>)</span>; however, rather than force repeated conversion back-and-forth between Racket values and bit strings, we chose instead to use <em>treaps</em> <span class="citation citep">(<a class="citation" id="cite-143" href="#bib-Seidel1996">Seidel and Aragon 1996</a>; <a class="citation" id="cite-144" href="#bib-Cormen2009">Cormen et al. 2009</a> <span class="citation-after">problem 13-4</span>)</span>. Treaps are trees which augment each node with a randomly-chosen <em>priority</em>, used to ensure a balanced tree. However, we require deterministic, canonical tree shapes for each unique set of key-value pairs. A deterministically-chosen priority can easily lead to unbalanced trees. The compromise that we have settled on is to use a fragment of a strong hash function to compute a deterministic pseudo-random priority from the key associated with each tree node. Experimental results (chapter <a class="cross-reference" href="#CHAP:PERFORMANCE">10</a>) show that the results are acceptable, though questions remain as to whether this deterministic pseudo-random function leads to well-balanced trees in general.<label class="footnote-number" for="fn_7_75">75</label></p>
<h6 class="unnumbered" id="x_7_1_10_0_27"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Efficiently canonicalizable sets.</span></h6><p id="x_7_1_10_0_28">Care must also be taken to ensure that the sets of actor IDs used in <span class="lyx-mathjax mathjax-inline">$\OK{}$</span> nodes when representing values from <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span> are efficiently canonicalizable. The implementation reuses canonicalized treaps (mapping keys to <tt>#t</tt>) for this purpose.</p>
<h6 class="unnumbered" id="x_7_1_10_0_29"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Compound data structures.</span></h6><p id="x_7_1_10_0_30">Our <span class="lyx-mathjax mathjax-inline">$\SEXP$</span>s include <span class="lyx-mathjax mathjax-inline">$n$</span>-tuples as the only compound, represented with special <span class="lyx-mathjax mathjax-inline">$\LL n$</span> tokens when converted to token sequences. By contrast, both Racket and JavaScript enjoy a rich variety of compound data structures. Racket offers the programmer <em>structures</em>, <em>lists</em>, and <em>vectors</em>, while JavaScript offers <em>arrays</em> and <em>objects</em>.</p><p id="x_7_1_10_0_31">Racket's structures may be interrogated to determine their <em>struct type</em>, which in turn can be examined to determine its arity. This suggests replacing generic tuple-markers <span class="lyx-mathjax mathjax-inline">$\LL n$</span> with a tuple-marker for each struct type. For example, a structure type <tt>present</tt> with a single field would appear in an assertion trie as a tuple-marker <span class="lyx-mathjax mathjax-inline">$\mathit{present}_{1}$</span>; and a structure type <tt>says</tt> with two fields would appear as <span class="lyx-mathjax mathjax-inline">$\mathit{says}_{2}$</span>. Lists and vectors are represented with tuple-markers <span class="lyx-mathjax mathjax-inline">$\mathit{list}_{n}$</span> and <span class="lyx-mathjax mathjax-inline">$\mathit{vector}_{n}$</span>, for arbitrary <span class="lyx-mathjax mathjax-inline">$n$</span>, respectively. Improper lists are disallowed: an alternative is to support <em>pairs</em> natively, and then to represent lists as nested pairs.</p><p id="x_7_1_10_0_32">JavaScript arrays are treated roughly as Racket's vectors, and for programmer convenience, <span class="small-caps">Syndicate/js</span> includes a crude <tt>struct</tt>-like facility, as well, allowing rough parity and reasonably smooth interoperability with <span class="small-caps">Syndicate/rkt</span>'s assertions. JavaScript objects present a problem, however. There is no “natural” interpretation of an object with an embedded wildcard as a pattern over assertions: should fields not mentioned in the “pattern” be ignored for the purposes of matching, or should they cause a mismatch? There is no clear “best” design option; for now, inclusion of assertions containing objects is forbidden. Similar problems occur in Racket's own built-in pattern-matcher, <tt>racket/match</tt>, when it comes to hash tables; patterns over hash tables come in many varieties. It may be possible to support objects and object patterns in an ergonomic way in future by taking inspiration from the use of the “interleave” operator as seen in pattern languages for XML <span class="citation citep">(<a class="citation" id="cite-149" href="#bib-Clark2001">Clark and Murata 2001</a>)</span>.</p>
<h6 class="unnumbered" id="x_7_1_10_0_33"><a name="toc_7.1.10"></a><span class="heading-text paragraph">Representing wildcard.</span></h6>
<figure id="x_7_1_10_0_40"><a name="fig:Representing-Wildcard"></a>
<pre class="listing" id="x_7_1_10_0_34"><code>;; A Question is a
;; (question DomainName QueryType QueryClass QuestionContext)
;; representing a DNS question: "What are the RRs for the given name,
;; type and class?" as well as a possible parent question that the
;; answer to this question is to contribute to the answer to.
</code></pre><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_7_1_10_0_35">(a)</p><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span>
<pre class="listing" id="x_7_1_10_0_36"><code>(struct: (TName TType TClass TContext)
question-repr
([name : TName] [type : TType] [class : TClass] [context : TContext])
#:transparent)
(pseudo-substruct: (question-repr DomainName
QueryType
QueryClass
QuestionContext)
Question question question?)
(pseudo-substruct: (question-repr (U Wild DomainName)
(U Wild QueryType)
(U Wild QueryClass)
(U Wild QuestionContext))
QuestionPattern question-pattern question-pattern?)
</code></pre><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_7_1_10_0_37">(b)</p><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span>
<pre class="listing" id="x_7_1_10_0_38"><code>(struct question (name type class context) #:transparent)
</code></pre><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_7_1_10_0_39">(c)</p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>46</span></span><span class="figcaption-text"><span class="lyx-argument">Typed Racket assertion struct definitions<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Representing-Wildcard"></a>Typed Racket and Racket code describing a structure type, <tt>Question</tt>, used in <span class="small-caps">Syndicate</span> messages and assertions. (a) The comment remained the same in both implementations. (b) The Typed Racket implementation. (c) The untyped Racket implementation.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_10_0_41">In languages like Typed Racket <span class="citation citep">(<a class="citation" id="cite-150" href="#bib-Tobin-Hochstadt2008">Tobin-Hochstadt and Felleisen 2008</a>)</span>, the types of values that may appear in fields of structures are precisely specified. Our trick of representing patterns over structures by embedding a special marker value does not work in this setting. Early experiments with a Typed Racket implementation of <span class="small-caps">Syndicate</span> required painstaking work to specify</p>
<ul id="x_7_1_10_0_45"><li id="x_7_1_10_0_42">the structure type itself with type parameters for all fields that could potentially carry a wildcard; plus</li><li id="x_7_1_10_0_43">an auxiliary type definition that instantiated the basic type with concrete types, for use in value contexts; and</li><li id="x_7_1_10_0_44">another that instantiated it again, with concrete types <em>plus a <tt>Wild</tt> type</em>, for use in pattern contexts.</li></ul><p id="x_7_1_10_0_46">The result proved awkward, verbose and brittle, as demonstrated by the example shown in figure <a class="cross-reference" href="#fig:Representing-Wildcard">46</a>. The “hack” of representing wildcard as an ordinary value does not work well for typed languages; instead, I suspect that deeper integration of wildcards with the type system is indicated.</p><p id="x_7_1_10_0_47">Despite the poor ergonomics of the experimental approach explored in Typed Racket, the ability of the system to <em>forbid </em>wildcard from appearing in certain positions was useful. Future work on type systems for <span class="small-caps">Syndicate</span> should support this feature: it allows static encoding of restrictions on the kinds of patterns that may be placed into the shared dataspace. For example, one application is to forbid actors from asserting <span class="lyx-mathjax mathjax-inline">$?(\star,\star)$</span> in situations where they should only be allowed to subscribe to messages explicitly addressed to them, <span class="lyx-mathjax mathjax-inline">$?(\mathit{id},\star)$</span>.</p>
<h5 id="x_7_1_11_0_1"><a name="toc_7.1.11"></a><span class="counter subsection"><span>7.1.11</span></span><span class="heading-text subsection">Evaluation of assertion tries</span></h5><p id="x_7_1_11_0_2">At the beginning of the subsection, we listed a handful of requirements that a worthy assertion set representation must satisfy. Let us revisit them in light of the presented design:</p>
<dl id="x_7_1_11_0_11"><dt id="x_7_1_11_0_3">Efficient&nbsp;computation&nbsp;of&nbsp;metafunctions.</dt><dd id="x_7_1_11_0_4"> The set operations needed by the core metafunctions of <span class="small-caps">Syndicate</span> can be effectively implemented in terms of assertion trie operations. By careful choice of data structure and implementation technique (section <a class="cross-reference" href="#subsec:Implementation-Considerations">7.1.10</a>), we can efficiently update our dataspace structures as changes are made; that is, without having to traverse the entirety of the dataspace.</dd><dt id="x_7_1_11_0_5">Efficient&nbsp;message&nbsp;routing.</dt><dd id="x_7_1_11_0_6"> Assertion tries can efficiently route messages to sets of actors (section <a class="cross-reference" href="#subsec:Searching">7.1.6</a>).</dd><dt id="x_7_1_11_0_7">Compactness.</dt><dd id="x_7_1_11_0_8"> Use of hash-consing and elimination of redundant branches in trie <span class="lyx-mathjax mathjax-inline">$\BRname$</span> nodes ensures that dataspace representations stay compact (section <a class="cross-reference" href="#subsec:Implementation-Considerations">7.1.10</a>).</dd><dt id="x_7_1_11_0_9">Generality.</dt><dd id="x_7_1_11_0_10"> Assertion tries support semi-structured data well, including local variations such as <em>structs</em> (Racket) and <em>arrays</em> (JavaScript). Support for hash-tables and objects remains future work, along with improved techniques for specifying allowable wildcard positions in assertions in typed languages.</dd></dl>
<h5 id="x_7_1_12_0_1"><a name="toc_7.1.12"></a><span class="counter subsection"><span>7.1.12</span></span><span class="heading-text subsection">Work related to assertion tries</span></h5><p id="x_7_1_12_0_2">The routing problem faced by <span class="small-caps">Syndicate</span> is a recurring challenge in networking, distributed systems, and coordination languages. Tries matching prefixes of <em>flat</em> data find frequent application in IP datagram routing <span class="citation citep">(<a class="citation" id="cite-151" href="#bib-Sklower1991">Sklower 1991</a>)</span> and are also used for topic-matching in industrial publish-subscribe middleware <span class="citation citep">(<a class="citation" id="cite-152" href="#bib-Eugster2003">Eugster et al. 2003</a>; <a class="citation" id="cite-153" href="#bib-Baldoni2005">Baldoni, Querzoni and Virgillito 2005</a>)</span>. I do not know of any other uses of tries exploiting visibly-pushdown languages <span class="citation citep">(<a class="citation" id="cite-154" href="#bib-Alur2009">Alur and Madhusudan 2009</a>; <a class="citation" id="cite-155" href="#bib-Alur2007">Alur 2007</a>)</span> (VPLs) for simultaneously evaluating multiple patterns over semi-structured data (such as the language of our assertions), though Mozafari et al. <span class="citation citep">(<a class="citation" id="cite-156" href="#bib-Mozafari2012">Mozafari, Zeng and Zaniolo 2012</a>)</span> compile single XPath queries into NFAs using VPLs in a complex event processing setting. A cousin to the technique described in this section is YFilter <span class="citation citep">(<a class="citation" id="cite-157" href="#bib-Diao2003">Diao et al. 2003</a>)</span>, which uses tries to aggregate multiple XPath queries into a single NFA for routing XML documents to collections of subscriptions. Depth in their tries corresponds to depth in the XML document; depth in ours, to <em>position</em> in the input tree.</p><p id="x_7_1_12_0_3">More closely related to our tries are the tries of <span class="citation citet"><a class="citation" id="cite-158" href="#bib-Hinze2000"><span>Hinze<span class="parens"> (</span>2000<span class="parens">)</span></span></a></span>, keyed by type-directed preorder readings of tree-shaped values. Hinzes tries, like those presented here, have implicit “pop” tokens; however, they rely on types, where our tries rely merely on arity, which may be computed either dynamically (as we do) or statically, and they furthermore lack wildcards in any form.</p><p id="x_7_1_12_0_4"><span class="citation citet"><a class="citation" id="cite-159" href="#bib-Ionescu2010"><span>Ionescu<span class="parens"> (</span>2010<span class="parens">)</span></span></a></span> presents a trie including a form of wildcard, and compiles it to a DFA via an equivalent NFA that corresponds directly to the trie. He reports that <em>backtracking</em> is the chief disadvantage of the naive trie representation they chose, and that compilation to DFA avoided this problem. However, the DFA representation is no panacea: he writes that “it occupies significantly more memory than the trie; there is a significant cost for adding new bindings, since the entire DFA has to be dropped and rebuilt; and it is more complex and therefore harder to implement and maintain.” Furthermore, it is not clear how to extend it to more general forms of predicate over tokens, as sketched above for our tries.</p><p id="x_7_1_12_0_5">In previously-published work <span class="citation citep">(<a class="citation" id="cite-160" href="#bib-Garnock-Jones2016a">Garnock-Jones and Felleisen 2016</a>)</span>, we introduced our trie structure, but used distinct “push” and “pop” tokens, <span class="lyx-mathjax mathjax-inline">$\ll$</span> and <span class="lyx-mathjax mathjax-inline">$\gg$</span>, which were not labeled with the arity of the tuple nested between them. Here, we use a family of “push” tokens with an associated arity instead, leaving the “pop” implicit. While using an explicit “pop” token allows prefix-matching of sequences (via a special <span class="lyx-mathjax mathjax-inline">$\mathsf{tl}()$</span> trie constructor representing a arbitrary number of <em>balanced </em>tokens, followed by a “pop” token), there are a number of disadvantages that leaving “pop” tokens implicit ameliorates. Most importantly, <span class="small-caps">Syndicate</span> relies heavily on extracting sets of assertions labeled with constructors such as <span class="lyx-mathjax mathjax-inline">$\downharpoonleft$</span> or <span class="lyx-mathjax mathjax-inline">$?$</span> from larger assertion sets.</p>
<figure class="fullwidth" id="x_7_1_12_0_9"><a name="fig:Extracting-with-pop"></a>
<p class="align-center" id="x_7_1_12_0_8"><img id="x_7_1_12_0_6" src="Figures/push-pop-explicit1.svg" style="width: auto; height: 2in;"/><span class="implies-raisebox-hack"><span class="lyx-mathjax mathjax-inline">$\implies$</span></span><img id="x_7_1_12_0_7" src="Figures/push-pop-explicit2.svg" style="width: auto; height: 2in;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>47</span></span><span class="figcaption-text"><span class="lyx-argument">Trie projection, explicit “pop” tokens<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Extracting-with-pop"></a>Extracting assertions labeled by some constructor, using explicit “pop” tokens<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure class="fullwidth" id="x_7_1_12_0_13"><a name="fig:Extracting-without-pop"></a>
<p class="align-center" id="x_7_1_12_0_12"><img id="x_7_1_12_0_10" src="Figures/push-pop-implicit1.svg" style="width: auto; height: 2in;"/><span class="implies-raisebox-hack"><span class="lyx-mathjax mathjax-inline">$\implies$</span></span><img id="x_7_1_12_0_11" src="Figures/push-pop-implicit2.svg" style="width: auto; height: 2in;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>48</span></span><span class="figcaption-text"><span class="lyx-argument">Trie projection, implicit “pop” tokens<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Extracting-without-pop"></a>Extracting assertions labeled by some constructor, using implicit “pop” tokens and arity-labelled “push” tokens.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_1_12_0_14">For example, it is common to wish to compute the set of assertions <span class="lyx-mathjax mathjax-inline">$\{c\ |\ \downharpoonleft c\in\ROUTES\}$</span> to be relayed to an outer dataspace from some local set of assertions <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span>; or to compute the set of current assertions in some dataspace <span class="lyx-mathjax mathjax-inline">$R$</span> that are relevant to some <span class="lyx-mathjax mathjax-inline">$j$</span>-labeled actor, <span class="lyx-mathjax mathjax-inline">$\{c\ |\ (c,k)\in R,(?c,j)\in R\}$</span>. To do so using explicit “pop” tokens, we must extract the portion of the trie <em>between</em> the “push” and “pop” tokens surrounding the structured terms <span class="lyx-mathjax mathjax-inline">$\downharpoonleft c$</span> and <span class="lyx-mathjax mathjax-inline">$?c$</span>, as shown in figure <a class="cross-reference" href="#fig:Extracting-with-pop">47</a>. By omitting the “pop” token and instead labeling the “push” token with an arity, we are able to simply discard two tokens, <span class="lyx-mathjax mathjax-inline">$\LL2$</span> and <span class="lyx-mathjax mathjax-inline">$?$</span>, thereby avoiding traversal of the remainder of the trie, as shown in figure <a class="cross-reference" href="#fig:Extracting-without-pop">48</a>. A secondary benefit is simplicity: the algorithm presented in our previous publication involved the <span class="lyx-mathjax mathjax-inline">$\mathsf{tl}()$</span> constructor mentioned above, while the presentation we choose here avoids this complication.</p>
<h4 id="x_7_2_0_0_1"><a name="toc_7.2"></a><span class="counter section"><span>7.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:implementing-dataspaces"></a><a name="sec:implementing-dataspaces"></a>Implementing the dataspace model</span></h4><p id="x_7_2_0_0_2">The prototype implementations of <span class="small-caps">Syndicate</span> closely follow the formal model described in chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>. <span class="small-caps">Syndicate/rkt</span> is written in a pure functional style, taking the signature of behavior functions as its central organizing principle. <span class="small-caps">Syndicate/js</span> is written in a more imperative style, making use of object-oriented idioms appropriate to JavaScript programming.</p><p id="x_7_2_0_0_3">There are two important differences between the model as described and as implemented. First, where the model treats dataspaces specially, the implementation treats them just like any other kind of actor. To do this, the interface to behavior functions is altered slightly. Second, the compactness of the model hides a number of useful abstractions, and the implementation benefits from explicitly recognizing these. In particular, the implementation separates representation of dataspace contents from the implementation of dataspace actors, and introduces a data structure that corresponds to the existential packages <span class="lyx-mathjax mathjax-inline">$\TBehPack{\tau}\subset\TBeh$</span> of the model (figure <a class="cross-reference" href="#fig:DS-evaluation-syntax">14</a>), precisely capturing the state of a running actor. The former allows reuse of the dataspace structure in other code, and the latter not only allows decomposition of the dataspace behavior into simpler components but also provides a useful interface to general reflective manipulation of actors.</p><p id="x_7_2_0_0_4">The implementation is layered. The innermost layer (section <a class="cross-reference" href="#subsec:Assertions">7.2.1</a>) consists of the implementation of assertion tries along with utilities for hash-consing and implementations of (canonicalized) maps and sets. It is at this level that the mapping between host-language data structures and <span class="small-caps">Syndicate</span> assertions is made. The second layer (section <a class="cross-reference" href="#subsec:Patches-and-multiplexors">7.2.2</a>) comprises two central data-structures. First, <em>patches</em> describe changes in assertion sets. Second, <em>multiplexors</em> or <em>muxes</em> form the central structure of each <span class="small-caps">Syndicate</span> dataspace; namely, the map between assertions and actor IDs. The final layer (sections <a class="cross-reference" href="#subsec:Processes-and-behavior-functions">7.2.3</a><a class="cross-reference" href="#subsec:Relays">7.2.5</a>) contains the data-structures and behavior functions implementing the semantics of the dataspace model itself.</p>
<h5 id="x_7_2_1_0_1"><a name="toc_7.2.1"></a><span class="counter subsection"><span>7.2.1</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Assertions"></a><a name="subsec:Assertions"></a>Assertions</span></h5><p id="x_7_2_1_0_2">An implementation of assertion tries in a given language must map that language's data structures onto the tokens <span class="lyx-mathjax mathjax-inline">$\TOK$</span> that label edges in <span class="lyx-mathjax mathjax-inline">$\BRname$</span> nodes. Each token must have an arity associated with it. It must also be possible to map <em>backwards</em> from a sequence of tokens to an implementation-language value. This means making choices about the representation of containers such as pairs, lists, vectors, sets, hash tables, <tt>struct</tt>s, reference cells, and objects, as well as about non-container data such as numbers, strings, symbols, and procedures.</p>
<div class="footnote" id="fn_7_76"><span class="counter footnote-counter"><span>76</span></span>It is left to future work to incorporate patterns over objects into <span class="small-caps">Syndicate</span> and its trie data structures.<span class="plain-layout-boundary"></span></div><p id="x_7_2_1_0_3">The prototype implementations include non-container data directly in <span class="lyx-mathjax mathjax-inline">$\TOK$</span>, each with arity <span class="lyx-mathjax mathjax-inline">$0$</span>. The reverse mapping from such tokens to host-language data is immediate. <em>Objects</em> in Racket <span class="citation citep">(<a class="citation" id="cite-161" href="#bib-Flatt2006">Flatt, Findler and Felleisen 2006</a>)</span> are also treated as non-compound in order to sidestep difficulties generically analyzing such objects as well as generically reconstructing them from token sequences. Racket's procedures are also treated as atomic data. Likewise, Racket's “boxes”, mutable reference cells, are treated as opaque atoms, following Baker's <tt>egal</tt> design <span class="citation citep">(<a class="citation" id="cite-162" href="#bib-Baker1993">Baker 1993</a>)</span>. For simplicity, <span class="small-caps">Syndicate/js</span> restricts the range of assertions able to be placed within its dataspaces, limiting them to atoms (including procedures, as for Racket), arrays, and “structs”. In particular, JavaScript objects (dictionaries) are forbidden entirely; to see why, consider the many different possible patterns one might wish to write over unordered key-value dictionaries, and the demands that each places on our trie data structure.<label class="footnote-number" for="fn_7_76">76</label></p>
<div class="footnote" id="fn_7_77"><span class="counter footnote-counter"><span>77</span></span>Racket pairs that are not part of a proper list may not be used in assertions, since modern Racket style eschews non-list uses of pairs, and accommodating both list and non-list uses would significantly complicate matters.<span class="plain-layout-boundary"></span></div><p id="x_7_2_1_0_4">Lists are handled with a family of tokens <span class="lyx-mathjax mathjax-inline">$\{\LISTTOK0,\LISTTOK1,\dots\}$</span> for marking the beginning of a container in a token sequence. Arrays and vectors are similar. The arity of <span class="lyx-mathjax mathjax-inline">$\LISTTOK n$</span> is just <span class="lyx-mathjax mathjax-inline">$n$</span>.<label class="footnote-number" for="fn_7_77">77</label></p><p id="x_7_2_1_0_5">Sets and hash tables pose a problem. The relevant equivalences for sets and tables do not coincide with the natural notion of equivalence for sequences of tokens. Therefore, the implementations treat sets and hash tables as opaque atoms when part of an assertion.</p><p id="x_7_2_1_0_8">Racket's <tt>struct</tt>s are the primary means by which programmers extend the data types of the language, and as such are prominent in <span class="small-caps">Syndicate/rkt</span> protocols. JavaScript does not include a native <tt>struct</tt>-like facility, and so <span class="small-caps">Syndicate/js</span> makes heavy use of a small support library providing a rough equivalent. In both languages, we may retrieve a <em>structure type</em> object describing the arity of a given structure instance, plus a sequence of the structure's field values. Furthermore, given a structure type and a sequence of field values, we may reconstruct a structure instance. We include these structure type objects in <span class="lyx-mathjax mathjax-inline">$\TOK$</span>. Each <tt>struct</tt> definition of the form
<div class="lyx-mathjax mathjax-display" id="x_7_2_1_0_6">\[
\mathtt{(struct}\ S\ \mathtt{(}x_{0}\ x_{1}\ \dots\ x_{n}\mathtt{))}
\]
</div>(and its JavaScript equivalent) leads to inclusion of <span class="lyx-mathjax mathjax-inline">$S$</span> in <span class="lyx-mathjax mathjax-inline">$\TOK$</span> with arity <span class="lyx-mathjax mathjax-inline">$n$</span>. The encoding of instances of <span class="lyx-mathjax mathjax-inline">$S$</span> is
<div class="lyx-mathjax mathjax-display" id="x_7_2_1_0_7">\[
\SER{\mathtt{(}S\ v_{0}\ v_{1}\ \dots\ v_{n}\mathtt{)}}=S\ \SER{v_{0}}\ \SER{v_{1}}\ \dots\ \SER{v_{n}}
\]
</div></p>
<div class="footnote" id="fn_7_78"><span class="counter footnote-counter"><span>78</span></span>Even though JavaScript array values are pervasively mutable, they are (roughly speaking) <em>copied</em> into assertion tries. This effectively forces programmers to treat arrays as immutable when communicating them via a <span class="small-caps">Syndicate</span> dataspace.<span class="plain-layout-boundary"></span></div><p id="x_7_2_1_0_9">If we are to strictly follow the <span class="small-caps">Syndicate</span> design principles laid out in section <a class="cross-reference" href="#sec:Syndicate-design-principles">2.6</a>, then higher-order data such as procedures, objects and mutable data structures should be forbidden from appearing in assertions. However, given that <span class="small-caps">Syndicate</span> is not yet distributed and so does not suffer the associated restriction to first-order data, and that interoperability with some libraries demands trafficking in higher-order data, the implementations turn a blind eye to these cases.<label class="footnote-number" for="fn_7_78">78</label></p><p id="x_7_2_1_0_11">It is usually an advantage that <span class="small-caps">Syndicate</span> can see deeply into data structures: without such deep destructuring, subscriptions matching on fields of a compound datum are impossible to construct. However, from time to time, a protocol will involve a compound datum that <em>could</em> be destructured but that <em>should</em> be treated as an atomic value. It may be very large, taking an unreasonable amount of space and time to convert to a token sequence and back; or it may be able to be converted to a token sequence, but not back to a host-language value; or the relevant notion of equality for the value may not coincide with the notion of equality entailed by conversion to a token sequence, as already seen for sets and hash tables. For these cases, the implementation offers a simple remedy: a predefined standard <tt>struct</tt> type called <tt>seal</tt> with a single field:
<div class="lyx-mathjax mathjax-display" id="x_7_2_1_0_10">\[
\texttt{(struct seal (contents))}
\]
</div>Its equivalence predicate is pointer-equality and it is treated as completely opaque by the assertion trie code. Examples of its use include the transport of Racket <em>picts</em> <span class="citation citep">(<a class="citation" id="cite-163" href="#bib-Felleisen2009">Felleisen et al. 2009</a>)</span> in the <span class="small-caps">Syndicate</span> assertions describing 2D graphics for display by <span class="small-caps">Syndicate/rkt</span>'s OpenGL driver, and transport of HTML fragments in assertions describing portions of a web page for display by <span class="small-caps">Syndicate/js</span>'s user-interface driver.</p>
<h5 id="x_7_2_2_0_1"><a name="toc_7.2.2"></a><span class="counter subsection"><span>7.2.2</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Patches-and-multiplexors"></a><a name="subsec:Patches-and-multiplexors"></a>Patches and multiplexors</span></h5><p id="x_7_2_2_0_2">A <em>patch</em> represents a concrete change to be made to an assertion set or dataspace. As defined in section <a class="cross-reference" href="#sec:incremental-DS">4.6</a>, each patch consists of a pair of assertion sets: one containing assertions to be removed, and the other assertions to be added. This becomes a structure or object with two members, each an instance of an assertion trie. Tries representing sets (<span class="lyx-mathjax mathjax-inline">$\SETTRIE$</span>) are used in most cases, but occasionally the implementation makes use of patches carrying <span class="lyx-mathjax mathjax-inline">$\DSTRIE$</span> instances.</p><p id="x_7_2_2_0_3">Most of the functions manipulating patches are straightforward, but there is one exception: the <tt>compute-aggregate-patch</tt> function (and its JavaScript cognate), which computes the <em>net effect</em> of a patch on an existing dataspace (sets <span class="lyx-mathjax mathjax-inline">$\ROUTESADDbullet$</span> and <span class="lyx-mathjax mathjax-inline">$\ROUTESDELbullet$</span> in metafunction <span class="lyx-mathjax mathjax-inline">$\FBCDName$</span>, definition <a class="cross-reference" href="#def:mf:bcd">4.47</a>). If some actor labeled <span class="lyx-mathjax mathjax-inline">$\ell$</span> has produced a patch action <span class="lyx-mathjax mathjax-inline">$\Delta$</span>, the changes to the dataspace it carries may be of interest to <span class="lyx-mathjax mathjax-inline">$\ell$</span> itself or to its peers in the dataspace. However, a newly-added assertion is only relayed on if no other actor has already made the same assertion, and a newly-retracted assertion likewise has no visible effect if some other actor happens to be making the same assertion at the time of retraction. The <tt>compute-aggregate-patch</tt> function makes use of various preconditions to optimize its calculation of the maximum visible net change to the dataspace, given the collection of assertions made by the dataspace's group of actors as a whole.</p><p id="x_7_2_2_0_4">The implementation frequently needs to discover the IDs of actors affected by a particular change, as well as the assertions currently being made by a particular actor. These correspond to reading off the dataspace structure, an instance of <span class="lyx-mathjax mathjax-inline">$\SETOF{\SEXP\times\LOC}$</span>, in either a forwards or a reverse direction. A specialized object type, a <em>multiplexor</em> or <em>mux</em>, combines the necessary state and operations along with a source of fresh <span class="lyx-mathjax mathjax-inline">$\LOC$</span>s. A mux, then, effectively represents the core data structures of the dataspace itself along with an ID allocator. It is useful anywhere routing needs to be performed: to actors within dataspaces, as well as to facets within individual actors.</p><p id="x_7_2_2_0_5">Each mux instance presents an interface involving a collection of named <em>streams</em>. The mux allocates stream names and allows addition, removal, and update of a set of assertions associated with each stream. It also offers convenient functions for computing events to be delivered to each stream in response to a given action or message. Within a dataspace, each actor is a stream; within an actor, each facet is a stream.</p>
<h5 id="x_7_2_3_0_1"><a name="toc_7.2.3"></a><span class="counter subsection"><span>7.2.3</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Processes-and-behavior-functions"></a><a name="subsec:Processes-and-behavior-functions"></a>Processes and behavior functions</span></h5><p id="x_7_2_3_0_3">Recall the signature of behavior functions from figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a>:
<div class="lyx-mathjax mathjax-display" id="x_7_2_3_0_2">\[
\textrm{Behavior functions }\CBehF\in\TBehF{\tau}=\TEvt\times\tau\rightarrow\CONTINUE{\VECOF{\TAct}\times\tau}+\EXIT{\VECOF{\TAct}}
\]
</div></p><p id="x_7_2_3_0_4">The core of the implementation builds representations of the components of this signature. Events and actions are represented as structures; patches, in particular, make use of the patch and assertion-trie libraries described previously. An abstraction called a <em>transition</em> captures the type of the result from a behavior function. However, while the mathematical definition offers two possibilities, <span class="lyx-mathjax mathjax-inline">$\CONTINUE{}$</span> or <span class="lyx-mathjax mathjax-inline">$\EXIT{}$</span>, the implementation offers <em>three</em>. A behavior function may yield a <tt>transition</tt> structure, corresponding to <span class="lyx-mathjax mathjax-inline">$\CONTINUE{}$</span>, bearing an updated state and a sequence of actions to perform. Alternatively it may produce a <tt>quit</tt> structure, corresponding to <span class="lyx-mathjax mathjax-inline">$\EXIT{}$</span>, instructing the dataspace to terminate the actor following the included sequence of final actions. The new third option is that a behavior function may return <tt>#f</tt>, signaling that the behavior is now inert and does not need to be <em>polled</em> until the next event arrives. This option is made available to ease implementation of dataspaces, and is described in the next subsection.</p><p id="x_7_2_3_0_5">Around this representation of a behavior function, we introduce an abstraction called a <em>process</em>. A process is a pair of a behavior function and an associated private state. Processes correspond to the existential packages <span class="lyx-mathjax mathjax-inline">$\CBehPack{\tau}{\CBehF}u\in\TBehPack{\tau}$</span> seen in the formalism of chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>. Making processes a first-class concept not only simplifies the implementation but allows for some reuse in situations calling for reflective representations of running actors. There are many examples: embedding <span class="small-caps">Syndicate</span> actors in Racket's <tt>big-bang</tt> framework; firewalling interactions between an actor and its dataspace; interfacing <span class="small-caps">Syndicate</span> actors to the rest of a running Racket system; simple approaches to supervision of actors; running individual <span class="small-caps">Syndicate</span> actors in separate Racket threads within a single dataspace; embedding dataspaces as ordinary actors within another dataspace, translating between assertions in the outer and the inner dataspaces appropriately; and of course embedding running actors within dataspaces themselves.</p>
<h5 id="x_7_2_4_0_1"><a name="toc_7.2.4"></a><span class="counter subsection"><span>7.2.4</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Dataspaces"></a><a name="subsec:Dataspaces"></a>Dataspaces</span></h5>
<div class="footnote" id="fn_7_79"><span class="counter footnote-counter"><span>79</span></span>A connection can be made here to the <em>parallel-or</em> construct of PCF <span class="citation citep">(<a class="citation" id="cite-164" href="#bib-Plotkin1977">Plotkin 1977</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_7_2_4_0_2">While the formal model of chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a> treats dataspaces specially, in both <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span> they are implemented as ordinary actors like any other. The private state of a dataspace actor contains a <em>mux</em>; a queue of pending actions, each labeled with the ID of the actor that issued it; a set of “runnable IDs”, used to manage the distinction between quiescent and inert actors; and a hash table mapping actor ID to <tt>process</tt> structures. Upon receipt of an event, the event is (trivially) translated into an action, labeled with a special ID—the symbol <tt>'meta</tt>—representing the containing context, and placed in the pending action queue. Then, the pending action queue is atomically exchanged for an empty queue, which will gather actions to be performed in the next event cycle, and the actions previously enqueued are interpreted. Any events that result from processing of an action are immediately delivered to the relevant actors during this stage, and the resulting transition structures both update the private state associated with the transitioning actor and enqueue actions for the next round of interpretation. Once all the queued actions from the current round have been processed, the dataspace <em>polls</em> any of its children that are marked as “not provably inert”; that is, those whose IDs are stored in the “runnable ID” set. An actor is considered not provably inert whenever its behavior function answers anything other than <tt>#f</tt> in response to a poll or a delivered event. This is critical for allowing some kind of approximation of fair scheduling: without such polling, the implementation would be forced to evaluate each actor, <em>including each dataspace</em>, to inertness every time a behavior function was invoked. This way, actors can choose to perform some small amount of work and to <em>yield</em> to any peers that may also wish to do work, thus interleaving stimuli from the outside world with internal reductions, while also allowing the system as a whole to become fully inert once there genuinely remains nothing to do.<label class="footnote-number" for="fn_7_79">79</label></p><p id="x_7_2_4_0_3">It is here that host-language exceptions raised by behavior functions are transmuted into synthetic <tt>quit</tt> transitions, leading to the termination of the faulting actor.</p><p id="x_7_2_4_0_4">Some care must be taken to ensure that an actor that has issued a <tt>quit</tt> transition (or raised an exception) is <em>immediately</em> disabled. Its behavior function must not be called again, even though its final actions may remain to be interpreted. The dataspace cannot completely forget about a terminated actor until all its queued actions have been performed.</p>
<h5 id="x_7_2_5_0_1"><a name="toc_7.2.5"></a><span class="counter subsection"><span>7.2.5</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Relays"></a><a name="subsec:Relays"></a>Relays</span></h5><p id="x_7_2_5_0_2">We have been claiming that dataspaces are implemented as ordinary actors like any other, but this is not quite accurate. A dataspace actor will, left to its own devices, never produce any actions. This is because it treats the connection to its containing context identically to the connections it maintains to its contained actors. Given that a contained actor will never receive a notification about an event it did not previously declare interest in, and that the same applies to the dataspace's treatment of the containing context, we see that the context will never “receive an event” (even though, syntactically, this is presented as the <em>dataspace</em> never <em>performing an action</em>).</p><p id="x_7_2_5_0_3">Furthermore, when one dataspace is embedded within another, we want to maintain a distinction between the two contained assertion sets. The protocol involving constructors <span class="lyx-mathjax mathjax-inline">$\downharpoonleft$</span> (“outbound”, “outgoing”) and <span class="lyx-mathjax mathjax-inline">$\upharpoonleft$</span> (“inbound”, “incoming”) should embody the connection between assertions in the two spaces.</p>
<div class="footnote" id="fn_7_80"><span class="counter footnote-counter"><span>80</span></span>As of this writing, <span class="small-caps">Syndicate/js</span> lags the Racket implementation in that its dataspaces combine the functionality of Racket's dataspaces and relays, fused together. This is the original design; <span class="small-caps">Syndicate/rkt</span> was initially like this. It took some time before the benefits of separating the functions of “relay” and “dataspace” became clear.<span class="plain-layout-boundary"></span></div><p id="x_7_2_5_0_4">The job of a <em>relay actor</em> is to solve these problems. Upon startup, a relay injects a synthetic <em>event</em> into its contained dataspace actor's behavior function, expressing interest in <span class="lyx-mathjax mathjax-inline">$\downharpoonleft\star$</span> and in <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft\star$</span>. When given an event, the relay's behavior function rewrites it, prepending <span class="lyx-mathjax mathjax-inline">$\upharpoonleft$</span> to each contained assertion, before delivering it to its contained dataspace actor. Because the relay previously expressed interest in certain assertions, the dataspace will from time to time produce actions mentioning these assertions; the relay rewrites the actions it receives, translating not only <span class="lyx-mathjax mathjax-inline">$\downharpoonleft c$</span> into <span class="lyx-mathjax mathjax-inline">$c$</span> but also <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft c$</span> into <span class="lyx-mathjax mathjax-inline">$?c$</span> before transmitting the action to its own surrounding context.<label class="footnote-number" for="fn_7_80">80</label></p><p id="x_7_2_5_0_5">The effect of the rewrite from <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft c$</span> into <span class="lyx-mathjax mathjax-inline">$?c$</span> is to allow expressed interest in <em>incoming</em> assertions to automatically result in an <em>outbound</em> expression of interest in those assertions. Without it, a contained actor would have to assert <span class="lyx-mathjax mathjax-inline">$\downharpoonleft?c$</span> as well as <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft c$</span>. The problem compounds with multiple layers of dataspace nesting: with the approach taken by <span class="small-caps">Syndicate</span> relays, an actor needs only assert <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft\upharpoonleft\upharpoonleft c$</span> in order to be informed of <span class="lyx-mathjax mathjax-inline">$c$</span> three levels out; without it, it would be necessary to assert <span class="lyx-mathjax mathjax-inline">$?\upharpoonleft\upharpoonleft\upharpoonleft c$</span>, <span class="lyx-mathjax mathjax-inline">$\downharpoonleft?\upharpoonleft\upharpoonleft c$</span>, <span class="lyx-mathjax mathjax-inline">$\downharpoonleft\downharpoonleft?\upharpoonleft c$</span>, and <span class="lyx-mathjax mathjax-inline">$\downharpoonleft\downharpoonleft\downharpoonleft?c$</span>.</p><p id="x_7_2_5_0_6">By injecting a synthetic event into its contained dataspace, a relay kicks off the exchange of information between the outer and inner dataspaces, and by carefully relabeling assertions traveling in each direction, it maintains the correct distinction between “local” and “remote” assertions in the inner dataspace.</p>
<h4 id="x_7_3_0_0_1"><a name="toc_7.3"></a><span class="counter section"><span>7.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:implementing-PLLAMBDA"></a><a name="sec:implementing-PLLAMBDA"></a>Implementing the full <span class="small-caps">Syndicate</span> design</span></h4>
<div class="footnote" id="fn_7_81"><span class="counter footnote-counter"><span>81</span></span>It remains future work to explore potential performance advantages from making the dataspace implementation aware of the internal structure of <span class="small-caps">Syndicate</span> actors.<span class="plain-layout-boundary"></span></div><p id="x_7_3_0_0_2">The implementation of the <span class="small-caps">Syndicate</span> language atop the dataspace implementation has three main pieces: a runtime, which provides functions and data structures implementing facets, fields, endpoints, queries, and so forth; a syntax layer, which provides a pleasant domain-specific language for making use of the runtime; and a simple, imperative <em>dataflow</em> implementation, which tracks changes to fields and schedules re-evaluation of dependent computations. No special knowledge of intra-actor features such as fields, facets or endpoints has been added to the implementation of the dataspace model itself.<label class="footnote-number" for="fn_7_81">81</label></p>
<h5 id="x_7_3_1_0_1"><a name="toc_7.3.1"></a><span class="counter subsection"><span>7.3.1</span></span><span class="heading-text subsection">Runtime</span></h5><p id="x_7_3_1_0_2">The runtime differs from the formal model of chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> primarily in its support for efficient re-evaluation of the assertions of an actor as its fields are updated, but also in its approach to tracking facet state during facet shutdown. A simple recursive procedure is used, contrasting with the small-step approach of the model's <span class="lyx-mathjax mathjax-inline">$\textsf{stop-child}$</span> rules.</p><p id="x_7_3_1_0_3">An additional difference is the approach taken to representing non-inert actors: while the formal model embeds pending statements within the facet tree, the implementation maintains the facet tree as a data structure separate from a priority queue used to hold pending scripts. A <em>script</em> is a sequence of expressions to be evaluated in-order within the context of a given facet.</p><p id="x_7_3_1_0_4">While the formalism of chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a> runs endpoint event handlers in the order they were written in the program, the implementations take a different approach. Endpoints are stored in an unordered hash-table; when ordering is relevant to an application, a system of endpoint <em>priorities</em> can be used. For example, the definitions of the <tt>define/query-<span class="lyx-mathjax mathjax-inline">$\star$</span></tt> forms all involve two endpoints, one for responding to relevant assertions, and one for relevant retractions. Both endpoints are run at a priority level higher than the default, ensuring that the side-effects on the fields maintained by the queries are visible to ordinary endpoint event handlers. Furthermore, the retraction endpoint is placed at a slightly higher priority-level still, ensuring that <em>removal</em> of elements from sets, hash-tables, and so on is performed before addition of elements. For the specific case of hash-tables mapping each key to a single value, this is crucial: given a patch that simultaneously adds <span class="lyx-mathjax mathjax-inline">$(k,v_{new})$</span> and removes <span class="lyx-mathjax mathjax-inline">$(k,v_{old})$</span>, processing addition of <span class="lyx-mathjax mathjax-inline">$(k,v_{new})$</span> before removal of <span class="lyx-mathjax mathjax-inline">$(k,v_{old})$</span> would result in an entirely absent entry for <span class="lyx-mathjax mathjax-inline">$k$</span>. Priority levels <em>lower</em> than the default also have their uses: for example, if the synthetic endpoint corresponding to a <tt>begin/dataflow</tt> block is placed at a very low priority, then it will run <em>after</em> other code, toward the end of the actor's turn. This is a convenient time to check invariants among fields in the actor: a form of “actor contract” analogous to a class contract in an object-oriented language.</p><p id="x_7_3_1_0_5">The <span class="small-caps">Syndicate/js</span> runtime differs from the <span class="small-caps">Syndicate/rkt</span> runtime in its treatment of fields. Fields in <span class="small-caps">Syndicate/js</span> are represented as properties on a special object used as the <tt>this</tt> object when running facet setup code and event handler code. They are thus “second-class” entities in the language, similar to <span class="small-caps">Syndicate/λ</span> but in contrast to <span class="small-caps">Syndicate/rkt</span>, where fields are values in their own right. Facets are nestable in <span class="small-caps">Syndicate</span>, and code in a given facet must be able to access not only the facet's own fields but those in any of its parents. In <span class="small-caps">Syndicate/rkt</span>, the “first-class” nature of fields makes it natural for there to be an actor-global collection of fields; in <span class="small-caps">Syndicate/js</span>, the situation is different. A form of <em>inheritance</em> is required, with field objects of nested facets extending the field objects of their parents. The inheritance tree is ultimately rooted in an actor-global field object. <span class="small-caps">Syndicate/js</span> provides this by way of JavaScript's own <tt>prototype</tt>-based object inheritance mechanism.</p>
<h5 id="x_7_3_2_0_1"><a name="toc_7.3.2"></a><span class="counter subsection"><span>7.3.2</span></span><span class="heading-text subsection">Syntax</span></h5><p id="x_7_3_2_0_2">The syntax layer adapts syntactic forms reminiscent of the formal model into calls to functions provided by the runtime. In the case of <span class="small-caps">Syndicate/rkt</span>, it makes use of Racket's syntactic extension system <span class="citation citep">(<a class="citation" id="cite-165" href="#bib-Culpepper2010">Culpepper and Felleisen 2010</a>)</span>, which greatly facilitates the addition of new constructs to a language. However, JavaScript lacks a built-in syntactic extension facility. Therefore, I developed a separate compiler based on Ohm <span class="citation citep">(<a class="citation" id="cite-166" href="#bib-Warth2016">Warth, Dubroy and Garnock-Jones 2016</a>)</span> that translates the language extended with <span class="small-caps">Syndicate</span> syntax to core JavaScript. Appendix <a class="cross-reference" href="#APPENDIX:PLJS-SYNTAX">A</a> describes the syntactic extensions.</p>
<h5 id="x_7_3_3_0_1"><a name="toc_7.3.3"></a><span class="counter subsection"><span>7.3.3</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Dataflow"></a><a name="subsec:Dataflow"></a>Dataflow</span></h5><p id="x_7_3_3_0_2">Sophisticated pure-functional dataflow implementations such as that of <span class="citation citet"><a class="citation" id="cite-167" href="#bib-Cooper2006"><span>Cooper and Krishnamurthi<span class="parens"> (</span>2006<span class="parens">)</span></span></a></span> are well-suited to pure languages. However, idiomatic programs in the <span class="small-caps">Syndicate</span> design presented here make extensive use of mutation. Therefore, we chose a trivially simple imperative dataflow design with moderate efficiency and an easily-understood evaluation order and cost model. </p>
<div class="footnote" id="fn_7_82"><span class="counter footnote-counter"><span>82</span></span>The analogous <span class="small-caps">Syndicate/js</span> syntax is a <tt><span class="normal">dataflow {</span></tt><span class="normal"> ... <tt>}</tt> block.</span><span class="plain-layout-boundary"></span></div><p id="x_7_3_3_0_3">Each <span class="small-caps">Syndicate</span> actor maintains a bipartite, directed <em>dataflow graph</em>: source nodes represent fields, target nodes represent endpoints, and edges represent dependencies of the endpoints on the fields. Each endpoint contains a procedure that is used to compute the set of assertions to be associated with the endpoint. By recording field dependencies during the execution of such procedures, the implementation learns which endpoints must have their assertion sets recomputed in response to a given field change. In addition, this dataflow facility is exposed to the programmer in the form of a special <tt>begin/dataflow</tt> form,<label class="footnote-number" for="fn_7_82">82</label> which creates a synthetic pseudo-endpoint whose assertion-set procedure always returns the empty assertion set but may perform arbitrary (side-effecting) computations. Commonly, these computations update a field with a computed expression depending on another field, potentially triggering further dataflow-induced recomputation.</p>
<figure class="fullwidth" id="x_7_3_3_0_19"><a name="fig:Interface-to-dataflow"></a><span class="footnotesize">
<div class="tabular" id="x_7_3_3_0_4"><table class="tabular"><tr><td class="alignment-left valignment-top width-0pt special-50-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize"><span class="lyx-mathjax mathjax-inline">$\texttt{current-dataflow-subject-id}:\mathit{Parameter}(\mathit{Endpoint})$</span></span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt special-45-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize">Used by <tt>dataflow-record-observation!</tt> to implicitly supply a depending endpoint.</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top width-0pt special-50-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize"><span class="lyx-mathjax mathjax-inline">$\texttt{dataflow-record-observation!}:DFG\times\mathit{Field}\rightarrow1$</span></span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt special-45-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize">Records a dependency of the implicit endpoint on the given field.</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top width-0pt special-50-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize"><span class="lyx-mathjax mathjax-inline">$\texttt{dataflow-record-damage!}:DFG\times\mathit{Field}\rightarrow1$</span></span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt special-45-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize">Marks the given field as “damaged”.</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top width-0pt special-50-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize"><span class="lyx-mathjax mathjax-inline">$\texttt{dataflow-forget-subject!}:DFG\times\mathit{Endpoint}\rightarrow1$</span></span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt special-45-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize">Removes the given endpoint (and its edges) from the graph.</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-left valignment-top width-0pt special-50-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize"><span class="lyx-mathjax mathjax-inline">$\texttt{dataflow-repair-damage!}:DFG\times(\mathit{Endpoint}\rightarrow1)\rightarrow1$</span></span><span class="plain-layout-boundary"></span></td><td class="alignment-left valignment-top width-0pt special-45-percent-textwidth alignment-left valignment-top usebox-none"><span class="footnotesize">Passes endpoints depending on damaged nodes to the given function one at a time, iterating until stability is reached.</span><span class="plain-layout-boundary"></span></td></tr></table></div></span><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_7_3_3_0_18"><tt>
<div class="tabular" id="x_7_3_3_0_17"><table class="tabular"><tr><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><tt>
<div class="frameless-box" id="x_7_3_3_0_7">
<div class="verbatim" id="x_7_3_3_0_6">
<pre class="verbatim" id="x_7_3_3_0_5"><code>(begin/dataflow
expr ...)
</code></pre></div></div></tt><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\Longrightarrow$</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top usebox-none"><tt>
<div class="frameless-box" id="x_7_3_3_0_10">
<div class="verbatim" id="x_7_3_3_0_9">
<pre class="verbatim" id="x_7_3_3_0_8"><code>(add-endpoint! ...
(lambda ()
(parameterize ((current-dataflow-subject-id ...))
expr ...)))
</code></pre></div></div></tt><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top alignment-center valignment-top usebox-none"><tt>
<div class="frameless-box" id="x_7_3_3_0_13">
<div class="verbatim" id="x_7_3_3_0_12">
<pre class="verbatim" id="x_7_3_3_0_11"><code>(define/dataflow id expr)
</code></pre></div></div></tt><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top usebox-none"><span class="lyx-mathjax mathjax-inline">$\Longrightarrow$</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top width-0pt alignment-center valignment-top usebox-none"><tt>
<div class="frameless-box" id="x_7_3_3_0_16">
<div class="verbatim" id="x_7_3_3_0_15">
<pre class="verbatim" id="x_7_3_3_0_14"><code>(begin
(field [id #f])
(begin/dataflow (field expr)))
</code></pre></div></div></tt><span class="plain-layout-boundary"></span></td></tr></table></div></tt></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>49</span></span><span class="figcaption-text"><span class="lyx-argument">Interfaces to imperative Racket dataflow library<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Interface-to-dataflow"></a>Runtime- and programmer-level interfaces to imperative Racket dataflow library<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_3_3_0_20">Figure <a class="cross-reference" href="#fig:Interface-to-dataflow">49</a> sketches the interface to the Racket implementation of the dataflow library; full source code for the library is shown in appendix <a class="cross-reference" href="#APPENDIX:DATAFLOW">D</a>. The JavaScript implementation is similar. The <tt>current-dataflow-subject-id</tt> parameter records the identity of the currently-evaluating endpoint. Whenever a field is read, the runtime invokes <tt>dataflow-record-observation!</tt> with the identity of the field, thus recording a connection between the executing endpoint and the observed field. Whenever a field is updated, the runtime calls <tt>dataflow-record-damage!</tt>. Later in the behavior function of the actor, the runtime calls <tt>dataflow-repair-damage!</tt> with a <em>repair </em>procedure which, given an endpoint, calls its assertion-set recomputation procedure, collecting the results into a patch action which updates the overall assertion set of the actor in the dataspace. The synthetic endpoints generated by <tt>begin/dataflow</tt> are simply a special case, where the side-effects of the assertion-set procedure are the interesting part of the computation.</p><p id="x_7_3_3_0_21">As time goes by and fields change state, the precise set of fields that a given endpoint computation depends upon may change. The <tt>dataflow-repair-damage!</tt> procedure takes care to call <tt>dataflow-forget-subject!</tt> for each endpoint, just before invoking its repair procedure for that endpoint, in order to clear its previous memory of the endpoint's dependencies. The repair procedure, during its execution, records the currently-relevant set of dependencies for the endpoint. Finally, when an endpoint is removed from an actor as part of the facet shutdown process, <tt>dataflow-forget-subject!</tt> is used to remove obsolete dependency information for each removed endpoint.</p>
<div class="footnote" id="fn_7_83"><span class="counter footnote-counter"><span>83</span></span><a href="http://knockoutjs.com/">http://knockoutjs.com/</a><span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_7_84"><span class="counter footnote-counter"><span>84</span></span><a href="https://docs.meteor.com/api/tracker.html">https://docs.meteor.com/api/tracker.html</a><span class="plain-layout-boundary"></span></div><p id="x_7_3_3_0_22">The simple “dataflow” system described here is neither a “sibling” of nor a “cousin” to reactive programming in the sense of <span class="citation citet"><a class="citation" id="cite-168" href="#bib-Bainomugisha2013"><span>Bainomugisha et al.<span class="parens"> (</span>2013<span class="parens">)</span></span></a></span>, or even dataflow in the sense of <span class="citation citet"><a class="citation" id="cite-169" href="#bib-Whiting1994"><span>Whiting and Pascoe<span class="parens"> (</span>1994<span class="parens">)</span></span></a></span>; rather, it is most similar to the simple <em>dependency tracking</em> approach to object-oriented reactive programming described by <span class="citation citet"><a class="citation" id="cite-170" href="#bib-Salvaneschi2014"><span>Salvaneschi and Mezini<span class="parens"> (</span>2014<span class="parens">)</span></span></a> <span class="citation-after">section 2.3</span></span>, and was in fact directly inspired by the dependency tracking of JavaScript frameworks like Knockout<label class="footnote-number" for="fn_7_83">83</label> <span class="citation citep">(<a class="citation" id="cite-171" href="#bib-Sanderson2010">Sanderson 2010</a>)</span> and Meteor.<label class="footnote-number" for="fn_7_84">84</label></p>
<h4 id="x_7_4_0_0_1"><a name="toc_7.4"></a><span class="counter section"><span>7.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Programming-tools"></a><a name="sec:Programming-tools"></a>Programming tools</span></h4><p id="x_7_4_0_0_2">Because the prototype implementations of <span class="small-caps">Syndicate</span> are closely connected to the underlying formal models, the programmer is able to use concepts from the model in understanding the behavior of programs. Furthermore, points exist in the code implementing dataspace actors that correspond closely to the reduction rules given in chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>, and each invocation of a dataspace's actor behavior function itself corresponds roughly to use of the <span class="lyx-mathjax mathjax-inline">$\RSchedule$</span> rule. This gives us an opportunity to record <em>trace events</em> capturing the behavior of the program in terms of the formal model. In turn, these events enable visualization of program execution.</p><p id="x_7_4_0_0_3">The lifecycle of an action can trigger multiple trace log entries from the moment of its production to the moment the dataspace events it causes are delivered:</p>
<ol id="x_7_4_0_0_9"><li id="x_7_4_0_0_4"><a class="label-anchor" href="#enu:action-produced"></a><a name="enu:action-produced"></a>an entry for the production of the action as a result from a behavior function;</li><li id="x_7_4_0_0_5"><a class="label-anchor" href="#enu:action-enqueued"></a><a name="enu:action-enqueued"></a>an entry for the moment the action is enqueued in the dataspace's pending-actions queue;</li><li id="x_7_4_0_0_6"><a class="label-anchor" href="#enu:action-interpreted"></a><a name="enu:action-interpreted"></a>an entry for its interpretation by the dataspace, which is the same moment that its effects are applied to the state of the dataspace, and the moment any resulting dataspace events are produced;</li><li id="x_7_4_0_0_7"><a class="label-anchor" href="#enu:event-enqueued"></a><a name="enu:event-enqueued"></a>an entry for the moment such events are enqueued for delivery to an actor; and</li><li id="x_7_4_0_0_8"><a class="label-anchor" href="#enu:event-delivered"></a><a name="enu:event-delivered"></a>an entry recording the final delivery of such events as input arguments to a behavior function.</li></ol><p id="x_7_4_0_0_10">Different <span class="small-caps">Syndicate</span> implementation strategies may combine some of these log entries together. For example, the prototype dataspace implementations combine entries <a class="cross-reference" href="#enu:action-produced">1</a> and <a class="cross-reference" href="#enu:action-enqueued">2</a> and entries <a class="cross-reference" href="#enu:event-enqueued">4</a> and <a class="cross-reference" href="#enu:event-delivered">5</a>. A hypothetical distributed implementation of <span class="small-caps">Syndicate</span> would likely maintain an observable distinction between all of the stages.</p><p id="x_7_4_0_0_11">Thus far, I have implemented three consumers of generated trace log entries. The first is a console-based logging facility which simply displays each entry as colorized text on the standard error file descriptor. The remainder of this section is devoted to discussion of the other two: an offline renderer of sequence diagrams and a live display of program activity.</p>
<h5 id="x_7_4_1_0_1"><a name="toc_7.4.1"></a><span class="counter subsection"><span>7.4.1</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Sequence-diagrams"></a><a name="subsec:Sequence-diagrams"></a>Sequence diagrams</span></h5>
<figure id="x_7_4_1_0_3"><a name="fig:program-to-trace"></a>
<pre class="listing" id="x_7_4_1_0_2"><code>(assertion-struct one-plus (n m))
(spawn #:name 'add1-server
(during/spawn (observe (one-plus $n _))
#:name (list 'solving 'one-plus n)
(assert (one-plus n (+ n 1)))))
(spawn #:name 'client-process
(stop-when (asserted (one-plus 3 $value))
(printf "1 + 3 = ~a\n" value)))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>50</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:program-to-trace"></a>Program generating the sequence diagram of figure <a class="cross-reference" href="#fig:trace-of-program">51</a><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_7_4_1_0_5"><a name="fig:trace-of-program"></a><img id="x_7_4_1_0_4" src="Figures/add1-simple.svg"/><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>51</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:trace-of-program"></a>Sequence diagram of the program of figure <a class="cross-reference" href="#fig:program-to-trace">50</a><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_4_1_0_6">Recorded trace events can be automatically rendered to a kind of <em>sequence diagram</em> displaying actor lifecycle events and causal connections between emitted actions, delivered events, and dataspace state. Any <span class="small-caps">Syndicate/rkt</span> program, if run with an environment variable <tt>SYNDICATE_MSD</tt> naming an output file name, fills the named file with recorded trace events as the program runs. Unix signals may be used to selectively enable and disable tracing during long executions. Once acquired, a trace file may be rendered with a command-line tool, <tt>syndicate-render-msd</tt>, able to display directly to the screen or produce PNG or PDF files.</p>
<div class="footnote" id="fn_7_85"><span class="counter footnote-counter"><span>85</span></span>They are non-contiguous because certain administrative events are not important for this form of visualization.<span class="plain-layout-boundary"></span></div><p id="x_7_4_1_0_7">The rendered trace of the program of figure <a class="cross-reference" href="#fig:program-to-trace">50</a> is shown in figure <a class="cross-reference" href="#fig:trace-of-program">51</a>. On the right of the diagram are the internal <em>step numbers</em> associated with displayed events.<label class="footnote-number" for="fn_7_85">85</label> Each “lifeline” corresponds to a single actor and is headed by a green rectangle containing the <tt>#:name</tt> of the actor, if any. In the example, we see from left to right swimlanes corresponding to the ground dataspace itself, the <tt>add1-server</tt> actor of lines 25 in the source code, the <tt>client-process</tt> of lines 68, and finally a server process named <tt>(solving one-plus 3)</tt> which is started in response to the <tt>client-process</tt>'s request. The vertical lines backing each lifeline are narrow and light gray when an actor is inactive, but are covered with empty white vertical rectangles when an actor's behavior function is executing. More than a single actor can be “executing” at once, because <span class="small-caps">Syndicate/rkt</span> is <em>functional</em> and a containing dataspace must be active in order for one of its children to be active. As a consequence, the ground dataspace in the leftmost lifeline is almost always executing; pauses in its execution correspond to moments when the system polled the outside world for any pending input. White rectangles on a lifeline correspond to <em>actions</em> performed by the actor, and orange rectangles correspond to <em>events</em> delivered to an actor.</p><p id="x_7_4_1_0_8">The arrows overlaid on the diagram represent <em>causal influence</em>. They connect swimlanes of actors that <em>contributed to</em> or <em>caused</em> an event to the event's displayed rectangle. For example, at step 30, we see that the spawning of the <tt>solving</tt> actor is caused by one of the actions emitted by <tt>add1-server</tt> at step 21. This in turn is caused by the event of step 18, which contained information about assertions placed in the dataspace by <tt>client-process</tt> at step 17.</p><p id="x_7_4_1_0_9">A more complex example of causal influence can be seen at step 39, where the <tt>solving</tt> actor emits a patch action asserting three groups of assertions:</p>
<ol id="x_7_4_1_0_13"><li id="x_7_4_1_0_10"><tt>(observe (observe (instance 'during/spawn27 (observe (one-plus 3 _)))))</tt></li><li id="x_7_4_1_0_11"><tt>(one-plus 3 4)</tt></li><li id="x_7_4_1_0_12"><tt>(instance 'during/spawn27 (observe (one-plus 3 _)))</tt></li></ol><p id="x_7_4_1_0_14">The second in the list, <tt>(one-plus 3 4)</tt>, is the only one manifest in the source code (line 5). The others are assertions allowing <tt>add1-server</tt> to <em>supervise</em> the actors it spawns in its <tt>during/spawn</tt> form. The third in the list asserts an <tt>instance</tt> record that is interpreted by <tt>add1-server</tt> as “the child you spawned to handle the situation of <tt>(observe (one-plus 3 _))</tt> is alive.” The first in the list allows the <em>child</em> to monitor the <em>parent</em>. The semantics of <span class="small-caps">Syndicate</span> requires that if a <tt>during</tt> or <tt>during/spawn</tt> endpoint disappears, all its subordinate facets <em>or actors</em> should also disappear; monitoring the parent arranges for this to happen.</p><p id="x_7_4_1_0_15">The action of step 39 results in three events: step 40 for <tt>add1-server</tt>, letting it know its new child exists; step 44 for <tt>client-process</tt>, giving it the answer to the <tt>one-plus</tt> question it asked; and step 49, for the new <tt>solving</tt> actor itself. This latter event is a response to the child's expressed interest in the presence of its parent. The tail of the arrow connecting step 39 to step 49 is connected to <tt>add1-server</tt>, showing that some of the information in event 49—in this case, <em>all</em> the information—came from the set of assertions produced by <tt>add1-server</tt> at moment 39. Looking back along the <tt>add1-server</tt> lifeline, we see that action 29, produced alongside the spawn action that created the <tt>solving</tt> actor, is the source of the assertion conveyed in event 49.</p><p id="x_7_4_1_0_16">Event 44 causes the <tt>client-process</tt> to terminate, its task complete. Step 48 marks the transition: the lifeline is solid light gray above this point, but dashed black-and-white below this point, terminating in a crossbar just after step 69. Its final actions are implicitly computed as part of its termination, which must retract all its assertions; the synthetic action 64 does this. Action 64 influences <tt>add1-server</tt>, informing it that interest in <tt>(one-plus 3 _)</tt> no longer exists. In turn, this causes <tt>add1-server</tt> to terminate its internal facet responsible for expressing interest in the existence of the <tt>solving</tt> actor, leading to action 78. Action 78 causes two events: 79, removing the record of the <tt>solving</tt> actor's existence from <tt>add1-server</tt>, and 83, informing the <tt>solving</tt> actor that it is no longer needed. The <tt>solving</tt> actor terminates, producing its final actions at step 87 and being finally removed just after step 96. At the time the program ends, only the ground dataspace and the <tt>add1-server</tt> actor remain.</p>
<div class="footnote" id="fn_7_86"><span class="counter footnote-counter"><span>86</span></span>Such accidental reuse of “stale” values seems, in my experience, to be endemic in functional-programming simulations of mutable state. A monadic approach would have enforced the necessary invariants. An interesting alternative is to investigate whether some form of <em>contract</em> could help.<span class="plain-layout-boundary"></span></div><p id="x_7_4_1_0_17">The sequence diagram renderer is a recent development, but has already been useful in my <span class="small-caps">Syndicate</span> programming, helping me find two interesting bugs. First, one program's accidental non-linear treatment of an accumulator led to duplicated spawn actions in response to an event. This mistake manifested itself on the trace as two identical new actors appearing as the result of one transaction. The fix was to treat the accumulator properly linearly.<label class="footnote-number" for="fn_7_86">86</label> Second, in a separate program, rapidly fluctuating assertions representing demand for a resource led to an actor outliving the demand that led to its creation. The problem was visible on the trace as a missing edge informing the new actor that its services were wanted. The fix was to ensure that the actor supplying the demanded resource began monitoring demand for its services as part of its initial assertions of interest (the <span class="lyx-mathjax mathjax-inline">$\ROUTES$</span> in the syntax of <span class="lyx-mathjax mathjax-inline">$\AActorName$</span> actions described in figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a>).</p>
<h5 id="x_7_4_2_0_1"><a name="toc_7.4.2"></a><span class="counter subsection"><span>7.4.2</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Live-program-display"></a><a name="subsec:Live-program-display"></a>Live program display</span></h5>
<figure id="x_7_4_2_0_3"><a name="fig:Live-program-display"></a><img id="x_7_4_2_0_2" src="Figures/syndicate-ide.png"/><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>52</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Live-program-display"></a>Two visualizations of a running chat server<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_7_4_2_0_6"><a name="fig:Actor-structure-of-the-displayed-program"></a>
<p class="align-center" id="x_7_4_2_0_5"><img id="x_7_4_2_0_4" src="Figures/live-program-display.svg"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>53</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Actor-structure-of-the-displayed-program"></a>Actor structure of the displayed program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_7_4_2_0_7">An experimental visualization based on trace information is shown in figure <a class="cross-reference" href="#fig:Live-program-display">52</a>. Two screen captures are shown: on the left, only interactions between peers within a single dataspace are highlighted, while on the right, interactions between peers both within and <em>across</em> dataspace boundaries are shown. The diagrams are animated during the execution of the program whose structure they represent. The program depicted is a simple TCP/IP chat room service with four connected users, implemented with a nested dataspace isolating chat functionality from generic assertions and events relating to TCP, timers, and so forth. Figure <a class="cross-reference" href="#fig:Actor-structure-of-the-displayed-program">53</a> shows the nesting structure of the program.</p><p id="x_7_4_2_0_8">Each of the circles in figure <a class="cross-reference" href="#fig:Live-program-display">52</a> represents an actor. The two larger circles correspond to the two dataspaces in the program; the smaller circles represent leaf actors. Edges connecting circles together represent recent <em>causal influence</em> between two actors. The thickness of an edge varies with the recent rolling-average rate of events exchanged between the edge's vertices; more recent events lead to thicker edges. As time goes by, interaction patterns among actors change, leading to changing patterns of connectivity in the visualization.</p><p id="x_7_4_2_0_9">No nesting structure is represented. A simple spring-layout algorithm brings together interacting actors. Thicker edges lead to higher spring constants. The result is that groups of actors that interact with each other tend to move toward each other.</p><p id="x_7_4_2_0_10">On the left of figure <a class="cross-reference" href="#fig:Live-program-display">52</a>, we see two groups of interacting actors. The completely-connected group (toward the upper-right of the screenshot) is the four actors representing users in the inner dataspace exchanging chat messages. The other group (toward the lower-left) is the four TCP socket actors in the outer dataspace interacting with the inner dataspace actor itself in terms of TCP byte streams.</p><p id="x_7_4_2_0_11">On the right, the same two groups are visible. However, the version on the right adds tracking of causal influence information across dataspace boundaries, allowing detection and display of the interactions between “Connected socket 1” and “User agent 1”, and so on. The additional edges represent translation back and forth between chat messages and TCP byte stream events.</p><p id="x_7_4_2_0_12">In both screenshots, we see five actors not interacting with any other. These are the ground dataspace, along with three actors directly running in the ground dataspace (“TCP listener factory”, “TCP connection factory” and “Listener socket 5999”) and one actor running in the inner dataspace (“Main chat room process”).</p><p id="x_7_4_2_0_13">This approach to visualization of a running program is still experimental and has not been integrated with the mainline implementation code. In future, exploration of ways of presenting nesting relationships among actors could prove useful.</p></p><p id="x_8_8_0_0_14">
<h3 id="x_8_0_0_0_1"><a name="toc_8"></a><span class="counter chapter"><span>8</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:IDIOMATIC-SYNDICATE"></a><a name="CHAP:IDIOMATIC-SYNDICATE"></a>Idiomatic <span class="small-caps">Syndicate</span></span></h3><p id="x_8_0_0_0_2">Having reviewed the theory of the dataspace model, the design of <span class="small-caps">Syndicate</span>'s novel language features, and the fundamentals of programming with <span class="small-caps">Syndicate/rkt</span>, we are ready to explore practical aspects of the construction of <span class="small-caps">Syndicate</span> programs. In this chapter, we consider representative programs that illustrate idiomatic <span class="small-caps">Syndicate</span> programming techniques. We begin with the central concern in <span class="small-caps">Syndicate</span> programming: the design of <span class="small-caps">Syndicate</span> protocols.</p>
<h4 id="x_8_1_0_0_1"><a name="toc_8.1"></a><span class="counter section"><span>8.1</span></span><span class="heading-text section">Protocols and Protocol Design</span></h4><p id="x_8_1_0_0_2">We have been calling the sum total of the related interactions among components a <em>protocol</em>, made up of<em> conversations</em> involving assertions and message transmissions. Each kind of conversation involves one or more actors playing <em>roles</em> within the conversation's context. Each role may include <em>responsibilities</em> and <em>obligations</em> that actors performing that role must live up to. The assertions and messages of each conversation form the shared <em>knowledge</em> exchanged among participants. The strong isolation afforded <span class="small-caps">Syndicate</span> actors dovetails with epistemic concerns about “who knows what” to force consideration of the <em>placement</em> of knowledge in a system. The notions of “schema”, “role”, “conversation” and so forth are, as yet, informal: they do not correspond either to <span class="small-caps">Syndicate</span> language features or to manifest aspects of the dataspace model. However, these latent ideas underpin each program that we examine in this chapter.</p><p id="x_8_1_0_0_3">Designing a dataspace protocol is similar to designing an actor model program, but also has points in common with designing a relational database. Like the actor model, the focus is on knowledge exchanged between parties and the placement of the program's stateful components. Where the actor model focuses on exchange of domain messages, <span class="small-caps">Syndicate</span> concentrates on shared conversational state, represented as domain assertions in the shared dataspace. The structure and meaning of the assertions themselves are the primary point of similarity with relational database schema design, where interpretations of and relationships among rows in tables are carefully described. Every dataspace protocol has the rough analogue of a <em>schema</em> that describes its assertions and messages and their meanings. The schema is ontologically prior to other elements of a protocol; conversational exchanges take place within the framework provided by the schema. Consideration of the goals, abilities and needs of each participant in a conversation leads in turn to the notions of roles, responsibilities and obligations.</p>
<div class="footnote" id="fn_8_87"><span class="counter footnote-counter"><span>87</span></span>The dataspace model is nameless, from the programmer's perspective; an actor label (section <a class="cross-reference" href="#sec:Formal-DS-semantics">4.2</a>) is a purely dataspace-internal concept. Likewise, each facet name (section <a class="cross-reference" href="#sec:Informal-PLLAMBDA-semantics">5.1</a>) is only meaningful to a single, specific actor.<span class="plain-layout-boundary"></span></div><p id="x_8_1_0_0_4">A second point of similarity between relational databases and the dataspace model is that both tend to construct rows from atomic data such as text, numbers, dates and domain-specific references to other rows. It is unusual to see a database include representations of programming-language concepts like thread IDs, exception values, mutable variables, or file handles. Likewise, in the dataspace model, it is rare to see such host-language implementation-level concepts communicated via the dataspace. This same point distinguishes dataspace programming from the actor model, which unavoidably communicates actor IDs as elements of message structures.<label class="footnote-number" for="fn_8_87">87</label></p><p id="x_8_1_0_0_23">
<div class="theorem-like protocol-description named" id="x_8_1_0_0_22"><span class="counter protocol-description"><span>8.1</span></span><a class="label-anchor" href="#protocol:toy-fs"></a><a name="protocol:toy-fs"></a><span class="lyx-argument">Toy “file system”<span class="plain-layout-boundary"></span></span>To demonstrate the pieces of a <span class="small-caps">Syndicate</span> protocol, we work through an example: a simple <em>file system</em> protocol as sketched in example <a class="cross-reference" href="#example:file-system">4.4</a>, discussed in section <a class="cross-reference" href="#sec:Ad-hoc-assertions">6.6</a>, and implemented in figure <a class="cross-reference" href="#fig:File-system-using-during">33</a>.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_1_0_0_11"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>Let us begin by examining the protocol's schema. Participants communicate primarily via assertions representing file contents:<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_1_0_0_5"><tt>(assertion-struct file (name content))</tt></p><span class="plain-layout-boundary"></span>where <tt>name</tt> is a string denoting a file-system path and <tt>content</tt> is either <tt>#f</tt>, meaning that the file does not exist, or a string, the contents of the file. For example, asserting<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_1_0_0_6"><tt>(file "novel.txt" "Call me Ishmael.")</tt></p><span class="plain-layout-boundary"></span>declares that the file named “<tt>novel.txt</tt>” currently contains the text “<tt>Call me Ishmael.</tt>” In principle, a <tt>file</tt> assertion could be maintained constantly for every file that exists, but in practice we allow an implementation to lazily manifest these assertions in response to detected demand. An endpoint like<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_1_0_0_7"><tt>(during (file "novel.txt" $text) ...)</tt></p><span class="plain-layout-boundary"></span>results in an assertion of interest,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_1_0_0_8"><tt>(observe (file "novel.txt" _))</tt></p><span class="plain-layout-boundary"></span>and so our schema assigns an additional meaning to such assertions, beyond the intrinsic meaning of <tt>observe</tt> in expressing subscriptions. In this setting, these assertions of interest denote an active <em>demand</em> for production of a matching <tt>file</tt> record, not mere interest in any matching records that happen to exist.<span class="plain-layout-boundary"></span>Besides <tt>file</tt> assertions, our schema includes two message types:<span class="plain-layout-boundary"></span>
<div class="verbatim" id="x_8_1_0_0_10">
<pre class="verbatim" id="x_8_1_0_0_9"><code>(message-struct save (name content))
(message-struct delete (name))
</code></pre></div>where the <tt>name</tt> fields contain path strings, as for <tt>file</tt> records, but the <tt>content</tt> field must contain a string. The two messages denote requests to <em>update</em> or <em>delete</em> a named file, respectively.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_1_0_0_16"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>There are three roles in our protocol: <em>Server</em>, <em>Reader</em>, and <em>Writer</em>.<span class="plain-layout-boundary"></span>
<ul id="x_8_1_0_0_15"><li id="x_8_1_0_0_12">The Server is expected to be unique within a given protocol instance. It maintains the authoritative file store, reacts to demand by supplying file contents to Readers, and accepts file changes from Writers.</li><li id="x_8_1_0_0_13">Any number of Readers may exist within an instance. Readers observe file contents.</li><li id="x_8_1_0_0_14">Any number of Writers may exist within an instance. Writers save and delete files.</li></ul></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_1_0_0_21"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span>There are three kinds of conversation in our protocol, each working toward satisfaction of the various <em>goals</em> that participants may have.<span class="plain-layout-boundary"></span>
<ul id="x_8_1_0_0_20"><li id="x_8_1_0_0_17"><em>Reading</em> is an interaction between a Reader and the Server. The Server responds to a Reader's assertion of <tt>(observe (file </tt><em>name</em><tt> _))</tt> records. Each distinct <em>name</em> causes the Server to assert a <tt>file</tt> record with the current contents of the named file, if it exists, or with <tt>#f</tt> if it does not. A Reader asserts <tt>(observe (file </tt><em>name</em><tt> _))</tt> for some specific <em>name</em>, and responds to assertion of <tt>(file </tt><em>name contents</em><tt>)</tt> according to its needs.</li><li id="x_8_1_0_0_18"><em>Updating</em> is an interaction between a Writer and the Server. A Writer sends <tt>(save</tt> <em>name content</em><tt>)</tt> to replace the content of the <em>name</em>d file with <em>content</em>, creating the file if it does not already exist. The Server responds to such messages by updating its store accordingly and updating any <tt>(file </tt><em>name</em><tt> _)</tt> assertions it has previously established to reference the new <em>content</em>.</li><li id="x_8_1_0_0_19"><em>Deleting</em> is also an interaction between a Writer and the Server. A Writer sends <tt>(delete </tt><em>name</em><tt>)</tt> to cause the deletion of the <em>name</em>d file. The Server responds to <tt>(delete </tt><em>name</em><tt>)</tt> messages by removing <em>name</em> from its records and updating any <tt>(file </tt><em>name</em><tt> _)</tt> assertions it has previously established to map <em>name</em> to <tt>#f</tt>.</li></ul></div><span class="plain-layout-boundary"></span></div></p><p id="x_8_1_0_0_24">An important part of the summary of a role is its expected <em>cardinality</em> within the dataspace. For example, in the example we imagine a unique file server; the protocol would require alteration to support multiple distinct file servers. Alternatively, if multiple <em>replica </em>servers were to be supported, the protocol would require changes to handle the necessary conversations among replicas. While we have described the server as unique within this protocol, we expect the protocol to support an arbitrary number of concurrent readers and writers.</p><p id="x_8_1_0_0_25">The dataspace model allows wildcards to be placed freely within compound data structures, but not all <span class="small-caps">Syndicate</span> programs allow wildcards in all positions: families of assertions that a program expects to be able to iterate over must be finite in every position where a pattern variable exists (see section <a class="cross-reference" href="#sec:Well-formedness-and-errors">5.5</a>). Therefore, we must take care to specify which positions in assertions themselves and in <em>subscriptions</em> to such assertions may contain wildcards. In the description of the “Reading” conversation in our example, we see that the Server expects to be able to deduce distinct <em>name</em>s of files of interest; therefore, it is forbidden for any Reader to subscribe with a wildcard in the <em>name</em> position of a <tt>file</tt> assertion. In effect, we must be able to deduce the appropriate <em>finiteness</em> constraints on positions in assertions and messages (and subscriptions to those assertions and messages) from the protocol description.</p><p id="x_8_1_0_0_26">Relatedly, certain positions in assertions may be required to be unique in the dataspace. In the file system example, a constraint exists that the server may not publish inconsistent information: for a given file <tt>"a"</tt>, only <em>one</em> <tt>file</tt> assertion of its contents may be placed in the dataspace at any given time.</p>
<h4 id="x_8_2_0_0_1"><a name="toc_8.2"></a><span class="counter section"><span>8.2</span></span><span class="heading-text section">Built-in protocols</span></h4><p id="x_8_2_0_0_2">Central to all dataspace protocols is an embedding of the protocol describing <em>interest</em> (<span class="lyx-mathjax mathjax-inline">$\Obs{}$</span>); without it, no communication takes place. Some programs also make use of <em>cross-layer relaying</em> (<span class="lyx-mathjax mathjax-inline">$\In{}$</span>/<span class="lyx-mathjax mathjax-inline">$\Out{}$</span>). These two protocols are special cases in that they are the <em>only</em> built-in protocols exposed to programmers.</p><p id="x_8_2_0_0_7">
<div class="theorem-like protocol-description named" id="x_8_2_0_0_6"><span class="counter protocol-description"><span>8.2</span></span><span class="lyx-argument">Interest<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#protocol:interest"></a><a name="protocol:interest"></a>This protocol is the fundamental unit of conversation in <span class="small-caps">Syndicate</span>; the smallest conversational frame that can exist. All other conversations and protocols are constructed from it.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_2_0_0_3"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>A single family of assertions, <tt>(observe</tt> <tt><span class="lyx-mathjax mathjax-inline">$x$</span>)</tt>, describes interest in the assertion or assertions <span class="lyx-mathjax mathjax-inline">$x$</span>. Asserting an <tt>observe</tt> record denotes <em>subscription</em> to matching assertions: not only to appearance and disappearance of assertions <em>per se</em>, but also to messages having a matching body. There are no inherent restrictions on wildcard use within <tt>observe</tt> records; indeed, wildcards are vital, as a wildcard used inside some <em><span class="lyx-mathjax mathjax-inline">$x$</span></em> in an <tt>observe</tt> record indicates a <em>range</em> of values of interest.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_2_0_0_4">
<div class="footnote" id="fn_8_88"><span class="counter footnote-counter"><span>88</span></span>A key difference between these two kinds of role is that the “relay” role performed by the dataspace has in some sense more to do with a <em>metalevel</em> protocol than any kind of domain-level protocol at all.<span class="plain-layout-boundary"></span></div><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>There are two overt, user-level roles, namely <em>subscriber</em> and <em>publisher</em>, but also a less apparent role: that of the dataspace itself acting as a <em>relay</em>.<label class="footnote-number" for="fn_8_88">88</label> Any actor asserting interest in <em><span class="lyx-mathjax mathjax-inline">$x$</span></em> is a subscriber to <span class="lyx-mathjax mathjax-inline">$x$</span>; any actor asserting <em><span class="lyx-mathjax mathjax-inline">$x$</span></em> or sending <em><span class="lyx-mathjax mathjax-inline">$x$</span> </em>as a message is a publisher of <span class="lyx-mathjax mathjax-inline">$x$</span>. The dataspace, of course, is the unique relay in the scenario.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_2_0_0_5"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span>Again, at an actor-to-actor level, only one kind of conversation exists: that between subscriber and publisher. The conversation between each actor and its dataspace is “at right angles” to, and facilitates, publisher-to-subscriber conversational interaction.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p><p id="x_8_2_0_0_11">
<div class="theorem-like protocol-description named" id="x_8_2_0_0_10"><span class="counter protocol-description"><span>8.3</span></span><span class="lyx-argument">Cross-layer relaying<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#protocol:cross-layer"></a><a name="protocol:cross-layer"></a>In every case where a dataspace is nested within another, the cross-layer relaying protocol exists to allow actors contained within the inner dataspace to access assertions and messages in the outer dataspace.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_2_0_0_8"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>Two general-purpose unary records, <tt>(inbound <span class="lyx-mathjax mathjax-inline">$x$</span>)</tt> and <tt>(outbound <span class="lyx-mathjax mathjax-inline">$x$</span>)</tt> (corresponding to <span class="lyx-mathjax mathjax-inline">$\In x$</span> and <span class="lyx-mathjax mathjax-inline">$\Out x$</span> in the formalism of section <a class="cross-reference" href="#sec:Informal-DS-semantics">4.1</a>, respectively) are used for both assertions and messages <span class="lyx-mathjax mathjax-inline">$x$</span>.<span class="plain-layout-boundary"></span></div>
<div class="protocol-section" id="x_8_2_0_0_9"><span class="lyx-argument">Roles and Conversations<span class="plain-layout-boundary"></span></span>This protocol is peculiar in that the relevant actors are, first, the actor <span class="lyx-mathjax mathjax-inline">$A$</span> asserting or sending an <tt>outbound</tt> assertion or message, and second, that actor's local dataspace, <span class="lyx-mathjax mathjax-inline">$D_{1}$</span>. The dataspace, <span class="lyx-mathjax mathjax-inline">$D_{1}$</span>, reacts to <tt>(outbound <span class="lyx-mathjax mathjax-inline">$x$</span>)</tt> assertions or messages by relaying <span class="lyx-mathjax mathjax-inline">$x$</span> to its own containing dataspace, <span class="lyx-mathjax mathjax-inline">$D_{2}$</span>.<span class="plain-layout-boundary"></span>
<div class="footnote" id="fn_8_89"><span class="counter footnote-counter"><span>89</span></span>This is apparent from the specification of <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> (definition <a class="cross-reference" href="#def:mf:out-monolithic">4.14</a>), where the assertion set relayed to a containing dataspace is given by <span class="lyx-mathjax mathjax-inline">$\{c\;|\;(j,\Out c)\in R\}\cup\{\Obs c\;|\;(j,\Obs{\In c})\in R\}$</span>.<span class="plain-layout-boundary"></span></div>Asserting <tt>(outbound (observe <span class="lyx-mathjax mathjax-inline">$x$</span>))</tt> leads <span class="lyx-mathjax mathjax-inline">$D_{1}$</span> to assert <tt>(observe <span class="lyx-mathjax mathjax-inline">$x$</span>)</tt> within the dataspace of <span class="lyx-mathjax mathjax-inline">$D_{2}$</span>. This, of course, acts as a subscription to <span class="lyx-mathjax mathjax-inline">$x$</span>, meaning that <span class="lyx-mathjax mathjax-inline">$D_{1}$</span> may receive assertions or messages <span class="lyx-mathjax mathjax-inline">$x$</span>. In response to such events, <span class="lyx-mathjax mathjax-inline">$D_{1}$</span> wraps them in an <tt>inbound</tt> record and relays them on to its own dataspace. However, notice that actor <span class="lyx-mathjax mathjax-inline">$A$</span> <em>never asserted interest in anything</em>. Actor <span class="lyx-mathjax mathjax-inline">$A$</span> must assert <tt>(observe (inbound <span class="lyx-mathjax mathjax-inline">$x$</span>))</tt> in order to be notified when a relevant <span class="lyx-mathjax mathjax-inline">$x$</span>-event in <span class="lyx-mathjax mathjax-inline">$D_{2}$</span>'s dataspace takes place. For this reason, every dataspace interprets <tt>(observe (inbound <span class="lyx-mathjax mathjax-inline">$x$</span>))</tt> as if it <em>implied </em><tt>(outbound (observe <span class="lyx-mathjax mathjax-inline">$x$</span>))</tt>. Actors such as <span class="lyx-mathjax mathjax-inline">$A$</span> need only assert the former to enjoy the effect of the latter.<label class="footnote-number" for="fn_8_89">89</label><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p>
<figure id="x_8_2_0_0_17"><a name="fig:Cross-layer-relaying-example"></a>
<div class="frameless-box" id="x_8_2_0_0_13">
<pre class="listing" id="x_8_2_0_0_12"><code>#lang syndicate
(assertion-struct greeting (text))
(spawn #:name "A" (assert (greeting "Hi from outer space!")))
(spawn #:name "B" (on (asserted (greeting $t))
(printf "Outer dataspace: ~a\n" t)))
(dataspace #:name "C"
(spawn #:name "D" (assert (outbound (greeting "Hi from inner!"))))
(spawn #:name "E" (on (asserted (inbound (greeting $t)))
(printf "Inner dataspace: ~a\n" t))))
</code></pre><span class="plain-layout-boundary"></span></div>&emsp;&emsp;
<div class="frameless-box" id="x_8_2_0_0_16">
<p class="align-center" id="x_8_2_0_0_15"><img id="x_8_2_0_0_14" src="Figures/example-cross-layer-relaying.svg" style="width: 2.6in; height: auto;"/></p><span class="plain-layout-boundary"></span><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>54</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Cross-layer-relaying-example"></a>Cross-layer relaying example.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered example named" id="x_8_2_0_0_33">
<p id="x_8_2_0_0_32"><span class="counter numbered example"><span>8.4</span></span><a class="label-anchor" href="#example:rkt-cross-layer"></a><a name="example:rkt-cross-layer"></a><span class="lyx-argument">Cross-layer relaying<span class="plain-layout-boundary"></span></span> The program in figure <a class="cross-reference" href="#fig:Cross-layer-relaying-example">54</a> creates three actors (A, B and C) within the ground dataspace. Actor C is a dataspace itself. As C starts up, two further actors (D and E) are spawned within it. All interaction among actors A, B, D and E takes place via the ground dataspace; D and E communicate with the ground dataspace indirectly via C by using <tt>inbound</tt> and <tt>outbound</tt> constructors. Two <tt>greeting</tt> records end up being asserted within the ground dataspace, from A and D. As discussed above, E's assertion of interest in <tt>(inbound (greeting _))</tt> assertions is automatically translated by C into an assertion of <tt>(observe (greeting _))</tt> at the ground dataspace level. The matching records are relayed up into C's dataspace, appearing wrapped as <tt>(inbound (greeting </tt>...<tt>))</tt>. At the time the program quiesces, the assertions in C's dataspace are:
<ul id="x_8_2_0_0_22"><li id="x_8_2_0_0_18"><tt>(outbound (greeting "Hi from inner!"))</tt>, courtesy of actor D.</li><li id="x_8_2_0_0_19"><tt>(observe (inbound (greeting _)))</tt>, from actor E.</li><li id="x_8_2_0_0_20"><tt>(inbound (greeting "Hi from outer space!"))</tt>, from actor A, relayed up into C's dataspace by C itself.</li><li id="x_8_2_0_0_21"><tt>(inbound (greeting "Hi from inner!"))</tt>, from actor D, relayed first down into the ground dataspace, where it matched C's own interest (on behalf of E) in <tt>greeting</tt> records and was relayed <em>back</em> again by C.</li></ul><p id="x_8_2_0_0_23">The assertions in the ground dataspace are:</p>
<ul id="x_8_2_0_0_27"><li id="x_8_2_0_0_24"><tt>(greeting "Hi from outer space!")</tt>, from A.</li><li id="x_8_2_0_0_25"><tt>(greeting "Hi from inner!")</tt>, from C (on behalf of D).</li><li id="x_8_2_0_0_26"><tt>(observe (greeting _))</tt>, asserted by <em>both</em> C (on behalf of E) and B.</li></ul>
<figure id="x_8_2_0_0_30"><a name="fig:trace-cross-layer"></a>
<p class="align-center" id="x_8_2_0_0_29"><img id="x_8_2_0_0_28" src="Figures/simple-cross-layer.svg"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>55</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:trace-cross-layer"></a><span class="lyx-argument">Execution trace of the cross-layer example<span class="plain-layout-boundary"></span></span>Execution trace of the cross-layer example <a class="cross-reference" href="#example:rkt-cross-layer">8.4</a><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_8_90"><span class="counter footnote-counter"><span>90</span></span>Unfortunately, the current tracing mechanism (section <a class="cross-reference" href="#subsec:Sequence-diagrams">7.4.1</a>) does not capture the causal connection between <tt>outbound</tt> assertions and the assertions of the containing dataspace. The reader is left to deduce the connection between the assertions of actors D and E, and the subsequent actions of C.<span class="plain-layout-boundary"></span></div><p id="x_8_2_0_0_31">Figure <a class="cross-reference" href="#fig:trace-cross-layer">55</a> shows an execution trace of the program.<label class="footnote-number" for="fn_8_90">90</label></p></p><span class="halmos"></span></div>
<h4 id="x_8_3_0_0_1"><a name="toc_8.3"></a><span class="counter section"><span>8.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Shared,-mutable-state"></a><a name="sec:Shared,-mutable-state"></a>Shared, mutable state</span></h4><p id="x_8_3_0_0_2">Some protocols need assertions in the dataspace to be long-lived, outliving the actors that produced them and actors making use of them. In these situations, the dataspace takes on even more of the characteristics of a relational-style database. We have already seen two examples of this idiom: the toy “file system” of protocol <a class="cross-reference" href="#protocol:toy-fs">8.1</a>, where <tt>file</tt> records persist until explicitly deleted, and the “box and client” program of example <a class="cross-reference" href="#example:rkt-box-and-client">6.1</a>, where the <tt>box-state</tt> record persists indefinitely. Here, we present a <em>mutable cell</em> protocol and program that generalizes the latter.</p><p id="x_8_3_0_0_16">
<div class="theorem-like protocol-description named" id="x_8_3_0_0_15"><span class="counter protocol-description"><span>8.5</span></span><a class="label-anchor" href="#protocol:mutable-cell"></a><a name="protocol:mutable-cell"></a><span class="lyx-argument">Mutable cell<span class="plain-layout-boundary"></span></span>This protocol describes a mutable cell service, instantiable multiple times in a single dataspace. Cell IDs are auto-generated; a minor modification to this protocol yields a <em>key-value store</em>. The protocol is similar to so-called “CRUD” protocols (standing for Create, Read, Update and Delete). Here, creation and deletion of cells is explicit; an alternative could be to create cells implicitly at first mention of a hitherto-unseen ID.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_3_0_0_5"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>One assertion describes the value of each cell, and three messages create, update, and destroy cells, respectively:<span class="plain-layout-boundary"></span>
<div class="verbatim" id="x_8_3_0_0_4">
<pre class="verbatim" id="x_8_3_0_0_3"><code>(assertion-struct cell (id value))
(message-struct create-cell (id value))
(message-struct update-cell (id value))
(message-struct delete-cell (id))
</code></pre></div>Cell IDs are arbitrary values, unique within one dataspace. At most one <tt>cell</tt> record is asserted for a given ID.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_3_0_0_6"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>There are four roles: <em>CellFactory</em>, <em>Cell</em>, <em>Reader</em> and <em>Writer</em>. A unique CellFactory exists in the dataspace. A distinct Cell exists for each cell ID created. Any number of Readers or Writers may exist. Readers observe Cell contents; Writers request creation, deletion and update of Cells.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_3_0_0_12"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_3_0_0_11"><li id="x_8_3_0_0_7"><em>Creation</em> (Writer/CellFactory). The Writer chooses a dataspace-unique cell ID, and sends a <tt>create-cell</tt> message with the initial value to place in the new cell. In response, the CellFactory creates a new Cell with the given ID and value.</li><li id="x_8_3_0_0_8"><em>Reading</em> (Cell/Reader). The Cell is continuously publishing a <tt>cell</tt> assertion, which the Reader observes. The Cell updates the assertion as its value changes.</li><li id="x_8_3_0_0_9"><em>Updating</em> (Cell/Writer). The Writer sends an <tt>update-cell</tt> message; the Cell updates its value (and <tt>cell</tt> assertion) accordingly.</li><li id="x_8_3_0_0_10"><em>Deleting</em> (Cell/Writer). The Writer sends a <tt>delete-cell</tt> message; the Cell terminates in response.</li></ul></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_3_0_0_14"><span class="lyx-argument">Programming interface<span class="plain-layout-boundary"></span></span>A library routine, <tt>spawn-cell</tt>, allocates a fresh cell ID, sends a <tt>createcell</tt> message, and returns the new ID:<span class="plain-layout-boundary"></span>
<pre class="listing" id="x_8_3_0_0_13"><code>(define (spawn-cell initial-value)
(define id (gensym 'cell))
(send! (create-cell id initial-value))
id)
</code></pre><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p>
<div class="theorem-like numbered example named" id="x_8_3_0_0_21">
<p id="x_8_3_0_0_20"><span class="counter numbered example"><span>8.6</span></span><a class="label-anchor" href="#example:rkt-mutable-cell"></a><a name="example:rkt-mutable-cell"></a><span class="lyx-argument">Mutable cell<span class="plain-layout-boundary"></span></span>The following listing shows an implementation of the Cell Factory and Cell roles, in context of the assertion- and message-structure definitions shown above:<p id="x_8_3_0_0_18">
<pre class="listing" id="x_8_3_0_0_17"><code>(spawn #:name 'cell-factory
(on (message (create-cell $id $initial-value))
(spawn #:name (list 'cell id)
(field [value initial-value])
(assert (cell id (value)))
(on (message (update-cell id $new-value)) (value new-value))
(stop-when (message (delete-cell id))))))
</code></pre></p><p id="x_8_3_0_0_19">The definition of an actor implementing Cell (lines 37) is embedded within the definition of the Cell Factory. Each time the Cell Factory receives a <tt>create-cell</tt> message (line 2), it spawns a new Cell instance (line 3), with a computed name incorporating the new cell's ID. Each Cell has a single <tt>value</tt> field (line 4), which is continuously published into the dataspace (line 5). Whenever an <tt>update-cell</tt> message is received, <tt>value</tt> is updated (line 6); recall that <span class="small-caps">Syndicate/rkt</span> fields are modeled as functions (see section <a class="cross-reference" href="#sec:rkt-Core-forms">6.4</a>). The Cell terminates itself when it receives an appropriately-addressed <tt>delete-cell</tt> message (line 7).</p></p><span class="halmos"></span></div><p id="x_8_3_0_0_22">Writers simply issue their requests by <tt>send!</tt>ing <tt>update-cell</tt> and <tt>delete-cell</tt> messages; Readers construct endpoints monitoring <tt>cell</tt> assertions.</p>
<div class="theorem-like numbered example" id="x_8_3_0_0_27">
<p id="x_8_3_0_0_26"><span class="counter numbered example"><span>8.7</span></span><a class="label-anchor" href="#example:rkt-mutable-cell-monitor"></a><a name="example:rkt-mutable-cell-monitor"></a>The following procedure spawns a simple actor that monitors the changing value of a cell:<p id="x_8_3_0_0_24">
<pre class="listing" id="x_8_3_0_0_23"><code>(define (spawn-cell-monitor id)
(spawn #:name (list 'cell-monitor id)
(on (asserted (cell id $value))
(printf "Cell ~a updated to: ~a\n" id value))
(on (retracted (cell id _))
(printf "Cell ~a deleted\n" id))))
</code></pre></p><p id="x_8_3_0_0_25">The endpoint of lines 34 monitors the <em>appearance</em> of each <em>distinct</em> ID/value combination for the ID given, thereby printing a message for each value the cell takes on. The endpoint of lines 56 monitors the <em>disappearance</em> of <em>all</em> <tt>cell</tt> assertions for the given ID, triggering only once: when no more assertions remain, namely when the cell's actor terminates itself. This is an example of the elision of irrelevant detail—here, the specific <em>value</em> in the <tt>cell</tt> record is irrelevant for this endpoint's purpose—performed by the metafunction <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> (definition <a class="cross-reference" href="#def:mf:inst">5.24</a>) as part of projection of incoming patch events.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example" id="x_8_3_0_0_32">
<p id="x_8_3_0_0_31"><span class="counter numbered example"><span>8.8</span></span><a class="label-anchor" href="#example:rkt-read-cell"></a><a name="example:rkt-read-cell"></a>Alternatively, a blocking <tt>read-cell</tt> routine can be constructed using <tt>flush!</tt> and <tt>react/suspend</tt> (section <a class="cross-reference" href="#par:Blocking-expressions">6.5</a>, page <a class="cross-reference pageref" href="#par:Blocking-expressions">&mdash;</a>):<p id="x_8_3_0_0_29">
<pre class="listing" id="x_8_3_0_0_28"><code>(define (read-cell id)
(flush!)
(react/suspend (k) (stop-when (asserted (cell id $value)) (k value))))
</code></pre></p><p id="x_8_3_0_0_30">The use of <tt>flush!</tt> in <tt>read-cell</tt> deserves explanation. Recall that message sending is asynchronous. This means that if we <tt>send!</tt> an <tt>update-cell</tt> message, it is enqueued for transmission once the actor's behavior function returns control to the dataspace, and execution continues. If we omit the call to <tt>flush!</tt> before accessing the <tt>cell</tt> assertion, then programs calling <tt>read-cell</tt> multiple times in succession <em>reuse</em> the most-recently delivered information, without forcing queued actions (such as <tt>update-cell</tt> messages) out to the dataspace and waiting for new information.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_3_0_0_47">
<p id="x_8_3_0_0_46"><span class="counter numbered example"><span>8.9</span></span><a class="label-anchor" href="#example:rkt-mutable-cell-main-actor"></a><a name="example:rkt-mutable-cell-main-actor"></a>Consider the following program, to be run alongside the definitions of protocol <a class="cross-reference" href="#protocol:mutable-cell">8.5</a> and examples <a class="cross-reference" href="#example:rkt-mutable-cell">8.6</a>, <a class="cross-reference" href="#example:rkt-mutable-cell-monitor">8.7</a> and <a class="cross-reference" href="#example:rkt-read-cell">8.8</a>:<p id="x_8_3_0_0_34">
<pre class="listing" id="x_8_3_0_0_33"><code>(spawn* #:name 'main-actor
(define id (spawn-cell 123))
(spawn-cell-monitor id)
(send! (update-cell id (+ (read-cell id) 1)))
(send! (update-cell id (+ (read-cell id) 1)))
(send! (update-cell id (+ (read-cell id) 1)))
(send! (delete-cell id)))
</code></pre></p><p id="x_8_3_0_0_35">With a <tt>flush!</tt> in <tt>read-cell</tt>, the output is</p>
<div class="verbatim" id="x_8_3_0_0_37">
<pre class="verbatim" id="x_8_3_0_0_36"><code>Cell cell27 updated to: 123
Cell cell27 updated to: 124
Cell cell27 updated to: 125
Cell cell27 updated to: 126
Cell cell27 deleted
</code></pre></div><p id="x_8_3_0_0_38">Without a <tt>flush!</tt> in <tt>read-cell</tt>, the output is</p>
<div class="verbatim" id="x_8_3_0_0_40">
<pre class="verbatim" id="x_8_3_0_0_39"><code>Cell cell27 updated to: 123
Cell cell27 updated to: 124
Cell cell27 deleted
</code></pre></div>
<figure class="fullwidth" id="x_8_3_0_0_44"><a name="fig:trace-mutable-cell-main-actor"></a>
<p class="align-center" id="x_8_3_0_0_43"><img id="x_8_3_0_0_41" src="Figures/mutable-cell-flush-crop.svg" style="width: 49%; height: auto;"/><img id="x_8_3_0_0_42" src="Figures/mutable-cell-no-flush.svg" style="width: 49%; height: auto;"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>56</span></span><span class="figcaption-text"><span class="lyx-argument">Execution trace of the mutable-cell example<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:trace-mutable-cell-main-actor"></a>Execution trace of the mutable-cell example <a class="cross-reference" href="#example:rkt-mutable-cell-main-actor">8.9</a>. On the left, a <tt>flush!</tt> call ensures the effects of <tt>update-cell</tt> messages are visible to <tt>main-actor</tt>; on the right, omitting <tt>flush!</tt> leads to reuse of cached knowledge.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_3_0_0_45">Figure <a class="cross-reference" href="#fig:trace-mutable-cell-main-actor">56</a> shows the reason why. The trace on the left includes <tt>flush!</tt>, while the trace on the right omits <tt>flush!</tt>. Recall that metafunction <span class="lyx-mathjax mathjax-inline">$\FEMIT$</span> (section <a class="cross-reference" href="#sec:Formal-PLLAMBDA-semantics">5.2</a>) coalesces adjacent patch actions produced by an actor. A chain of calls to a <tt>flush!</tt>less variation on <tt>read-cell</tt> results in repeated assertion and retraction of interest in <tt>(cell id _)</tt> assertions, which are then coalesced into <em>no-op, empty patches</em>. Observe the empty patches interleaved in the “8 actions” shown on the right in figure <a class="cross-reference" href="#fig:trace-mutable-cell-main-actor">56</a> as outputs of <tt>main-actor</tt> (center region of middle column). The version shown in example <a class="cross-reference" href="#example:rkt-read-cell">8.8</a>, however, breaks up the chain of patch actions with the message sent as part of the implementation of <tt>flush!</tt> that forces the round trip to the dataspace, leading to the (truncated) longer sequence of interactions shown on the left in figure <a class="cross-reference" href="#fig:trace-mutable-cell-main-actor">56</a>. There, the retraction of interest in <tt>(cell id _)</tt> prior to the <tt>flush!</tt> causes the actor's cached record of the cell's value (stored in the <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> register in <span class="small-caps">Syndicate/λ</span>'s semantics, and an analogous location in the <span class="small-caps">Syndicate/rkt</span> implementation) to be evicted.</p></p><span class="halmos"></span></div>
<h4 id="x_8_4_0_0_1"><a name="toc_8.4"></a><span class="counter section"><span>8.4</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:I/O,-time,-timers"></a><a name="sec:I/O,-time,-timers"></a>I/O, time, timers and timeouts</span></h4><p id="x_8_4_0_0_2">Simple I/O in <span class="small-caps">Syndicate/rkt</span> programs can be performed as normal for Racket programs, via ordinary side-effecting function calls. If a particular I/O action could block—for example, a write to a buffered channel such as a TCP socket, or a read from a serial port—then an alternative strategy must be chosen to allow other conversations to proceed while the program waits. Generally speaking, identification of a blocking I/O facility results in design and construction of a driver actor. This includes pseudo-input operations such as waiting for a certain period of wall-clock time to elapse, exposed in <span class="small-caps">Syndicate</span> as a protocol like everything else.</p><p id="x_8_4_0_0_13">
<div class="theorem-like protocol-description named" id="x_8_4_0_0_12"><span class="counter protocol-description"><span>8.10</span></span><a class="label-anchor" href="#protocol:timer"></a><a name="protocol:timer"></a><span class="lyx-argument">Timer Driver<span class="plain-layout-boundary"></span></span>The <em>timer driver</em> implements this protocol.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_3"><span class="lyx-argument">Module to activate<span class="plain-layout-boundary"></span></span><tt>syndicate/drivers/timer</tt><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_6"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>The protocol involves two messages. The first is<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_4_0_0_4"><tt>(message-struct set-timer (label msecs kind))</tt></p><span class="plain-layout-boundary"></span>where <tt>label</tt> is an arbitrary value and <tt>msecs</tt> is a count of milliseconds. If <tt>kind</tt> is <tt>'absolute</tt>, then <tt>msecs</tt> is interpreted as an absolute moment in time, counted in milliseconds from the machine's epoch; if <tt>kind</tt> is <tt>'relative</tt>, then <tt>msecs</tt> is interpreted as milliseconds in the future, counted from the moment the message is received by the timer driver implementation. The second message type is<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_4_0_0_5"><tt>(message-struct timer-expired (label msecs))</tt></p><span class="plain-layout-boundary"></span>where <tt>label</tt> is the label from a previous <tt>set-timer</tt> message, and <tt>msecs</tt> is the absolute time that the message was sent from the timer driver implementation, counted in milliseconds from the machine's epoch.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_7"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>The unique role of <em>Driver</em> is performed by the actor(s) started when a user program activates the driver's module. The roles of <em>AlarmSetter</em> and <em>AlarmReceiver</em> are performed by user code.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_11"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_4_0_0_10"><li id="x_8_4_0_0_8"><em>Setting</em> (AlarmSetter/Driver). The AlarmSetter sends <tt>set-timer</tt>. The Driver eventually responds with <tt>timer-expired</tt>.</li><li id="x_8_4_0_0_9"><em>Notifying</em> (Driver/AlarmReceiver). The Driver sends <tt>timer-expired</tt>, and the AlarmReceiver interprets it in an application-specific way.</li></ul></div><span class="plain-layout-boundary"></span></div></p><p id="x_8_4_0_0_14">Protocol <a class="cross-reference" href="#protocol:timer">8.10</a> was the first to be implemented during the development of <span class="small-caps">Syndicate</span> and its predecessors, and so is in some ways anachronistic. To begin with, it uses <em>messages</em> in place of <em>assertions</em> for its functionality. This forces clients to take care with respect to ordering of operations. In particular, they must ensure their subscriptions to <tt>timer-expired</tt> messages are in place before the corresponding <tt>set-timer</tt> messages are sent, lest unfortunate scheduling cause them to miss their wake-up call. A so-called “timestate” driver provides an interface to timer functionality that is more idiomatic.</p><p id="x_8_4_0_0_22">
<div class="theorem-like protocol-description named" id="x_8_4_0_0_21"><span class="counter protocol-description"><span>8.11</span></span><a class="label-anchor" href="#protocol:timestate"></a><a name="protocol:timestate"></a><span class="lyx-argument">Timestate<span class="plain-layout-boundary"></span></span>The <em>timestate driver</em> is an ordinary <span class="small-caps">Syndicate/rkt</span> program that exposes this protocol to clients, using protocol <a class="cross-reference" href="#protocol:timer">8.10</a> internally to implement its services.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_15"><span class="lyx-argument">Module to activate<span class="plain-layout-boundary"></span></span><tt>syndicate/drivers/timestate</tt><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_16"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>The protocol involves a single assertion, <tt>(assertion-struct later-than (msecs))</tt>, where <tt>msecs</tt> is an integer denoting an absolute moment in time counted in milliseconds from the machine's epoch. When asserted, it denotes a claim that wall-clock time is equal to or later than the moment mentioned.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_17"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>The unique role of <em>Driver</em> is performed by the actor(s) started when a user program activates the driver's module. The role of <em>TimeObserver</em> is performed by user code.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_20"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_4_0_0_19"><li id="x_8_4_0_0_18"><em>Observing</em> (TimeObserver/Driver). The TimeObserver asserts interest in a particular <tt>later-than</tt> assertion. The Driver eventually responds by asserting it. Once the TimeObserver's interest is withdrawn, the Driver retracts it again.</li></ul></div><span class="plain-layout-boundary"></span></div></p>
<div class="theorem-like numbered example named" id="x_8_4_0_0_27">
<p id="x_8_4_0_0_26"><span class="counter numbered example"><span>8.12</span></span><a class="label-anchor" href="#example:timestate-impl"></a><a name="example:timestate-impl"></a><span class="lyx-argument">Timestate implementation<span class="plain-layout-boundary"></span></span>The “driver” is extremely simple, as it is an ordinary program which reformulates protocol <a class="cross-reference" href="#protocol:timer">8.10</a> into the more palatable form of protocol <a class="cross-reference" href="#protocol:timestate">8.11</a>:<p id="x_8_4_0_0_24">
<pre class="listing" id="x_8_4_0_0_23"><code>(spawn #:name 'drivers/timestate
(during (observe (later-than $msecs))
(define timer-id (gensym 'timestate))
(on-start (send! (set-timer timer-id msecs 'absolute)))
(on (message (timer-expired timer-id _))
(react (assert (later-than msecs))))))
</code></pre></p><p id="x_8_4_0_0_25">The use of <tt>during</tt> (lines 26) creates a facet whose lifetime is scoped to a particular conversation. Upon detection of interest in a particular <tt>later-than</tt> assertion, lines 36 run, creating the endpoints necessary for the conversation and kicking off the conversation between the timestate driver and the underlying timer driver. Line 3 uses Racket's <tt>gensym</tt> utility to generate a fresh symbol, unique within the running operating system process. This symbol is used on line 4 in a <tt>set-timer</tt> message. Recall from section <a class="cross-reference" href="#sec:rkt-Core-forms">6.4</a> that <tt>on-start</tt> forms execute once the endpoints of a new facet are completely configured. This ensures that <tt>set-timer</tt> is transmitted in a context where a subscription to the corresponding <tt>timer-expired</tt> message has already been established (by lines 56). When triggered, that subscription creates a nested facet (line 6) which simply asserts the requested <tt>later-than</tt> record. When the TimeObserver that started this conversation retracts its interest in the <tt>later-than</tt> assertion, the entire <tt>during</tt> facet is terminated. Not only is the subscription to <tt>timer-expired</tt> then retracted, but the nested facet asserting <tt>later-than</tt> is also terminated.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_4_0_0_31">
<p id="x_8_4_0_0_30"><span class="counter numbered example"><span>8.13</span></span><span class="lyx-argument">Use of <tt>later-than</tt><span class="plain-layout-boundary"></span></span>The following program prints a message (line 2), and waits for five seconds (lines 4 and 5). Once the time has elapsed, the facet is terminated, triggering the message of line 3. Finally, the message of line 6 is printed.<p id="x_8_4_0_0_29">
<pre class="listing" id="x_8_4_0_0_28"><code>(spawn #:name 'demo-later-than
(on-start (printf "Starting demo-later-than\n"))
(on-stop (printf "Stopping demo-later-than\n"))
(field [deadline (+ (current-inexact-milliseconds) 5000)])
(stop-when (asserted (later-than (deadline)))
(printf "Deadline expired\n")))
</code></pre></p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_4_0_0_35">
<p id="x_8_4_0_0_32"><span class="counter numbered example"><span>8.14</span></span><a class="label-anchor" href="#example:rkt-updating-deadline"></a><a name="example:rkt-updating-deadline"></a><span class="lyx-argument">Updating a deadline<span class="plain-layout-boundary"></span></span>The following program prints out ten “Tick” messages (from line 5), waiting for one second between each, and then terminates. The endpoint of lines 47 is automatically withdrawn as soon as the value of the <tt>counter</tt> field exceeds 9, and is otherwise triggered every time the <tt>deadline</tt> is reached. After printing a “Tick” message, it increments its <tt>counter</tt> and adjusts the <tt>deadline</tt> forward by another second. Modifying <tt>counter</tt> causes reevaluation of the endpoint's <tt>#:when</tt> clause; modifying <tt>deadline</tt> causes reevaluation of the endpoint's subscription, and triggers the transmission of a patch action into the dataspace, which in turn informs the Timestate driver of the new state of affairs.</p>
<p id="x_8_4_0_0_34">
<pre class="listing" id="x_8_4_0_0_33"><code>(spawn #:name 'demo-updating-later-than
(field [deadline (current-inexact-milliseconds)])
(field [counter 0])
(on #:when (&lt; (counter) 10) (asserted (later-than (deadline)))
(printf "Tick ~v\n" (counter))
(counter (+ (counter) 1))
(deadline (+ (deadline) 1000))))
</code></pre></p><span class="halmos"></span></div><p id="x_8_4_0_0_36">Besides its primary purpose of simplifying interaction with the Timer driver, the Timestate driver offers a pair of utilities, <tt>stop-when-timeout</tt> and <tt>sleep</tt>, that capture frequently-occurring interaction patterns.</p>
<div class="theorem-like numbered example named" id="x_8_4_0_0_41">
<p id="x_8_4_0_0_40"><span class="counter numbered example"><span>8.15</span></span><span class="lyx-argument">Timeouts<span class="plain-layout-boundary"></span></span>The <tt>stop-when-timeout</tt> macro offers a new kind of endpoint which terminates its facet after a certain number of milliseconds have elapsed. If the timeout occurs, the body expressions are executed; if the facet has already terminated for some other reason, the endpoint is withdrawn along with the other endpoints of the facet, and the body expressions are not executed.<p id="x_8_4_0_0_38">
<pre class="listing" id="x_8_4_0_0_37"><code>(define-syntax-rule (stop-when-timeout relative-msecs body ...)
(let ((timer-id (gensym 'timeout)))
(on-start (send! (set-timer timer-id relative-msecs 'relative)))
(stop-when (message (timer-expired timer-id _)) body ...)))
</code></pre></p><p id="x_8_4_0_0_39">The macro expands into an expression to be executed in <em>facet-setup-expr</em> context. The expression creates an <tt>on-start</tt> endpoint which arms the timer, and a <tt>stop-when</tt> endpoint which reacts to the resulting <tt>timer-expired</tt> event by terminating the surrounding facet and executing the <tt>body</tt> forms.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_4_0_0_45">
<p id="x_8_4_0_0_44"><span class="counter numbered example"><span>8.16</span></span><span class="lyx-argument">Use of <tt>stop-when-timeout</tt><span class="plain-layout-boundary"></span></span>The following program terminates itself after three seconds have elapsed. During its execution, it prints the messages of lines 2, 3 and 4, in that order.<p id="x_8_4_0_0_43">
<pre class="listing" id="x_8_4_0_0_42"><code>(spawn #:name 'demo-timeout
(on-start (printf "Starting demo-timeout\n"))
(on-stop (printf "Stopping demo-timeout\n"))
(stop-when-timeout 3000 (printf "Three second timeout fired\n")))
</code></pre></p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_4_0_0_49">
<p id="x_8_4_0_0_48"><span class="counter numbered example"><span>8.17</span></span><a class="label-anchor" href="#example:sleep"></a><a name="example:sleep"></a><span class="lyx-argument">Use of <tt>sleep</tt><span class="plain-layout-boundary"></span></span>We have already seen the definition of <tt>sleep</tt> in section <a class="cross-reference" href="#example:rkt:sleep-definition">6.5</a>. The following program uses <tt>spawn*</tt> to start a new actor in <em>script-expr</em> rather than <em>facet-setup-expr</em> context, allowing it to perform sequential actions such as sending a message, creating a facet, and so on. The program is a <tt>sleep</tt>-based reimplementation of example <a class="cross-reference" href="#example:rkt-updating-deadline">8.14</a>. Where that example was written in an event-based style, this is written in a threaded style <span class="citation citep">(<a class="citation" id="cite-172" href="#bib-Li2007">Li and Zdancewic 2007</a>; <a class="citation" id="cite-173" href="#bib-Haller2009">Haller and Odersky 2009</a>)</span>. It uses Racket's built-in looping construct, <tt>for</tt>, with a range of natural numbers (line 2). Example <a class="cross-reference" href="#example:rkt-updating-deadline">8.14</a>'s <tt>counter</tt> field is replaced with an ordinary Racket variable, and <tt>sleep</tt> is used to cede control to neighboring actors until an appropriate wake-up event arrives, at which point the loop is resumed. The actor terminates once the loop finishes, since it contains no other facets.<p id="x_8_4_0_0_47">
<pre class="listing" id="x_8_4_0_0_46"><code>(spawn* #:name 'demo-sleep
(for [(counter (in-range 10))]
(printf "Sleeping tick ~v\n" counter)
(sleep 1.0)))
</code></pre></p></p><span class="halmos"></span></div><p id="x_8_4_0_0_50">An interesting aspect of the Timestate protocol is that its purpose is to adapt <em>messages</em> to <em>assertions</em>. We will see the reverse case, adapting <span class="small-caps">Syndicate</span> assertions to <em>messages </em>sent over a non-<span class="small-caps">Syndicate</span> communications mechanism, in the context of a simple chat server (section <a class="cross-reference" href="#sec:Placing-PL-on-the-map">11.1</a>).</p><p id="x_8_4_0_0_51">The examples in this section so far have taken the approach of using a driver to perform blocking operations. An alternative, suitable for simple cases, is to make use of an <em>implicit</em> driver, that responds to interest in values yielded by Racket's CML-style events <span class="citation citep">(<a class="citation" id="cite-174" href="#bib-Reppy1999">Reppy 1999</a>; <a class="citation" id="cite-175" href="#bib-plt-tr1">Flatt and PLT 2010</a> <span class="citation-after">version 6.2.1, section 11.2.1</span>)</span>. The protocol is available at the (notional) dataspace surrounding the ground dataspace; that is, actors inhabiting the ground dataspace engage with the event driver via the cross-layer protocol (protocol <a class="cross-reference" href="#protocol:cross-layer">8.3</a>).</p><p id="x_8_4_0_0_60">
<div class="theorem-like protocol-description named" id="x_8_4_0_0_59"><span class="counter protocol-description"><span>8.18</span></span><a class="label-anchor" href="#protocol:cml-events"></a><a name="protocol:cml-events"></a><span class="lyx-argument">CML-style I/O Events<span class="plain-layout-boundary"></span></span> Each of Racket's CML-style events yields zero or more values as its <em>synchronization result</em> when ready. For example, if <tt>sock</tt> is a Racket TCP server socket handle, then <tt>(tcp-accept-evt</tt> <tt>sock)</tt> is an event yielding two values, an input port and an output port, when ready. This protocol allows <span class="small-caps">Syndicate/rkt</span> programs to express interest in such synchronisation results.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_53"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>A single assertion, <tt>external-event</tt>, pairs an event with its synchronisation results:<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_4_0_0_52"><tt>(assertion-struct external-event (descriptor values))</tt></p><span class="plain-layout-boundary"></span>The <tt>descriptor</tt> is the event, and the <tt>values</tt> are a list containing the synchronisation results from the event.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_54"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>The implicit, unique implementation of the <em>Driver</em> role exists just outside the ground dataspace. The <em>EventConsumer</em> role exists at or within the ground dataspace, and interacts with the <em>Driver</em> via the cross-layer protocol.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_4_0_0_58"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_4_0_0_57"><li id="x_8_4_0_0_55"><em>Subscription</em> (EventConsumer/Driver). Assertion of interest in <tt>(external-event </tt><span class="lyx-mathjax mathjax-inline">$e$</span><tt> _)</tt> for some particular Racket event value <span class="lyx-mathjax mathjax-inline">$e$</span> signals the Driver that <span class="lyx-mathjax mathjax-inline">$e$</span> should be added to its collection of active events. Retraction of interest withdraws <span class="lyx-mathjax mathjax-inline">$e$</span> from the same collection.</li><li id="x_8_4_0_0_56"><em>Delivery</em> (Driver/EventConsumer). Periodically, and whenever the ground dataspace as a whole is idle, the system will block, waiting for one of the <span class="lyx-mathjax mathjax-inline">$e$</span>s in the collection of active events to become ready. The first to do so, yielding a list of results <span class="lyx-mathjax mathjax-inline">$r$</span>, leads to a message <tt>(external-event </tt><span class="lyx-mathjax mathjax-inline">$e$</span><tt> </tt><span class="lyx-mathjax mathjax-inline">$r$</span><tt>)</tt> being broadcast.</li></ul></div><span class="plain-layout-boundary"></span></div></p>
<figure id="x_8_4_0_0_62"><a name="fig:example:Terminal-I/O-demo"></a>
<pre class="listing" id="x_8_4_0_0_61"><code>#lang syndicate
(require (only-in racket/port read-bytes-line-evt))
(define e (read-bytes-line-evt (current-input-port) 'any))
(spawn (field [total 0])
(begin/dataflow (printf "The total is ~a.\n" (total)))
(on-stop (printf "Goodbye!\n"))
(on (message (inbound (external-event e (list $input))))
(cond
[(eof-object? input) (stop-current-facet)]
[(string-&gt;number (bytes-&gt;string/utf-8 input)) =&gt;
(lambda (n) (total (+ (total) n)))]
[else (void)])))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>57</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:example:Terminal-I/O-demo"></a>Terminal I/O “running total” program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered example named" id="x_8_4_0_0_66">
<p id="x_8_4_0_0_63"><span class="counter numbered example"><span>8.19</span></span><span class="lyx-argument">Terminal I/O<span class="plain-layout-boundary"></span></span>The program in figure <a class="cross-reference" href="#fig:example:Terminal-I/O-demo">57</a> demonstrates the usage of protocol <a class="cross-reference" href="#protocol:cml-events">8.18</a>. Successive lines of text input appearing on standard input are, if they conform to the syntax for Racket numeric values, interpreted as such and added to an accumulator. Each time the accumulator changes, its new value is printed.</p>
<p id="x_8_4_0_0_64">Line 2 <tt>require</tt>s the <tt>read-bytes-line-evt</tt> event constructor: when given an input port, the constructor yields an event whose synchronization result is either an end-of-file object or a byte-vector containing a single line's worth of text input. Line 3 constructs a single constant event that the program uses throughout. The field declaration on line 4 initializes the accumulator, and line 5 ensures that each time the <tt>total</tt> field is written to, its updated value is printed. Line 6 prints a message when the program terminates.</p>
<p id="x_8_4_0_0_65">Line 7 is the point where the program interacts with the Driver role of protocol <a class="cross-reference" href="#protocol:cml-events">8.18</a>. The actor itself is running within the ground dataspace, but the driver is notionally one layer further out. Therefore, the actor subscribes to messages using an <tt>inbound</tt> constructor to signify that a cross-layer subscription should be established. Each time the event is selected and ready, it yields either a line of text input or an end-of-file value, available as <tt>input</tt> in lines 812. On end-of-file, the program terminates itself (triggering line 6 in the process). If the input text, interpreted as UTF-8 text, can be converted to a number, that number is added to the current value of the <tt>total</tt> field. Otherwise, the input is ignored.</p><span class="halmos"></span></div><p id="x_8_4_0_0_67">Multiple subscriptions to such events may exist in a single running ground dataspace, from different drivers, actors, and protocols. Racket's underlying synchronization mechanism ensures fair (pseudo-random) selection from the set of ready events in case more than one is available at once.</p><p id="x_8_4_0_0_68">Protocol <a class="cross-reference" href="#protocol:cml-events">8.18</a> allows <span class="small-caps">Syndicate/rkt</span> programs to respond to Racket's CML-inspired I/O events. However, it is also possible to use Racket's event mechanism to transmit observations of the interior of a <span class="small-caps">Syndicate/rkt</span> program to other portions of a larger Racket program. For example, a Racket thread may run a <span class="small-caps">Syndicate</span> ground dataspace alongside other Racket-level threads. Within the dataspace, actors can respond to <span class="small-caps">Syndicate</span> events by sending non-<span class="small-caps">Syndicate</span> messages to those other Racket threads. In this way, the programmer may embed <span class="small-caps">Syndicate/rkt</span> subprograms within existing non-<span class="small-caps">Syndicate</span> code.</p>
<h4 id="x_8_5_0_0_1"><a name="toc_8.5"></a><span class="counter section"><span>8.5</span></span><span class="heading-text section">Logic, deduction, databases, and elaboration</span></h4><p id="x_8_5_0_0_2">We have seen that the <span class="small-caps">Syndicate/λ</span> notion of <span class="lyx-mathjax mathjax-inline">$\KDuring$</span> is reminiscent of logical implication. The analogous <span class="small-caps">Syndicate/rkt</span> <tt>during</tt> construct is no different, and allows us to write <span class="small-caps">Syndicate</span> actors that perform <em>deductions</em> based on the assertions in the dataspace, expressed in a quasi-logical style. When relevant information is held elsewhere, such as an external SQL database, or the file system, actors may retrieve information from the external source on demand, presenting the results as assertions. In this way, multiple “proof strategies”, including procedural knowledge, integrate smoothly with ordinary forward- and backward-chaining reasoning about assertions and demand for assertions.</p>
<h5 id="x_8_5_1_0_1"><a name="toc_8.5.1"></a><span class="counter subsection"><span>8.5.1</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Forward-chaining"></a><a name="subsec:Forward-chaining"></a>Forward-chaining</span></h5>
<figure id="x_8_5_1_0_3"><a name="fig:Forward-chaining-Datalog"></a>
<pre class="listing" id="x_8_5_1_0_2"><code>parent(john, douglas).
parent(bob, john).
parent(ebbon, bob).
ancestor(A, C) :- parent(A, C).
ancestor(A, B) :- parent(A, C), ancestor(C, B).
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>58</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Forward-chaining-Datalog"></a>Datalog “ancestor” program.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_8_5_1_0_5"><a name="fig:Forward-chaining-Syndicate"></a>
<pre class="listing" id="x_8_5_1_0_4"><code>(assertion-struct parent (who of))
(assertion-struct ancestor (who of))
(spawn (assert (parent 'john 'douglas)))
(spawn (assert (parent 'bob 'john)))
(spawn (assert (parent 'ebbon 'bob)))
(spawn (during (parent $A $C)
(assert (ancestor A C))
(during (ancestor C $B)
(assert (ancestor A B)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>59</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Forward-chaining-Syndicate"></a>Forward-chaining <span class="small-caps">Syndicate</span> “ancestor” program.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_5_1_0_6">Writing a <span class="small-caps">Syndicate</span> program frequently feels similar to writing a Datalog program. Consider the “ancestor” Datalog predicate shown in figure <a class="cross-reference" href="#fig:Forward-chaining-Datalog">58</a>. A <span class="small-caps">Syndicate</span> encoding of the predicate is shown in figure <a class="cross-reference" href="#fig:Forward-chaining-Syndicate">59</a>. Lines 12 declare the relations involved, implicit in the Datalog equivalent. Lines 35 assert ground terms describing a <span class="lyx-mathjax mathjax-inline">$\mathit{parent}$</span> relation. Lines 69 define an <span class="lyx-mathjax mathjax-inline">$\mathit{ancestor}$</span> relation in a form strongly reminiscent of a proposition involving implication:</p><p id="x_8_5_1_0_8">
<div class="lyx-mathjax mathjax-display" id="x_8_5_1_0_7">\[
\mathit{parent}(A,C)\implies(\mathit{ancestor}(A,C)\wedge(\mathit{ancestor}(C,B)\implies\mathit{ancestor}(A,B)))
\]
</div>Here, the program uses forward-chaining to prove all provable conclusions from the inputs given. The program reacts to <span class="lyx-mathjax mathjax-inline">$\mathit{parent}$</span> assertions (line 6), immediately concluding the consequences of the base case of the inductive definition of <span class="lyx-mathjax mathjax-inline">$\mathit{ancestor}$</span> (line 7; cf. figure <a class="cross-reference" href="#fig:Forward-chaining-Datalog">58</a> line 4) and enabling an additional reaction (lines 89; cf. figure <a class="cross-reference" href="#fig:Forward-chaining-Datalog">58</a> line 5) embodying the inductive step of the <span class="lyx-mathjax mathjax-inline">$\mathit{ancestor}$</span> definition for a <em>specific</em> case. Line 8 reacts to assertion—interpreted as <em>proof</em>—of the inductive hypothesis for the specific case at hand, the specific binding of the variable <tt>C</tt>, and line 9 asserts a conclusion building upon that hypothesis.</p>
<h5 id="x_8_5_2_0_1"><a name="toc_8.5.2"></a><span class="counter subsection"><span>8.5.2</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Backward-chaining"></a><a name="subsec:Backward-chaining"></a>Backward-chaining and Hewitt's “Turing” Syllogism</span></h5><p id="x_8_5_2_0_2">Carl Hewitt's paper describing <tt>PLANNER</tt> includes the following quote, which seems to anticipate the dataspace model <span class="citation citep">(<a class="citation" id="cite-176" href="#bib-Hewitt1971">Hewitt 1971</a>)</span>:</p>
<blockquote id="x_8_5_2_0_4">
<p id="x_8_5_2_0_3">ASSOCIATIVE MEMORY forms the basis for PLANNER'S data space which consists of directed graphs with labeled arcs. [...] Assertions are stored in buckets by their coordinates using the associative memory in order to provide efficient retrieval.</p></blockquote><p id="x_8_5_2_0_5">In the same paper, he offers a syllogistic proof of Turing's fallibility, which can be expressed in <span class="small-caps">Syndicate</span> as shown in figure <a class="cross-reference" href="#fig:Hewitt's-Turing-syllogism">60</a>. Where the example of figure <a class="cross-reference" href="#fig:Forward-chaining-Syndicate">59</a> uses a forward-chaining strategy, our implementation of Hewitt's syllogism uses backwards-chaining. The key difference is the monitoring of interest in <tt>fallible</tt> assertions (line 4). When interest is detected, it is interpreted as a goal, and a small facet (lines 56) using a forward-chaining strategy is constructed to attempt to satisfy the goal.</p>
<figure id="x_8_5_2_0_7"><a name="fig:Hewitt's-Turing-syllogism"></a>
<pre class="listing" id="x_8_5_2_0_6"><code>(assertion-struct human (who))
(assertion-struct fallible (who))
(spawn (assert (human 'turing)))
(spawn (during (observe (fallible $who))
(during (human who)
(assert (fallible who)))))
(spawn (during (fallible 'turing)
(on-start (printf "Turing: fallible\n"))
(on-stop (printf "Turing: infallible\n"))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>60</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Hewitt's-Turing-syllogism"></a>Hewitt's “Turing” syllogism<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h5 id="x_8_5_3_0_1"><a name="toc_8.5.3"></a><span class="counter subsection"><span>8.5.3</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:External-knowledge-sources"></a><a name="subsec:External-knowledge-sources"></a>External knowledge sources: The file-system driver</span></h5><p id="x_8_5_3_0_2">A particularly important external database for many applications is the file system provided by the underlying operating system.</p><p id="x_8_5_3_0_11">
<div class="theorem-like protocol-description named" id="x_8_5_3_0_10"><span class="counter protocol-description"><span>8.20</span></span><a class="label-anchor" href="#protocol:filesystem-driver"></a><a name="protocol:filesystem-driver"></a><span class="lyx-argument">File system<span class="plain-layout-boundary"></span></span><span class="small-caps">Syndicate/rkt</span>'s file system driver implements this protocol, which tracks and publishes the contents of files and directories.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_3_0_3"><span class="lyx-argument">Module to activate<span class="plain-layout-boundary"></span></span><tt>syndicate/drivers/filesystem</tt><span class="plain-layout-boundary"></span></div>
<div class="protocol-section" id="x_8_5_3_0_5"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>The protocol involves a single assertion,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_5_3_0_4"><tt>(assertion-struct file-content (name reader-proc content))</tt></p><span class="plain-layout-boundary"></span>Each <tt>file-content</tt> structure represents a claim about the contents of the file system path <tt>name</tt>. When <tt>content</tt> is <tt>#f</tt>, the claim is that no file or directory exists at that path; otherwise, some file or directory exists at that name, and <tt>content</tt> is the output of <tt>(reader-proc name)</tt>.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_3_0_6"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>The unique role of <em>Driver</em> is performed by the actor(s) started when a user program activates the driver's module. The role of <em>FileObserver</em> is performed by user code.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_3_0_9"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_5_3_0_8"><li id="x_8_5_3_0_7"><em>Observing</em> (FileObserver/Driver). The FileObserver asserts interest in a <tt>file-content</tt> assertion with a specific <tt>name</tt> string and specific <tt>reader-proc</tt>. The Driver will respond with a <tt>file-content</tt> assertion reporting the state of the <tt>name</tt>d file or directory in terms of <tt>reader-proc</tt>'s result. Each time the operating system reports a change to the file at <tt>name</tt>, the Driver re-executes <tt>(reader-proc</tt> <tt>name)</tt> and updates the assertion. Once interest is withdrawn, the Driver retracts the assertion and releases the operating-system-level resources associated with notifications about changes to the file.</li></ul></div><span class="plain-layout-boundary"></span></div></p><p id="x_8_5_3_0_12">This protocol is unusual in that it explicitly requires inclusion of a Racket procedure value in a field of an assertion, depending indirectly on Racket's primitive pointer-equality to compare such values. The reason is the large number and great variety of operations for reading or otherwise analyzing a file system resource. Supplying different <tt>reader-proc</tt> values allows the programmer to specify the nature of the information about the file that is of interest.</p>
<div class="theorem-like numbered example named" id="x_8_5_3_0_17">
<p id="x_8_5_3_0_16"><span class="counter numbered example"><span>8.21</span></span><span class="lyx-argument">Monitoring a file's contents<span class="plain-layout-boundary"></span></span>Monitoring the actual contents of a file can be done using <tt>file-&gt;bytes</tt> as <tt>reader-proc</tt>,<p id="x_8_5_3_0_14">
<p class="align-center" id="x_8_5_3_0_13"><tt>(on (asserted (file-content "novel.txt" file-&gt;bytes $bytes)) ...)</tt></p></p><p id="x_8_5_3_0_15">In the event-handling code, <tt>bytes</tt> contains the raw bytes making up the file, or <tt>#f</tt> if the file does not exist or was deleted.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_5_3_0_22">
<p id="x_8_5_3_0_21"><span class="counter numbered example"><span>8.22</span></span><span class="lyx-argument">Monitoring a directory's entries<span class="plain-layout-boundary"></span></span>Monitoring the list of files in a directory can be done with <tt>directory-list</tt> as <tt>read-proc</tt>,<p id="x_8_5_3_0_19">
<p class="align-center" id="x_8_5_3_0_18"><tt>(on (asserted (file-content "/tmp" directory-list $files)) ...)</tt></p></p><p id="x_8_5_3_0_20">The <tt>files</tt> variable contains a list of the names of the files in <tt>/tmp</tt>. Each time a file is added or removed, the <tt>file-content</tt> assertion is replaced. If the directory is deleted, <tt>files</tt> becomes <tt>#f</tt>.</p></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_5_3_0_27">
<p id="x_8_5_3_0_26"><span class="counter numbered example"><span>8.23</span></span><a class="label-anchor" href="#example:rkt:file-&gt;sha1"></a><a name="example:rkt:file-&gt;sha1"></a><span class="lyx-argument">Detecting whether a file's content has changed<span class="plain-layout-boundary"></span></span>Given a small utility procedure <tt>file-&gt;sha1</tt> (shown in figure <a class="cross-reference" href="#fig:rkt:Automatic-Make-like-compiler">61</a>) to use for <tt>read-proc</tt>, we may track a secure hash of the file's contents with the endpoint<p id="x_8_5_3_0_24">
<p class="align-center" id="x_8_5_3_0_23"><tt>(on (asserted (file-content "novel.txt" file-&gt;sha1 $hash)) ...)</tt></p></p><p id="x_8_5_3_0_25">As usual, <tt>hash</tt> is <tt>#f</tt> if the file is not present; otherwise, it is a string containing a hexadecimal representation of the SHA-1 hash of the file's content. The properties of such secure hashes allow us to treat a changed <tt>hash</tt> as a change in the underlying file content, without having to relay the entirety of the contents via the dataspace.</p></p><span class="halmos"></span></div><p id="x_8_5_3_0_28">Commodity operating systems offer only the simplest of change-notification systems, essentially nothing more than a message signifying that <em>something</em> changed about a given path. This is akin to the monolithic SCN events of the dataspace model, which place the burden of determining the nature of a given change on the recipient of each event. The dataspace model's <em>incremental</em> patch SCN events convey the same information, but relieve actors of this burden. Augmenting operating systems with more fine-grained notifications would help in the same way, improving efficiency around reacting to changes in the file system.</p>
<h5 id="x_8_5_4_0_1"><a name="toc_8.5.4"></a><span class="counter subsection"><span>8.5.4</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Procedural-knowledge"></a><a name="subsec:Procedural-knowledge"></a>Procedural knowledge and Elaboration: “Make”</span></h5><p id="x_8_5_4_0_2">The Unix program <tt>make</tt> <span class="citation citep">(<a class="citation" id="cite-177" href="#bib-IEEE-9945-2009">IEEE 2009</a> <span class="citation-after">``Shell and Utilities'' volume</span>)</span> is a venerable tool for systematically producing conclusions (<em>target</em> files) from premises (<em>source</em> files) by way of procedural knowledge (<em>rules</em>). We may similarly combine deduction with procedural knowledge in <span class="small-caps">Syndicate</span>.</p>
<figure id="x_8_5_4_0_4"><a name="fig:rkt:Automatic-Make-like-compiler"></a>
<pre class="listing" id="x_8_5_4_0_3"><code>#lang syndicate
(require/activate syndicate/drivers/filesystem)
(require racket/string racket/system file/sha1)
(define (file-&gt;sha1 p) (call-with-input-file p sha1))
(spawn (during (observe (file-content $name _ _))
(unless (string-suffix? name ".c")
(define name.c (string-append name ".c"))
(on (asserted (file-content name.c file-&gt;sha1 $hash)) ;; nb. $hash, not _
(cond [(not hash) (printf "~a doesn't exist.\n" name.c)]
[else
(printf "~a has changed hash to ~a, recompiling\n" name.c hash)
(system* (find-executable-path "cc") "-o" name name.c)])))))
(spawn (on (asserted (file-content "." directory-list $files))
(for [(name-path (in-list files))]
(match (path-&gt;string name-path)
[(pregexp #px"(.*)\\.c" (list _ name))
(assert! (observe (file-content name file-exists? #t)))]
[_ (void)]))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>61</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:rkt:Automatic-Make-like-compiler"></a>Automatic “Make”-like compiler<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="theorem-like numbered example named" id="x_8_5_4_0_8">
<p id="x_8_5_4_0_5"><span class="counter numbered example"><span>8.24</span></span><span class="lyx-argument">Make-like compiler<span class="plain-layout-boundary"></span></span>The program of figure <a class="cross-reference" href="#fig:rkt:Automatic-Make-like-compiler">61</a> implements a pair of actors which, together, use the file system driver (protocol <a class="cross-reference" href="#protocol:filesystem-driver">8.20</a>) to track the “.c” files in the current directory, compiling them to executables each time one changes.</p>
<div class="footnote" id="fn_8_91"><span class="counter footnote-counter"><span>91</span></span>Use of a blocking call here is suboptimal: it indicates the need for a <em>subprocess</em> driver for starting, managing, and terminating subprocesses.<span class="plain-layout-boundary"></span></div>
<p id="x_8_5_4_0_6">The first actor (lines 512) interprets interest in a file named <tt>name</tt> to be a request that it should be compiled from <tt>name.c</tt>, if that file exists. Each time <tt>name.c</tt> is created or changes (cf. example <a class="cross-reference" href="#example:rkt:file-&gt;sha1">8.23</a>), the actor shells out to <tt>cc(1)</tt> to compile the program.<label class="footnote-number" for="fn_8_91">91</label> There are two notable features of this portion of the program. The first is the use of <tt>unless</tt> on line 6 to <em>conditionally</em> add endpoints to the facet of the <tt>during</tt> of line 5. When interest is expressed in some file, we only attempt to build it from some corresponding C source file if the file of interest is not already a C source file. In the case that <tt>name</tt> ends with “.c”, the facet created by the activation of <tt>during</tt> on line 5 is terminated automatically since it lacks endpoints entirely. The second interesting feature is the use of a binding, <tt>$hash</tt>, on line 8, where one might expect to see a discard pattern,<tt> _</tt>. Recall that <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> discards irrelevant structure from observed assertions during projection of incoming patch events. Had we used discard in place of <tt>$hash</tt>, we would have been declaring our lack of interest in such fine detail as the hash of the file being different, and would instead react only to the file having a hash <em>at all</em>. By using <tt>$hash</tt>, we convey that we care about specific values of <tt>hash</tt>, and thus that we should react every time the file's content changes.</p>
<p id="x_8_5_4_0_7">The second actor (lines 1318) monitors the files in the current directory. Every time it sees a file whose name ends in “.c”, it strips that extension, and asserts interest in the existence of the resulting base filename. A more robust program would be able to <em>retract</em> interest in case such a file were erased (perhaps in turn leading to deletion of the corresponding build product); however, this program contents itself with an ever-growing collection of filenames of interest. It uses the ad-hoc assertion form, <tt>assert!</tt>, discussed in section <a class="cross-reference" href="#sec:Ad-hoc-assertions">6.6</a>.</p><span class="halmos"></span></div><p id="x_8_5_4_0_9">The form of the actor of lines 512 in figure <a class="cross-reference" href="#fig:rkt:Automatic-Make-like-compiler">61</a> is essentially the same as that of lines 46 in our implementation of Hewitt's “Turing” syllogism (figure <a class="cross-reference" href="#fig:Hewitt's-Turing-syllogism">60</a>). This tells us that our “Make”-like program is also taking a backtracking strategy to goal satisfaction. The difference here is use of <em>procedural</em> knowledge as the local strategy for achieving some goal. In the “Make”-like program, we know that invoking the C compiler will achieve our goal, while in the “Turing” syllogism, the goal is an immediate logical consequence of the premise detected on line 5 of figure <a class="cross-reference" href="#fig:Hewitt's-Turing-syllogism">60</a>.</p><p id="x_8_5_4_0_10">The notion of an <em>elaboration</em> of a formalism captures the idea of its modification to take into account new phenomena <span class="citation citep">(<a class="citation" id="cite-178" href="#bib-McCarthy1998">McCarthy 1998</a>)</span>. A simple example of this is the need to compute additional or derived information about a domain entity. The “Make” example can be seen as an instance of this, augmenting information about a source file with information about its compiled form. Such augmentation is promoted to a design pattern and given the name of <em>Content Enrichment</em> by <span class="citation citet"><a class="citation" id="cite-179" href="#bib-Hohpe2004"><span>Hohpe and Woolf<span class="parens"> (</span>2004<span class="parens">)</span></span></a></span>; the examples they present can be readily adapted to the idioms introduced in this section.</p>
<h5 id="x_8_5_5_0_1"><a name="toc_8.5.5"></a><span class="counter subsection"><span>8.5.5</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Incremental-truth-maintenance-and-Aggregation"></a><a name="subsec:Incremental-truth-maintenance-and-Aggregation"></a>Incremental truth-maintenance and Aggregation: All-pairs shortest paths</span></h5>
<figure id="x_8_5_5_0_3"><a name="fig:rkt:All-pairs-shortest-paths"></a>
<pre class="listing" id="x_8_5_5_0_2"><code>#lang syndicate
(require racket/set)
(assertion-struct link (from to cost))
(assertion-struct path (from to seen cost))
(assertion-struct min-cost (from to cost))
(spawn (assert (link 1 3 -2))
(assert (link 2 1 4))
(assert (link 2 3 3))
(assert (link 3 4 2))
(assert (link 4 2 -1)))
(spawn (during (link $from $to $cost)
(assert (path from to (set from to) cost))))
(spawn (during (link $A $B $link-cost)
(during (path B $C $seen $path-cost)
(assert #:when (not (set-member? seen A))
(path A C (set-add seen A) (+ link-cost path-cost))))))
(spawn (during (path $from $to _ _)
(field [costs (set)] [least +inf.0])
(assert (min-cost from to (least)))
(on (asserted (path from to _ $cost))
(costs (set-add (costs) cost))
(least (min (least) cost)))
(on (retracted (path from to _ $cost))
(define new-costs (set-remove (costs) cost))
(costs new-costs)
(least (for/fold [(least +inf.0)] [(x new-costs)] (min x least))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>62</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:rkt:All-pairs-shortest-paths"></a><span class="lyx-argument">All-pairs shortest paths program<span class="plain-layout-boundary"></span></span>All-pairs shortest paths program. After Figure 1 of <span class="citation citet"><a class="citation" id="cite-180" href="#bib-Conway2012"><span>Conway et al.<span class="parens"> (</span>2012<span class="parens">)</span></span></a></span>, but modified with a <tt>path-seen</tt> set to ensure termination on input cycles.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_5_5_0_4">In their recent paper, <span class="citation citet"><a class="citation" id="cite-181" href="#bib-Conway2012"><span>Conway et al.<span class="parens"> (</span>2012<span class="parens">)</span></span></a></span> present a short program which solves the all-pairs shortest-paths problem, written in their distributed, Datalog-based language Bloom <span class="citation citep">(<a class="citation" id="cite-182" href="#bib-Alvaro2011">Alvaro et al. 2011</a>)</span>. An analogous <span class="small-caps">Syndicate/rkt</span> program is shown in figure <a class="cross-reference" href="#fig:rkt:All-pairs-shortest-paths">62</a>. Each <tt>link</tt> assertion (lines 610) forms part of the program's input, describing a weighted edge in a directed graph. The program computes <tt>path</tt> assertions as it proceeds (lines 1116), though these are an implementation detail; it is the <tt>min-cost</tt> assertions (lines 1726) that are the outputs of the program. Each <tt>min-cost</tt> assertion describes a path between two nodes in the input graph, along with the computed minimum total cost for that path. As <tt>link</tt> edges are added and removed, the program reacts, converging on a solution and quiescing once it is achieved.</p>
<div class="footnote" id="fn_8_92"><span class="counter footnote-counter"><span>92</span></span>We discuss options for eliminating interference from intermediate states in section <a class="cross-reference" href="#sec:Dataflow-and-reactive">8.8</a>.<span class="plain-layout-boundary"></span></div><p id="x_8_5_5_0_5">The program demonstrates two important <span class="small-caps">Syndicate</span> idioms. The first is the ability for programs expressed in this style to incrementally maintain outputs as inputs change. Altering the set of asserted <tt>link</tt> records leads to a corresponding update to the set of asserted <tt>min-cost</tt> records—though intermediate states become visible as the computation proceeds back toward consistency.<label class="footnote-number" for="fn_8_92">92</label></p><p id="x_8_5_5_0_6">The second idiom is aggregation of a set of assertions into a single <em>summary</em> of the set; here, this is seen in the actor of lines 1726, which computes the <em>minimum</em> of a set of paths from A to B. The aggregation operator here is thus “set minimum”. The pattern <tt>(path $from $to _ _)</tt> of line 17 scopes each computation to a particular source/sink node pair. Within this context, two fields are maintained: the first, <tt>costs</tt>, tracks all distinct path costs, while the second, <tt>least</tt>, contains the smallest cost in <tt>(costs)</tt>. As a new distinct cost appears (line 20), it is added to the set, and <tt>least</tt> is efficiently updated. However, when a distinct cost disappears (line 23), we must laboriously recompute <tt>least</tt> from an updated <tt>costs</tt>. A heap or ordered-set data structure would eliminate this problem.</p><p id="x_8_5_5_0_7">This idiom of maintaining an order statistic could be abstracted into a new streaming query form, perhaps called <tt>define/query-min</tt> by analogy with the existing aggregate query forms introduced in section <a class="cross-reference" href="#par:Streaming-queries">6.5</a>. In fact, the Bloom program of <span class="citation citeauthor"><a class="citation" id="cite-183" href="#bib-Conway2012">Conway et al.</a></span> makes use of a built-in operator supporting a minimum-value calculation. Setting aside the explicit, non-library implementation of computing the minimum, our program is comparable in length to the Bloom program, showing that Bloom-like Datalog-style programming is achievable and useful in <span class="small-caps">Syndicate</span>, though of course <span class="small-caps">Syndicate</span> does not yet extend to distributed systems. An interesting question to examine is to what extent reasoning based on logical monotonicity, as introduced in the Bloom “CALM theorem” <span class="citation citep">(<a class="citation" id="cite-184" href="#bib-Alvaro2011">Alvaro et al. 2011</a>)</span>, translates well to <span class="small-caps">Syndicate</span>.</p>
<h5 id="x_8_5_6_0_1"><a name="toc_8.5.6"></a><span class="counter subsection"><span>8.5.6</span></span><span class="heading-text subsection"><a class="label-anchor" href="#subsec:Modal-reasoning-Advertisement"></a><a name="subsec:Modal-reasoning-Advertisement"></a>Modal reasoning: Advertisement</span></h5><p id="x_8_5_6_0_2">Earlier work on Network Calculus (NC) <span class="citation citep">(<a class="citation" id="cite-185" href="#bib-Garnock-Jones2014">Garnock-Jones, Tobin-Hochstadt and Felleisen 2014</a>)</span> included only a limited form of observable, replicated, shared state: the state of <em>subscriptions</em> to messages within each dataspace. The dataspace model generalizes this to allow observation of arbitrary shared assertions, and brings messages into the new setting by reinterpreting them as transient knowledge. However, NC included <em>two</em> forms of subscription. The traditional notion of “subscription” led to actors receiving messages produced by publishers, but a symmetric notion of “advertisement” led to publishers receiving <em>feedback</em> from subscribers. The dataspace model drops the idea of feedback, and with it the idea of a distinct publisher, leaving it to domain-specific protocols to include such notions as appropriate. Examining NC programs shows that the primary use of feedback and observation of “publisher” endpoints was to detect whether messages of a certain type <em>might potentially be produced in the near future</em>. Absence of a “publisher” was interpreted as meaning that there was no need to prepare to receive that publisher's communications; its presence, by contrast, suggested that it might begin speaking soon. <span class="small-caps">Syndicate</span> and the dataspace model captures this idea with an <em>advertisement</em> protocol.</p><p id="x_8_5_6_0_6">
<div class="theorem-like protocol-description named" id="x_8_5_6_0_5"><span class="counter protocol-description"><span>8.25</span></span><a class="label-anchor" href="#protocol:advertisement"></a><a name="protocol:advertisement"></a><span class="lyx-argument">Advertisement<span class="plain-layout-boundary"></span></span>The <em>advertisement</em> protocol decouples synchronization of conversational context from subsequent conversational interaction.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_3"><span class="lyx-argument">Module to require<span class="plain-layout-boundary"></span></span><tt>syndicate/protocol/advertise</tt><span class="plain-layout-boundary"></span></div>
<div class="protocol-section" id="x_8_5_6_0_4"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span><tt>(assertion-struct advertise (claim))</tt><span class="plain-layout-boundary"></span>An assertion of <tt>(advertise</tt> <span class="lyx-mathjax mathjax-inline">$c$</span><tt>)</tt> denotes the potential for <em>future</em> assertion of <span class="lyx-mathjax mathjax-inline">$c$</span> itself, across some unspecified timescale. Other protocols will incorporate this protocol, as seen earlier in protocols <a class="cross-reference" href="#protocol:interest">8.2</a> and <a class="cross-reference" href="#protocol:cross-layer">8.3</a>. No particular obligations are placed on parties asserting <tt>advertise</tt> records, other than the loose notion that they may eventually produce an assertion of the underlying <tt>claim</tt>.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span></div></p><p id="x_8_5_6_0_7">Advertisement allows us to explore an alternative factoring of protocol <a class="cross-reference" href="#protocol:mutable-cell">8.5</a>.</p><p id="x_8_5_6_0_15">
<div class="theorem-like protocol-description named" id="x_8_5_6_0_14"><span class="counter protocol-description"><span>8.26</span></span><span class="lyx-argument">Mutable cell, with advertisement<span class="plain-layout-boundary"></span></span>In place of explicit command messages, we will create and destroy Cell actors in response to presence or absence of advertisements of potential <tt>update-cell</tt> messages and potential subscription to <tt>cell</tt> assertions.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_8"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>As for protocol <a class="cross-reference" href="#protocol:mutable-cell">8.5</a>, omitting <tt>create-cell</tt> and <tt>delete-cell</tt>, and adding <tt>(advertise (update-cell id _))</tt> and <tt>(advertise (observe (cell id _)))</tt>.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_9"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>As for protocol <a class="cross-reference" href="#protocol:mutable-cell">8.5</a>.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_13"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span>As for protocol <a class="cross-reference" href="#protocol:mutable-cell">8.5</a>, but replacing Creation and Deleting as follows:<span class="plain-layout-boundary"></span>
<ul id="x_8_5_6_0_12"><li id="x_8_5_6_0_10"><em>Creation</em> (Writer/Reader/CellFactory). In response to one of the forms of advertisement mentioned above, the CellFactory creates a new cell, initially with no value (and thus publishing no <tt>cell</tt> assertion).</li><li id="x_8_5_6_0_11"><em>Deleting</em> (Writer/Reader/Cell). Each Cell monitors both forms of advertisement (specific to its ID) mentioned above; once all advertisements have been retracted, it terminates itself.</li></ul></div><span class="plain-layout-boundary"></span></div></p>
<div class="theorem-like numbered example named" id="x_8_5_6_0_20">
<p id="x_8_5_6_0_19"><span class="counter numbered example"><span>8.27</span></span><a class="label-anchor" href="#example:mutable-cell-plus-advertisement"></a><a name="example:mutable-cell-plus-advertisement"></a><span class="lyx-argument">Mutable cell, with advertisement<span class="plain-layout-boundary"></span></span> <p id="x_8_5_6_0_17">
<pre class="listing" id="x_8_5_6_0_16"><code>(spawn #:name 'cell-factory
(assertion-struct cell-existence-demanded (id))
(during (advertise (update-cell $id _)) (assert (cell-existence-demanded id)))
(during (advertise (observe (cell $id _))) (assert (cell-existence-demanded id)))
(during/spawn (cell-existence-demanded $id)
(field [has-value? #f] [value (void)])
(assert #:when (has-value?) (cell id (value)))
(on (message (update-cell id $new-value))
(has-value? #t)
(value new-value))))
</code></pre></p>
<div class="footnote" id="fn_8_93"><span class="counter footnote-counter"><span>93</span></span>In principle, we could imagine augmenting <span class="small-caps">Syndicate</span>'s pattern language with an “<tt>or</tt>” construct that implemented this pattern automatically: <tt>(advertise (or (update-cell $id _) (observe (cell $id _))))</tt>. There is no fundamental obstacle to such a feature.<span class="plain-layout-boundary"></span></div><p id="x_8_5_6_0_18">Line 2 declares an implementation-local structure type representing an intermediate piece of knowledge: that a cell with a particular ID should exist. Lines 3 and 4 deduce such facts from the two forms of relevant advertisement.<label class="footnote-number" for="fn_8_93">93</label> The consequences of a <tt>cell-existence-demanded</tt> assertion are spelled out on lines 510. Line 5 means that each distinct ID demanded results in a separate actor; once the demand for cell existence is retracted, by retraction of all corresponding advertisement assertions, the actor is automatically terminated. Lines 610 follow the implementation of our earlier mutable cell protocol closely. The main differences are a lack of a <tt>stop-when</tt> clause reacting to <tt>delete-cell</tt> messages, replaced by the action of <tt>during/spawn</tt> on line 5, and addition of the <tt>has-value?</tt> field, which accounts for the new protocol's cells lacking a value initially. Line 7 publishes a <tt>cell</tt> assertion only once a value is available.</p></p><span class="halmos"></span></div>
<div class="footnote" id="fn_8_94"><span class="counter footnote-counter"><span>94</span></span>This description covers only UDP <em>listener</em> sockets. Much other functionality including UDP multicast is available in the implementation.<span class="plain-layout-boundary"></span></div><p id="x_8_5_6_0_21"><span class="small-caps">Syndicate/rkt</span>'s support for UDP communication makes use of protocol <a class="cross-reference" href="#protocol:advertisement">8.25</a> to signal that the socket backing a request for service is ready.<label class="footnote-number" for="fn_8_94">94</label></p><p id="x_8_5_6_0_38">
<div class="theorem-like protocol-description named" id="x_8_5_6_0_37"><span class="counter protocol-description"><span>8.28</span></span><a class="label-anchor" href="#protocol:udp"></a><a name="protocol:udp"></a><span class="lyx-argument">UDP sockets<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_22"><span class="lyx-argument">Module to activate<span class="plain-layout-boundary"></span></span><tt>syndicate/drivers/udp</tt><span class="plain-layout-boundary"></span></div>
<div class="protocol-section" id="x_8_5_6_0_26"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>The core of the protocol is<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_5_6_0_23"><tt>(assertion-struct udp-packet (source destination body))</tt></p><span class="plain-layout-boundary"></span>where <tt>body</tt> is a Racket byte-vector and <tt>source</tt> and <tt>destination</tt> are instances of<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_5_6_0_24"><tt>(assertion-struct udp-remote-address (host port))</tt> or</p><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_5_6_0_25"><tt>(assertion-struct udp-listener (port))</tt></p><span class="plain-layout-boundary"></span>A <tt>udp-packet</tt> must either have a <tt>udp-remote-address</tt> in its <tt>source</tt> field, and a <tt>udp-listener</tt> in its <tt>destination</tt> field, or vice versa.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_27"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>There are three roles: <em>SocketFactory</em>, which responds to demand for sockets; <em>Socket</em>, which mediates between local actors and a Racket socket resource; and <em>Client</em>, a local actor making use of UDP functionality.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_5_6_0_36"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_5_6_0_35"><li id="x_8_5_6_0_29"><em>Listening</em> (Client/SocketFactory/Socket). The Client chooses a port number <tt>port</tt> and asserts interest in <tt>(udp-packet _ (udp-listener port) _)</tt>.In response, the SocketFactory begins performing a corresponding Socket role (e.g. by delegating this responsibility to a new actor). The Socket asserts<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_5_6_0_28"><tt>(advertise (udp-packet _ (udp-listener port) _))</tt>,</p><span class="plain-layout-boundary"></span>which the Client may choose to observe to detect when the underlying UDP socket resource is ready to forward inbound packets.<span class="plain-layout-boundary"></span>The Socket also expresses interest in <tt>(udp-packet (udp-listener port) _ _)</tt>, in order to receive packets intended to be relayed to remote parties; the Client may also make decisions based on the presence of such interest. Once a Socket actor is established and ready, <em>Reading</em> and <em>Writing</em> conversations take place.<span class="plain-layout-boundary"></span></li><li id="x_8_5_6_0_31"><em>Reading</em> (Client/Socket). When the underlying UDP socket receives a datagram from <tt>peer-host</tt> at <tt>peer-port</tt> with a certain <tt>body</tt>, it sends a
<p class="align-center" id="x_8_5_6_0_30"><tt>(udp-packet (udp-remote-address peer-host peer-port) (udp-listener port) body)</tt></p><span class="plain-layout-boundary"></span>message. The Client, having previously declared interest in such messages, receives it.<span class="plain-layout-boundary"></span></li><li id="x_8_5_6_0_33"><em>Writing</em> (Client/Socket) The Client may send a
<p class="align-center" id="x_8_5_6_0_32"><tt>(udp-packet (udp-listener port) (udp-remote-address peer-host peer-port) body)</tt></p><span class="plain-layout-boundary"></span>to deliver <tt>body</tt> to any <tt>peer-host</tt> and <tt>peer-port</tt>. The Socket will receive it and relay it via the Racket socket resource.<span class="plain-layout-boundary"></span></li><li id="x_8_5_6_0_34"><em>Closing</em> (Client/Socket) The Client may withdraw its interest in inbound <tt>udp-packet</tt>s. The Socket detects this, closes the underlying UDP socket resource, and terminates, thus withdrawing its <tt>advertise</tt>ment of readiness and its interest in outbound packets.</li></ul></div><span class="plain-layout-boundary"></span></div></p>
<div class="theorem-like numbered example named" id="x_8_5_6_0_42">
<p id="x_8_5_6_0_41"><span class="counter numbered example"><span>8.29</span></span><span class="lyx-argument">UDP echo program<span class="plain-layout-boundary"></span></span>The following actor listens for packets on port 5999, echoing each back to its sender as it is received; as soon as it knows packets may be forwarded to it, it prints a message saying so.<p id="x_8_5_6_0_40">
<pre class="listing" id="x_8_5_6_0_39"><code>(spawn (on (message (udp-packet $peer (udp-listener 5999) $body))
(send! (udp-packet (udp-listener 5999) peer body)))
(on (asserted (advertise (udp-packet _ (udp-listener 5999) _)))
(printf "Socket is ready and will forward datagrams.\n")))
</code></pre></p></p><span class="halmos"></span></div><p id="x_8_5_6_0_43">The UDP socket protocol was designed originally for our implementation of Network Calculus, which explains its awkward use of advertisement in place of a more straightforward <tt>udp-socket-ready</tt> assertion or similar. While the protocol of <em>interest</em> (protocol <a class="cross-reference" href="#protocol:interest">8.2</a>) is essential to the dataspace model, the protocol of <em>advertisement</em> appears to have much more limited applicability.</p><p id="x_8_5_6_0_44">Despite this limited applicability, the general interpretation of the protocol remains of interest. Taking <tt>(advertise </tt><span class="lyx-mathjax mathjax-inline">$c$</span><tt>)</tt> to mean “eventually <span class="lyx-mathjax mathjax-inline">$c$</span>” or “possibly <span class="lyx-mathjax mathjax-inline">$c$</span>” suggests a connection with the modal logic <span class="lyx-mathjax mathjax-inline">$\diamond$</span> operator <span class="citation citep">(<a class="citation" id="cite-186" href="#bib-Manna1991">Manna and Pnueli 1991</a>; <a class="citation" id="cite-187" href="#bib-VanDitmarsch">van Ditmarsch, van der Hoek and Kooi 2017</a>)</span>. We have seen that <tt>(during</tt> <em>P </em><tt>(assert </tt><em>E</em><tt>))</tt> reads as <span class="lyx-mathjax mathjax-inline">$P\implies E$</span>; perhaps it is, in truth, closer to some interpretation of <span class="lyx-mathjax mathjax-inline">$\square(P\implies E)$</span>. It remains future work to explore this connection further.</p><p id="x_8_5_6_0_45">Finally, while advertisement has limited use within domain-specific protocols, it is of great benefit in the setting of publish/subscribe middleware, where it is used to optimize message routing overlays <span class="citation citep">(<a class="citation" id="cite-188" href="#bib-Carzaniga2000">Carzaniga, Rosenblum and Wolf 2000</a>; <a class="citation" id="cite-189" href="#bib-Pietzuch2002">Pietzuch and Bacon 2002</a>; <a class="citation" id="cite-190" href="#bib-Jayaram2011">Jayaram and Eugster 2011</a>; <a class="citation" id="cite-191" href="#bib-Martins2010">Martins and Duarte 2010</a>; <a class="citation" id="cite-192" href="#bib-Eugster2003">Eugster et al. 2003</a>)</span>. Automatic, conservative overapproximation of the assertions an actor may produce could lead to efficiency gains in <span class="small-caps">Syndicate</span> implementations, which may become particularly useful in any attempt to scale the design to distributed systems.</p>
<h4 id="x_8_6_0_0_1"><a name="toc_8.6"></a><span class="counter section"><span>8.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Dependency-resolution-and-Startup"></a><a name="sec:Dependency-resolution-and-Startup"></a>Dependency resolution and lazy startup: Service presence</span></h4>
<div class="footnote" id="fn_8_95"><span class="counter footnote-counter"><span>95</span></span>At least, this is the ideal.<span class="plain-layout-boundary"></span></div><p id="x_8_6_0_0_2">Unix systems start up their system service programs in an order which guarantees that the dependencies of each program are all ready before that program is started.<label class="footnote-number" for="fn_8_95">95</label> Many current Unix distributions manually schedule the system startup process. Because it is a complex process, such manually-arranged boot sequences tend to be strictly sequential. Other distributions are starting to use tools like <tt>make</tt> both to automatically compute a suitable startup ordering and to automatically parallelize system startup.</p><p id="x_8_6_0_0_3">With <span class="small-caps">Syndicate</span>, we can both ensure correct ordering and automatically parallelize system startup where possible, by taking advantage of <em>service presence</em> information <span class="citation citep">(<a class="citation" id="cite-193" href="#bib-Konieczny2009">Konieczny et al. 2009</a>)</span>. Programs offer their services via endpoints; clients of these services interpret the presence of these endpoints as service availability and react, offering up their own services in turn when a service they depend upon becomes available.</p><p id="x_8_6_0_0_4">Service availability must, at some level, be expressed in a concrete style, with endpoints interacting with their environment in terms of the actual messages of the protocols supported by the service. However, availability may also be expressed at a more abstract level. Consumers of a service may detect service presence by directly observing the presence of endpoints engaging in a protocol of interest, or by observing the presence of assertions describing the service more abstractly. The former corresponds to a kind of <em>structural</em> presence indicator, while the latter corresponds to a form of <em>nominal</em> service presence.</p>
<figure id="x_8_6_0_0_6"><a name="fig:Service-dependency-resolution"></a>
<pre class="listing" id="x_8_6_0_0_5"><code>(assertion-struct service-ready (name))
(spawn (assert (service-ready 'file-systems)) ...)
(spawn (stop-when (asserted (service-ready 'file-systems))
(react (assert (service-ready 'database-service)) ...)))
(spawn (stop-when (asserted (service-ready 'file-systems))
(react (assert (service-ready 'logging-service)) ...)))
(spawn (stop-when (asserted (service-ready 'database-service))
(react (stop-when (asserted (service-ready 'logging-service))
(react (assert (service-ready 'web-application-server))
...)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>63</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Service-dependency-resolution"></a>Service dependency resolution<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_6_0_0_7">For example, a web application server may depend on a SQL database service as well as on the system logging service, which may in turn depend on the machine's file systems all being mounted. Figure <a class="cross-reference" href="#fig:Service-dependency-resolution">63</a> sketches a <span class="small-caps">Syndicate</span> realization of these service dependencies, with the actual implementations of each service replaced by ellipses. We may arbitrarily reorder the services in the file without changing the order in which they become available. The startup procedures of the services in the sketch pause until they see the <em>names</em> of their dependencies asserted. An alternative would be to wait for assertions of interest in service requests to appear; concretely, the web application could wait until <tt>(asserted (observe (log-message ...)))</tt> rather than waiting for <tt>(asserted 'logging-service-ready)</tt>.</p>
<figure id="x_8_6_0_0_9"><a name="fig:service-dependency-macros"></a>
<pre class="listing" id="x_8_6_0_0_8"><code>(define-syntax await-services
(syntax-rules ()
[(_ [] body ...)
(begin body ...)]
[(_ [service more ...] body ...)
(stop-when (asserted (service-ready service))
(react (await-services [more ...] body ...)))]))
(define-syntax spawn-service
(syntax-rules (&lt;-)
[(_ target &lt;- [service ...] body ...)
(spawn (await-services [service ...]
(assert (service-ready target))))]))
(spawn-service 'file-systems &lt;- [] ...)
(spawn-service 'database-service &lt;- ['file-systems] ...)
(spawn-service 'logging-service &lt;- ['file-systems] ...)
(spawn-service 'web-application-server &lt;- ['database-service
'logging-service]
...)
</code></pre><figcaption><span class="counter figure"><span>64</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:service-dependency-macros"></a>Macros abstracting away details of the service dependency pattern.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_6_0_0_10">Examination of the sketch of figure <a class="cross-reference" href="#fig:Service-dependency-resolution">63</a> reveals a <em>design pattern</em>. Service actors start in a state awaiting their first dependency. When it appears, they transition to a state awaiting their second dependency; and so on, until all their dependencies are available, at which point the service configures its own offerings and asserts its own availability. A pair of simple macros allows us to abstract over this pattern; figure <a class="cross-reference" href="#fig:service-dependency-macros">64</a> shows an example. Having recognized and abstracted away details of this pattern, we may take further steps, such as to rearrange the implementation of the <tt>await-services</tt> macro to express interest in <em>all</em> dependencies at once rather than in one at a time.</p><p id="x_8_6_0_0_11">The notion of service dependency can be readily extended to start services only when some demand for them exists. A service <em>factory</em> actor might observe <tt>(observe (service-ready <span class="lyx-mathjax mathjax-inline">$x$</span>))</tt>, arranging for the program implementing service <span class="lyx-mathjax mathjax-inline">$x$</span> to be run when such an interest appears in the dataspace. The protocol may also be enriched to allow a service to declare that it must run <em>before</em> some other service is started, rather than after. The combination of such forward and reverse dependencies, along with <em>milestones</em> such as “network configuration complete” masquerading as abstract services, yields a self-configuring system startup facility rivaling those available in many modern Unix distributions.</p><p id="x_8_6_0_0_12">The notion of service startup applies not only at the level of a whole operating system, but also within specific applications in an arbitrarily fine-grained way. For example, a web server that depends on a database might wish to only start accepting TCP connections once (a) the database server itself is available, (b) a connection to the database server is established, and (c) the schema and contents of the database have been initialized.</p>
<h4 id="x_8_7_0_0_1"><a name="toc_8.7"></a><span class="counter section"><span>8.7</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:RPC"></a><a name="sec:RPC"></a>Transactions: RPC, Streams, Memoization</span></h4><p id="x_8_7_0_0_2">As we have discussed as far back as chapter <a class="cross-reference" href="#CHAP:PHILOSOPHY-AND-OVERVIEW">2</a>, certain assertions serve as <em>framing knowledge</em> in a protocol, identifying and delimiting sub-conversations within an overarching interaction. Often, framing knowledge can be seen as statement of a goal; subsequent actions and interactions are then steps taken toward satisfaction of the goal. Establishment of a conversational frame is similar to establishment of a transaction boundary, and indeed various forms of transaction manifest themselves in <span class="small-caps">Syndicate</span> as conversational frames.</p><p id="x_8_7_0_0_3">The simplest possible transaction is a one-way message. The message entails establishment and tear-down of a transactional context that lasts just long enough to process the message. Beyond this point, a vast design space opens up. Here we consider a few points in this space.</p>
<h6 class="unnumbered" id="x_8_7_0_0_4"><a name="toc_8.7"></a><span class="heading-text paragraph">RPC.</span></h6><p id="x_8_7_0_0_5">The simplest form of transaction involving feedback from recipient to sender is <em>request/response</em>. Such transactions allow us to encode <em>remote procedure call</em> (RPC); that is, <em>function calls</em> across <span class="small-caps">Syndicate</span> dataspaces.</p>
<div class="theorem-like numbered example named" id="x_8_7_0_0_10">
<p id="x_8_7_0_0_6"><span class="counter numbered example"><span>8.30</span></span><span class="lyx-argument">RPC, message/message<span class="plain-layout-boundary"></span></span>At its simplest, a request message establishes context for the call at the same time as making a specific request, and a corresponding response message signals both completion of the request and discarding of the request's context.</p>
<p id="x_8_7_0_0_8">
<pre class="listing" id="x_8_7_0_0_7"><code>(message-struct request (body))
(message-struct reply (body))
(spawn (on (message (request `(square ,$x)))
(send! `(square-of ,x is ,(* x x)))))
</code></pre></p>
<p id="x_8_7_0_0_9">Here, we know that computation of a square is <em>idempotent</em>, and so we may omit distinct request-identifiers. If the invoked action were non-idempotent, clients would have to allocate dataspace-unique request IDs, using them to tell otherwise-identical-seeming instances of the protocol apart. Similarly, here we see that the argument <span class="lyx-mathjax mathjax-inline">$x$</span> can be used to correlate a response with a request, so that answers to simultaneous requests for <tt>`(square 3)</tt> and <tt>`(square 4)</tt> do not get mixed up. In cases where simple echoing of arguments does not suffice to correlate a response with its request, explicit correlation information should be supplied in a request and included in the response.</p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_7_0_0_14">
<p id="x_8_7_0_0_11"><span class="counter numbered example"><span>8.31</span></span><a class="label-anchor" href="#example:rpc:interest-assertion"></a><a name="example:rpc:interest-assertion"></a><span class="lyx-argument">RPC, interest/assertion<span class="plain-layout-boundary"></span></span>We may take a more relational approach to RPC by observing that a (pure) function is a relation between its argument and result. Interest in a subset of the elements of the relation can serve to establish the necessary context; assertion of the specific element produced by the function supplies the response; and retraction of interest signals the end of the conversation. In cases where requests are non-idempotent, and thus must be distinguished by some request ID, we may use a reply <em>message</em> instead of an assertion, since there is no risk of confusion in this case. Use of a reply message with idempotent request assertions would be an error, however: the dataspace model collapses multiple simultaneous assertions of the same request, risking a situation where a client is not supplied with an answer to its request.</p>
<p id="x_8_7_0_0_13">
<pre class="listing" id="x_8_7_0_0_12"><code>(assertion-struct function (argument result))
(spawn (during (observe (function `(square ,$x) _))
(assert (function `(square ,x) (* x x)))))
</code></pre></p><span class="halmos"></span></div>
<div class="theorem-like numbered example named" id="x_8_7_0_0_26">
<p id="x_8_7_0_0_15"><span class="counter numbered example"><span>8.32</span></span><span class="lyx-argument">RPC, interest/assertion/error<span class="plain-layout-boundary"></span></span>Error handling may be incorporated into our RPC protocols via <em>sum types</em>, as is traditional for pure functional languages. Alternatively, we may introduce a <em>nested conversational context</em> within which it is known to the <em>requestor</em> that processing of the request is ongoing. Closure of that nested context prior to assertion of a reply indicates abnormal termination. We may press protocol <a class="cross-reference" href="#protocol:advertisement">8.25</a> into service as a convenient expression of this nested context, asserting our intention to <em>eventually</em> answer the request.</p>
<p id="x_8_7_0_0_17">
<pre class="listing" id="x_8_7_0_0_16"><code>(spawn #:name 'division-server
(during/spawn (observe (function `(divide ,$n ,$d) _))
(assert (advertise (function `(divide ,n ,d) _)))
(on-start (flush!)
(react (assert (function `(divide ,n ,d) (/ n d)))))))
</code></pre></p>
<div class="footnote" id="fn_8_96"><span class="counter footnote-counter"><span>96</span></span>An interesting generalization of this idea is to replace a simple <tt>advertise</tt> with a protocol for <em>progress reporting</em>; the service can then keep the client informed as a perhaps-complex request proceeds toward completion. This makes an RPC-like request into a kind of <em>stream</em>, discussed below.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_8_97"><span class="counter footnote-counter"><span>97</span></span>An alternative to this use of <tt>flush!</tt> would be to use the <em>responsibility transfer</em> mechanism of the initial assertion set that is included with each actor-spawn action of the dataspace model, as discussed at the end of section <a class="cross-reference" href="#sec:Formal-DS-semantics">4.2</a>. The <tt>division-server</tt>'s <tt>during/spawn</tt> would arrange for each spawned actor to be created <em>already asserting</em> its <tt>advertise</tt> record. That way, there would be zero risk of either a crash before the assertion of the <tt>advertise</tt> record, or accidentally beginning computation of the result before the <tt>advertise</tt> had safely made its way to the dataspace.<span class="plain-layout-boundary"></span></div>
<p id="x_8_7_0_0_18">On line 3, the service asserts its intention to reply.<label class="footnote-number" for="fn_8_96">96</label> The <tt>flush!</tt> call of line 4 is necessary to ensure that the patch SCN action resulting from line 3 reaches the dataspace safely before computation of the function begins.<label class="footnote-number" for="fn_8_97">97</label> Line 5 computes and publishes the answer. Once interest is retracted, the semantics of <tt>during/spawn</tt> ensures that the actor created for the specific request is terminated along with all its state and resources.</p>
<p id="x_8_7_0_0_19">Naturally, a request entailing a division by zero causes a Racket exception to be signaled on line 5, terminating the request's actor (but not the service overall). We may take advantage of the careful separation of the advertisement of line 3 from the response of line 5 in order to make a <em>positive statement</em> of failure; a positive statement of an inference drawn from a <em>lack</em> of information:</p>
<p id="x_8_7_0_0_21">
<pre class="listing" id="x_8_7_0_0_20"><code>(assertion-struct failed (argument))
(spawn #:name 'failure-detector
(during/spawn (observe (function $req _))
(on (retracted (advertise (function req _)))
(react (assert (failed req))))))
</code></pre></p>
<p id="x_8_7_0_0_22">Every time a not-previously-asserted declaration of interest in a function result appears, an actor is spawned to monitor the situation (line 3). The <tt>during/spawn</tt> terminates the monitor as soon as interest in the function result is retracted. If a result—assertion of a <tt>function</tt> record—is transmitted, and the protocol is followed, the service maintains its assertion of <tt>advertise</tt>ment until after our monitoring actor has terminated. However, if the service crashes before asserting its result, its <tt>advertise</tt> assertion is withdrawn, triggering lines 4 and 5 to report to interested parties that the overall request failed. Clients, then, pay attention to <tt>failed</tt> assertions, rather than observing retraction of the <tt>advertise</tt>ment directly:</p>
<p id="x_8_7_0_0_24">
<pre class="listing" id="x_8_7_0_0_23"><code>(spawn (define req `(divide 1 0))
(stop-when (asserted (failed req))
(printf "No answer was supplied!\n"))
(stop-when (asserted (function req $answer))
(printf "The answer is: ~a\n" answer)))
</code></pre></p>
<p id="x_8_7_0_0_25">The endpoint of line 4 demands the answer to our division problem, triggering a computation in the division server. The endpoint of lines 23 causes the client to respond to failure<tt> assertions</tt>, should any appear. Alternatively, a normal answer from the server triggers the endpoint of lines 45.</p><span class="halmos"></span></div><p id="x_8_7_0_0_27">Recall the “eager” answer-production of the forward-chaining strategy of section <a class="cross-reference" href="#subsec:Forward-chaining">8.5.1</a> and the “lazy” nature of the backward-chaining strategy of section <a class="cross-reference" href="#subsec:Backward-chaining">8.5.2</a>. Each example of RPC we have explored here combines <em>procedural knowledge</em> (section <a class="cross-reference" href="#subsec:Procedural-knowledge">8.5.4</a>) with a <em>lazy</em> answer-production strategy. However, the decoupling of control from information flow that the dataspace model offers allows us to employ an <em>eager</em> strategy on a case-by-case basis, without altering any client code or protocol details. We may go further, offering <em>memoization</em> of computed results without altering callers.</p>
<div class="theorem-like numbered example named" id="x_8_7_0_0_32">
<p id="x_8_7_0_0_28"><span class="counter numbered example"><span>8.33</span></span><span class="lyx-argument">RPC, automatic memoization<span class="plain-layout-boundary"></span></span>Here, a cache actor notices interest in answers to a request <tt>req</tt>, and “asks the same question” itself. This strategy exploits the way the dataspace model collapses identical assertions to <em>maintain</em> interest in answers to <tt>req</tt> for a certain length of time, presumably exceeding the duration of interest expressed by the original client.</p>
<p id="x_8_7_0_0_30">
<pre class="listing" id="x_8_7_0_0_29"><code>(spawn (on (asserted (observe (function $req _)))
(react (assert (observe (function req _)))
(stop-when (retracted (advertise (function req _))))
(stop-when-timeout 750))))
</code></pre></p>
<p id="x_8_7_0_0_31">Because interest in a given answer is maintained without interruption, the service only performs its computation once.</p><span class="halmos"></span></div><p id="x_8_7_0_0_33">An alternative implementation of memoization might listen in on the answer from the service and take on responsibility for asserting that answer on its own. Then it may optionally coordinate with the server to relieve it of the burden of redundantly asserting the answer for the life time of the cache entry. By coordinating among different entries <em>within</em> a memoizing cache actor, making the life time of a cache entry depend on the life time of previously-demanded entries, we may achieve the effect of dynamic programming.</p><p id="x_8_7_0_0_34">Finally, in a situation where one function-like service depends on another, we may wish to short-circuit the analogue of <em>tail calls</em>. Where request/reply correlation is done using the structure of the request, this can be difficult to achieve, but where explicit, arbitrary correlation identifiers exist distinct from request descriptions, an intermediary can reuse the identity of the request that triggered it, effectively <em>forwarding</em> the request to another service.</p>
<h6 class="unnumbered" id="x_8_7_0_0_35"><a name="toc_8.7"></a><span class="heading-text paragraph">Streams.</span></h6><p id="x_8_7_0_0_36">Moving beyond a single request and single response toward more long-lived transactions takes us toward <em>streams</em>. A stream is a conversational frame involving multiple interactions in either or both directions. Examples include the protocols <span class="small-caps">Syndicate/rkt</span> exposes as part of its TCP/IP socket, HTTP server, WebSocket, and IRC client drivers. We will examine these in more detail as part of our evaluation in chapter <a class="cross-reference" href="#CHAP:PATTERNS">9</a>, focusing here on the example of the IRC driver protocol as it appears to clients.</p><p id="x_8_7_0_0_51">
<div class="theorem-like protocol-description named" id="x_8_7_0_0_50"><span class="counter protocol-description"><span>8.34</span></span><span class="lyx-argument">IRC client connection<span class="plain-layout-boundary"></span></span><span class="small-caps">Syndicate/rkt</span> may interact across the network via the IRC protocol <span class="citation citep">(<a class="citation" id="cite-194" href="#bib-rfc1459">Oikarinen and Reed 1993</a>; <a class="citation" id="cite-195" href="#bib-rfc2812">Kalt 2000</a>)</span>, exposed by <span class="small-caps">Syndicate/rkt</span>'s IRC client driver.<span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_7_0_0_37"><span class="lyx-argument">Module to activate<span class="plain-layout-boundary"></span></span><tt>syndicate/drivers/irc</tt><span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_7_0_0_42"><span class="lyx-argument">Schema<span class="plain-layout-boundary"></span></span>The IRC protocol allows participants to connect to a server and then to join zero or more separate named chat rooms, each known as a <em>channel</em>. Each connection is identified at the server by a server-unique nickname. A connection to an IRC server is represented by an <tt>irc-connection</tt> record,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_7_0_0_38"><tt>(assertion-struct irc-connection (host port nick))</tt></p><span class="plain-layout-boundary"></span>
<div class="footnote" id="fn_8_98"><span class="counter footnote-counter"><span>98</span></span>The library is a drastically simplified prototype, not even supporting nick changes during a connection.<span class="plain-layout-boundary"></span></div>where <tt>host</tt> and <tt>port</tt> identify the server to connect to, and <tt>nick</tt> the nickname to associate with the connection.<label class="footnote-number" for="fn_8_98">98</label> The nicknames of connected users in a given channel are conveyed via <tt>irc-presence</tt> assertions,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_7_0_0_39"><tt>(assertion-struct irc-presence (conn nick channel))</tt></p><span class="plain-layout-boundary"></span>where <tt>conn</tt> is an <tt>irc-connection</tt> record, and <tt>nick</tt> and <tt>channel</tt> both strings. Messages from a given channel on the server appear as <tt>irc-inbound</tt> messages,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_7_0_0_40"><tt>(message-struct irc-inbound (conn nick target body))</tt></p><span class="plain-layout-boundary"></span>where <tt>conn</tt> is an <tt>irc-connection</tt> record, <tt>body</tt> is the message text, and <tt>nick</tt> and <tt>target</tt> identify the speaker and the channel, respectively. Messages traveling in the other direction, from the program to a given server channel, appear as <tt>irc-outbound</tt> messages,<span class="plain-layout-boundary"></span>
<p class="align-center" id="x_8_7_0_0_41"><tt>(message-struct irc-outbound (conn target body))</tt></p><span class="plain-layout-boundary"></span>with <tt>conn</tt> having its usual meaning, <tt>body</tt> being the message text, and <tt>target</tt> identifying the channel to which the IRC message should be directed.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_7_0_0_43"><span class="lyx-argument">Roles<span class="plain-layout-boundary"></span></span>The unique <em>ConnectionFactory</em> creates a <em>Connection</em> in response to user requests. In turn, each Connection interacts with a <em>User</em>.<span class="plain-layout-boundary"></span></div><span class="plain-layout-boundary"></span>
<div class="protocol-section" id="x_8_7_0_0_49"><span class="lyx-argument">Conversations<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span>
<ul id="x_8_7_0_0_48"><li id="x_8_7_0_0_44"><em>Connecting</em> (User/ConnectionFactory). The User asserts an <tt>irc-connection</tt> record into the dataspace; the ConnectionFactory reacts to its appearance by creating a Connection. Alternatively, the User may simply assert interest in <tt>irc-inbound</tt> messages: the ConnectionFactory notices this, and asserts the <tt>irc-connection</tt> record carried in the <tt>irc-inbound</tt> subscription, thereby triggering the Connecting conversation automatically.</li><li id="x_8_7_0_0_45"><em>Joining</em> (User/Connection). The User asserts interest in <tt>irc-inbound</tt> messages for a specific, previously established connection and a specific channel name. In response, the Connection sends appropriate <tt>JOIN</tt> messages to the remote server. The Connection also commits to maintaining a local record of channel membership in terms of <tt>irc-presence</tt> assertions as the IRC server sends an initial bulk list of fellow channel members and subsequent incremental updates to this list. As a consequence, the User may use the <tt>irc-presence</tt> record indicating its <em>own</em> presence in the channel as an indication that the channel join operation is complete. When interest in <tt>irc-inbound</tt> messages is retracted, the Connection sends appropriate <tt>PART</tt> messages and retracts the channel-specific <tt>irc-presence</tt> assertions it has been maintaining.</li><li id="x_8_7_0_0_46"><em>Speaking</em> (User/Connection). The User sends <tt>irc-outbound</tt> messages, which the Connection relays on to the IRC server.</li><li id="x_8_7_0_0_47"><em>Listening</em> (User/Connection). Within the context of a joined channel, utterances from channel members are delivered by the Connection as <tt>irc-inbound</tt> messages to all listening Users.</li></ul></div><span class="plain-layout-boundary"></span></div></p>
<div class="theorem-like numbered example named" id="x_8_7_0_0_53">
<p id="x_8_7_0_0_52"><span class="counter numbered example"><span>8.35</span></span><span class="lyx-argument">IRC bot<span class="plain-layout-boundary"></span></span>Figure <a class="cross-reference" href="#fig:example:IRC-bot">65</a> shows a simple “bot” program which connects to the Freenode IRC network with nickname <tt>syndicatebot</tt>, joins channel <tt>##syndicatelang</tt>, and greets those in the channel as it joins. The driver notices the subscription of line 5, asserting <tt>C</tt>, the <tt>irc-connection</tt> record, in response. This triggers the actual creation of the connection. The endpoint of lines 58 reacts to incoming chat messages. The endpoint of lines 910 sends a greeting to the members of the channel once the connection has completed joining the channel. Finally, lines 1113 react to changes in channel membership, including the connection's own membership and the members present at the time of channel join, by printing messages.</p><span class="halmos"></span></div><p id="x_8_7_0_0_54">In this example, the conversational context of membership in a particular IRC channel delimits two <em>streams</em> of messages. One of the two is the stream of <tt>irc-inbound</tt> messages from channel members; the other is the stream of <tt>irc-outbound</tt> messages from the local User to peers in the channel. The two streams interact: each <tt>irc-outbound</tt> message is reflected as an <tt>irc-inbound</tt> message, meaning that a connection “hears its own speech”. Finally, these channel-specific streams are in fact <em>nested streams</em> (nested transactions) within the larger conversational context of the connection to the IRC server as a whole. Channel-specific sub-conversations come and go within a connection's context, interleaving arbitrarily.</p>
<figure id="x_8_7_0_0_56"><a name="fig:example:IRC-bot"></a>
<pre class="listing" id="x_8_7_0_0_55"><code>(define NICK "syndicatebot")
(define CHAN "##syndicatelang")
(define C (irc-connection "irc.freenode.net" 6667 NICK))
(spawn #:name 'irc-connection-example
(on (message (irc-inbound C $who CHAN $body))
(printf "~a says: ~a\n" who body)
(when (not (equal? who NICK))
(send! (irc-outbound C CHAN (format "Hey, ~a said '~a'" who body)))))
(on (asserted (irc-presence C NICK CHAN))
(send! (irc-outbound C CHAN "Hello, everybody!")))
(during (irc-presence C $who CHAN)
(on-start (printf "~a joins ~a\n" who CHAN))
(on-stop (printf "~a leaves ~a\n" who CHAN))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>65</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:example:IRC-bot"></a>IRC bot<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h6 class="unnumbered" id="x_8_7_0_0_57"><a name="toc_8.7"></a><span class="heading-text paragraph">Acknowledgement and flow control.</span></h6><p id="x_8_7_0_0_58">Within a single stream, it may be important to manage the sizes of various buffers. Assertions describing the amount of free available buffer space at a recipient act as <em>windowed flow control</em>. Assertions describing successfully-received messages act as <em>acknowledgements</em>. The former allow management of receive buffer space; the latter, management of send (retransmission) buffer space. Acknowledgements effectively “garbage-collect” slots in a sender's retransmission buffer. These ideas can be used to model TCP/IP-like sliding-window “reliable-delivery” transport protocols.</p><p id="x_8_7_0_0_62">
<figure class="marginfigure" id="x_8_7_0_0_61"><a name="fig:flow-control-and-ack-state"></a>
<p class="align-center" id="x_8_7_0_0_60">
<div class="lyx-mathjax mathjax-display" id="x_8_7_0_0_59">\[
\begin{array}{c}
\text{Waiting}\\
\llap{-\mathtt{REQ}/-\mathtt{X\quad}}\upharpoonleft\downharpoonright\rlap{\quad+\mathtt{REQ}/+\mathtt{X}}\\
\text{Transmitting}\\
\;\downarrow\rlap{\quad+\mathtt{ACK}/-\mathtt{X}}\\
\text{Complete}
\end{array}
\]
</div></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>66</span></span><span class="figcaption-text"><span class="lyx-argument">Flow control and acknowledgement<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:flow-control-and-ack-state"></a>Flow control and acknowledgement<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure></p><p id="x_8_7_0_0_63">Consider the case of a single piece of information, to be transmitted from a sender to a receiver. In order to make effective use of bandwidth or other scarce resources, the sender might want to wait until the receiver is ready to listen before producing a message for its consumption. Likewise, if the medium or some relay in the communication path is unreliable, or if the receiver itself might fail at any time, the sender will keep trying to transfer until receipt (and/or processing) is confirmed.</p><p id="x_8_7_0_0_64">Figure <a class="cross-reference" href="#fig:flow-control-and-ack-state">66</a> depicts the lifecycle of the process from the sender's perspective. Starting in “Waiting” state, the sender learns that the receiver has <tt>REQ</tt>uested the item, transitioning to “Transmitting” state and asserting the item <tt>X</tt> itself. If the receiver crashes or changes its mind, the <tt>REQ</tt>uest is withdrawn, and the sender transitions back to “Waiting”, retracting <tt>X</tt>. If the receiver <tt>ACK</tt>nowledges the item, however, the sender transitions to state “Complete”, retracting <tt>X</tt> and continuing about its business. By using assertions instead of messages, the <span class="small-caps">Syndicate</span> programmer has delegated to the dataspace the messy business of retries, timeouts and so forth, and can concentrate on the epistemic properties of the logic of the transfer itself.</p>
<div class="theorem-like numbered example named" id="x_8_7_0_0_69">
<p id="x_8_7_0_0_65"><span class="counter numbered example"><span>8.36</span></span><span class="lyx-argument">Acknowledgement and flow control<span class="plain-layout-boundary"></span></span>In simple cases, the fact of an interest in a given assertion can be an implicature that the time is right to produce and to communicate it. As we saw above in cases such as example <a class="cross-reference" href="#example:rpc:interest-assertion">8.31</a>, when no explicit, positive indication of receipt is required, <em>retraction</em> of interest can serve as acknowledgement of receipt. However, this conflates an indication that the receiver has reneged on its previously-declared interest with an indication of successful delivery. When acknowledgement is important, we must make it explicit and separate from assertions of readiness to receive.</p>
<p id="x_8_7_0_0_67">
<pre class="listing" id="x_8_7_0_0_66"><code>(assertion-struct envelope (payload))
(assertion-struct acknowledgement (payload))
... (react/suspend (k)
(during (observe (envelope _))
(define item (compute-item))
(assert (envelope item))
(on (asserted (acknowledgement item)) (k)))) ...
</code></pre></p>
<p id="x_8_7_0_0_68">On line 3, we enter the “Waiting” state of figure <a class="cross-reference" href="#fig:flow-control-and-ack-state">66</a>. Interest in our <tt>envelope</tt> assertion (line 4) constitutes a <tt>REQ</tt> signal from a recipient; a subfacet is created representing occupancy of the “Transmitting” state. The subfacet computes the item to transfer (line 5), asserts it (line 6) and awaits explicit, positive acknowledgement of receipt (line 7). Once acknowledgement is received, the call to <tt>k</tt> serves to terminate the facet opened on line 3, finishing at “Complete” state and releasing the continuation of the <tt>react/suspend</tt> form. Otherwise, if the <tt>(observe (envelope _))</tt> assertion is retracted before acknowledgement is received, the corresponding subfacet is destroyed and we return to “Waiting” state.</p><span class="halmos"></span></div>
<h4 id="x_8_8_0_0_1"><a name="toc_8.8"></a><span class="counter section"><span>8.8</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Dataflow-and-reactive"></a><a name="sec:Dataflow-and-reactive"></a>Dataflow and reactive programming</span></h4><p id="x_8_8_0_0_2">Manna and Pnueli define a <em>reactive</em> program very generally as follows:</p>
<blockquote id="x_8_8_0_0_4">
<p id="x_8_8_0_0_3">A reactive program is a program whose role is to maintain an ongoing interaction with its environment rather than to compute some final value on termination. <span class="citation citep">(<a class="citation" id="cite-196" href="#bib-Manna1991">Manna and Pnueli 1991</a>)</span></p></blockquote><p id="x_8_8_0_0_5">This contrasts with the slightly more restrictive definition of Bainomugisha et al., who define reactive programming as “a programming paradigm that is built around the notion of continuous time-varying values and propagation of change” <span class="citation citep">(<a class="citation" id="cite-197" href="#bib-Bainomugisha2013">Bainomugisha et al. 2013</a>)</span> that is in turn based on synchronous <em>dataflow</em> <span class="citation citep">(<a class="citation" id="cite-198" href="#bib-Lee1987">Lee and Messerschmitt 1987</a>)</span>. The dataspace model is clearly reactive in sense of Manna and Pnueli, and while it does not quite satisfy the “distinguishing features” of reactive languages given by Bainomugisha et al., it does enjoy similar strengths and suffer similar weaknesses to many of the reactive languages they describe.</p>
<figure id="x_8_8_0_0_7"><a name="fig:Synchrony-between-two-temp-scales"></a>
<pre class="listing" id="x_8_8_0_0_6"><code>(assertion-struct temperature (unit value))
(message-struct set-temperature (unit value))
(spawn #:name 'track-celsius
(field [temp 0])
(assert (temperature 'C (temp)))
(on (message (set-temperature 'C $new-temp))
(temp new-temp))
(on (asserted (temperature 'F $other-temp))
(temp (* (- other-temp 32) 5/9))))
(spawn #:name 'track-fahrenheit
(field [temp 32])
(assert (temperature 'F (temp)))
(on (message (set-temperature 'F $new-temp))
(temp new-temp))
(on (asserted (temperature 'C $other-temp))
(temp (+ (* other-temp 9/5) 32))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>67</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Synchrony-between-two-temp-scales"></a>Maintaining synchrony between two temperature scales<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_8_99"><span class="counter footnote-counter"><span>99</span></span>The specific presentation of this section is inspired by that of <span class="citation citet"><a class="citation" id="cite-201" href="#bib-Ingalls1988"><span>Ingalls et al.<span class="parens"> (</span>1988<span class="parens">)</span></span></a></span>.<span class="plain-layout-boundary"></span></div><p id="x_8_8_0_0_8">Maintenance of a connection between a representation of a temperature in degrees Fahrenheit and in degrees Celsius is a classic challenge problem for dataflow languages <span class="citation citep">(<a class="citation" id="cite-199" href="#bib-Ingalls1988">Ingalls et al. 1988</a>; <a class="citation" id="cite-200" href="#bib-Bainomugisha2013">Bainomugisha et al. 2013</a>)</span>. The problem is to internally maintain a temperature value, presenting it to the user in both temperature scales and allowing the user to modify the value in terms of either temperature scale.<label class="footnote-number" for="fn_8_99">99</label> Figure <a class="cross-reference" href="#fig:Synchrony-between-two-temp-scales">67</a> shows a <span class="small-caps">Syndicate/rkt</span> implementation of the problem. An actor exists for each of the two temperature scales, maintaining an appropriate assertion and responding to <tt>set-temperature</tt> messages by performing necessary conversions before updating internal state. Temperature displays (not shown) may monitor the <tt>temperature</tt> assertions maintained by each actor, and user interface controls allowing temperature update should issue <tt>set-temperature</tt> messages with appropriate <tt>unit</tt> and <tt>value</tt> fields.</p><p id="x_8_8_0_0_9">Each of the two actors shown acts as a <em>unidirectional</em> propagator of changes. The difference between <tt>temperature</tt> assertions and <tt>set-temperature</tt> command messages suffices to rule out confusion: a <tt>set-temperature</tt> message is always the cause of a change to the temperature, while an update to a <tt>temperature</tt> assertion is never the cause of a change; rather, it simply reflects some previous change. As <span class="citation citet"><a class="citation" id="cite-202" href="#bib-Radul2009"><span>Radul<span class="parens"> (</span>2009<span class="parens">)</span></span></a></span> observes, “multidirectional constraints are very easy to express in terms of unidirectional propagators”, and indeed the combination of the two actors ensures a bidirectional connection between the Fahrenheit and Celsius <tt>temperature</tt> assertions. However, we must ask whether we have truly entered into the spirit of the problem: by allowing the Celsius actor to interpret events expressed in Fahrenheit, and vice versa, our solution lacks the modularity and extensibility of the multidirectional solutions available in true dataflow languages.</p>
<figure id="x_8_8_0_0_11"><a name="fig:Modular-synchronization"></a>
<pre class="listing" id="x_8_8_0_0_10"><code>(spawn #:name 'track-celsius
(field [temp 0])
(assert (temperature 'C (temp)))
(on (message (set-temperature 'C $new-temp)) (temp new-temp)))
(spawn #:name 'track-fahrenheit
(field [temp 32])
(assert (temperature 'F (temp)))
(on (message (set-temperature 'F $new-temp)) (temp new-temp)))
(spawn #:name 'convert-C-to-F
(on (asserted (temperature 'C $other-temp))
(send! (set-temperature 'F (+ (* other-temp 9/5) 32)))))
(spawn #:name 'convert-F-to-C
(on (asserted (temperature 'F $other-temp))
(send! (set-temperature 'C (* (- other-temp 32) 5/9)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>68</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Modular-synchronization"></a>Modular synchronization between two temperature scales<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_8_8_0_0_12"> Figure <a class="cross-reference" href="#fig:Modular-synchronization">68</a> addresses the problem, separating the equations relating the Celsius and Fahrenheit representations from the actors maintaining the representations. Each time some <em>distinct</em> assertion of <tt>temperature</tt> appears, a <tt>set-temperature</tt> message is sent. Even though it seems like this may lead to unbounded chains of updates, activity will eventually quiesce because the two equations are inverses. After a time, the interpretation of a <tt>set-temperature</tt> message will lead to no observable change in a corresponding <tt>temperature</tt> assertion.</p><p id="x_8_8_0_0_13">While our solutions thus far enjoy multidirectionality, they exhibit observable <em>glitching</em> <span class="citation citep">(<a class="citation" id="cite-203" href="#bib-Bainomugisha2013">Bainomugisha et al. 2013</a>)</span>. For example, just after a <tt>set-temperature</tt> message expressed in degrees Celsius has been interpreted, a moment in the stream of events exists when the corresponding Celsius <tt>temperature</tt> assertion has been updated but the Fahrenheit assertion has not yet incorporated the change. In general, any computation that depends on events traveling through the dataspace to peers (and perhaps back again) involves unavoidable latency, which may manifest as a form of glitching in some protocols. One approach to resolution of the problem is to bring the mutually-dependent stateful entities into the same location; that is, publish both Celsius and Fahrenheit from a single actor. If we do so, we may use any number of off-the-shelf techniques for avoiding glitching, including reactive DSLs such as FrTime <span class="citation citep">(<a class="citation" id="cite-204" href="#bib-Cooper2006">Cooper and Krishnamurthi 2006</a>)</span>. However, this approach shuffles the problem under the rug, as the domain-specific assertion protocol no longer embodies a dataflow system in any meaningful sense. An alternative approach is to extend the assertions in our protocol with <em>provenance</em> information (a.k.a “version” information or tracking of causality) to form a more complete picture of transient states in a system's evolution <span class="citation citep">(<a class="citation" id="cite-205" href="#bib-Radul2009">Radul 2009</a>; <a class="citation" id="cite-206" href="#bib-Shapiro2011">Shapiro et al. 2011</a>)</span>. That way, while the assertions themselves are able to (and do) represent not-yet-consistent intermediate states, <em>under interpretation</em> the incomplete states are ignored. Provenance information allows us to reason <em>epistemically</em> about flows of information in our protocols.</p></p>
<h2 id="x_8_0_0_0_1"><a name="toc_IV"></a><span class="counter part"><span>IV</span></span><span class="heading-text part">Reflection</span></h2>
<h3 class="unnumbered" id="x_8_0_0_0_2"><a name="toc_8"></a><span class="heading-text chapter">Overview</span></h3><p id="x_8_0_0_0_3">Every design demands evaluation. For a language design, this takes the form of the investigation of properties such as well-definedness, usefulness, and performance. While the formal models of <span class="small-caps">Syndicate</span> include basic theorems that characterize evaluation in <span class="small-caps">Syndicate/λ</span>, this part presents an evaluation of the practical aspects of the design.</p><p id="x_8_0_0_0_4">To begin, chapter <a class="cross-reference" href="#CHAP:PATTERNS">9</a> examines the usefulness of <span class="small-caps">Syndicate</span>, presenting a qualitative evaluation of the design in terms of its effect on <em>patterns</em> in program texts.</p><p id="x_8_0_0_0_5">Performance is the focus of chapter <a class="cross-reference" href="#CHAP:PERFORMANCE">10</a>, which develops a <span class="small-caps">Syndicate</span>-specific performance model. Programmers can rely on this model in the design and evaluation of their programs and in the understanding of the programs of others.</p><p id="x_8_0_0_0_6">Chapter <a class="cross-reference" href="#CHAP:DISCUSSION">11</a> places <span class="small-caps">Syndicate</span> within the concurrency design landscape introduced in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>, analyzing it in terms of the criteria developed in section <a class="cross-reference" href="#sec:A-concurrency-design-landscape">3.1</a>.</p><p id="x_8_0_0_0_7">Finally, chapter <a class="cross-reference" href="#CHAP:CONCLUSION">12</a> reflects on the thesis of this dissertation and outlines a handful of promising directions for future work.</p><p id="x_9_8_0_0_27">
<h3 id="x_9_0_0_0_1"><a name="toc_9"></a><span class="counter chapter"><span>9</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:PATTERNS"></a><a name="CHAP:PATTERNS"></a>Evaluation: Patterns</span></h3>
<blockquote id="x_9_0_0_0_4">
<p id="x_9_0_0_0_2">A programming language is low level when its programs require attention to the irrelevant.</p>
<p class="align-right" id="x_9_0_0_0_3">—Alan J. Perlis <span class="citation citeyearpar"><a class="citation" id="cite-207" href="#bib-Perlis1982">1982</a></span></p></blockquote><p id="x_9_0_0_0_5">The evaluation of programming models and language designs is a thorny topic. Where a design has been realized into a full language, and where mature implementations of that language exist, we may examine quantitative attributes such as performance on a suite of benchmarks. Where many large programs written in a language exist, we may plausibly look into quantitative attributes such as error rates or programmer productivity. However, programming models are mathematical constructs, and novel language designs are abstract. Quantitative measures are inappropriate.</p><p id="x_9_0_0_0_6">We are left with the investigation of <em>qualitative</em> attributes of our models and designs. A key quality is the extent to which a model or design eliminates or simplifies<em> patterns</em> in program texts, because other attributes improve as a consequence. In evaluating <span class="small-caps">Syndicate</span> through the lens of design and programming patterns, I aim to show that the design is effective in concisely achieving the effects of several such patterns.</p>
<h4 id="x_9_1_0_0_1"><a name="toc_9.1"></a><span class="counter section"><span>9.1</span></span><span class="heading-text section">Patterns</span></h4><p id="x_9_1_0_0_2">I use the term “pattern” to cover two related concepts. The first is the idea of a <em>programming pattern</em> in the sense discussed by Felleisen in his work on expressiveness <span class="citation citep">(<a class="citation" id="cite-208" href="#bib-Felleisen1991">Felleisen 1991</a>)</span>, synonymous with an <em>encoding</em> of an otherwise-inexpressible concept. The second is the idea of a <em>design pattern</em> from the object-oriented programming literature <span class="citation citep">(<a class="citation" id="cite-209" href="#bib-Beck1987">Beck and Cunningham 1987</a>; <a class="citation" id="cite-210" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span>. That is, a “pattern” appears in a text not only when a specific design pattern is mentioned, but also in any situation in which an encoding is applied.</p><p id="x_9_1_0_0_3">An encoding is a precise, potentially-automatable program transformation for representing some linguistic feature that cannot be expressed directly. An example of an encoding is <em>store passing</em> in a functional language to achieve the effect of <em>mutable state</em>. The precision of an encoding makes it possible to develop tooling or language extensions to assist the programmer in working with it. Seen from another angle, however, this same precision makes working with an encoding by hand an exercise in “boilerplate” programming. For example, a program with a manual implementation of store passing has entirely routine and predictable placement and usage of the variable representing the store. Errors frequently arise in such programs. Approaches to automation such as macros, code generation, and monadic style help reduce this boilerplate and rule out errors, but cannot usually ensure complete adherence to the abstraction the encoding represents. For example, a monadic state library hides the explicit store from the program text, but unless a type system rich enough to enforce the necessary invariants is available, it remains possible for the programmer to misapply the library and throw into doubt the guarantees offered by the abstraction. In other words, encodings generally yield leaky abstractions.</p><p id="x_9_1_0_0_4">The notion of a design pattern originated in architecture <span class="citation citep">(<a class="citation" id="cite-211" href="#bib-Alexander1977">Alexander et al. 1977</a>)</span>, but has been successfully transplanted to object-oriented programming <span class="citation citep">(<a class="citation" id="cite-212" href="#bib-Beck1987">Beck and Cunningham 1987</a>)</span> and can also be applied to other programming paradigms such as asynchronous messaging <span class="citation citep">(<a class="citation" id="cite-213" href="#bib-Hohpe2004">Hohpe and Woolf 2004</a>; <a class="citation" id="cite-214" href="#bib-Hohpe2017">Hohpe 2017</a>)</span>. A design pattern, in an object-oriented context, “names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object-oriented design” <span class="citation citep">(<a class="citation" id="cite-215" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span>. Unlike an encoding, a design pattern is often not precise enough to be captured as either a library implementation or a language feature, but like an encoding, its manual expression often involves boilerplate code and the problems that go with it. The lack of precision often makes it difficult to provide tooling for working with design patterns <em>per se.</em></p>
<h4 id="x_9_2_0_0_1"><a name="toc_9.2"></a><span class="counter section"><span>9.2</span></span><span class="heading-text section">Eliminating and simplifying patterns</span></h4><p id="x_9_2_0_0_2">In order to see what it might mean for a pattern to be eliminated or simplified, we must first understand how patterns manifest in programs. Broadly speaking, a pattern is characterized by realization of a program organization <em>goal</em> in terms of some <em>mechanism</em>, which frequently involves boilerplate code. We see <em>recursive</em> use of patterns: implementation of the mechanism for achieving some goal entails organizational requirements of its own, which in turn demand satisfaction by some means. This can lead to towers of patterns. A pattern is eliminated by a programming model or language feature if it is provided directly or made unnecessary. A pattern can be simplified in two ways: in the case that its implementation depends on a tower of patterns, some supporting layer of that tower can be eliminated; or its implementation may be made more obvious by some part of the model or language feature.</p>
<div class="lyx-mathjax mathjax-definitions" id="x_9_2_0_0_3">\(\newcommand{\CSHARP}{\textrm{C}^{\sharp}}
\)</div><p id="x_9_2_0_0_4">For example, consider the task of maintaining a consistent graphical view on a list of items as items are added to and removed from the list. Our ultimate goal is the <em>synchronization of state</em> between the state of the on-screen view and the state of the underlying list. We might choose to use the <em>observer pattern</em> to accomplish our synchronization task by processing signals from the list as it changes. In turn, the observer pattern might be implemented using <em>callbacks</em>, which ultimately depend on <em>function calls</em>. In the early days of computing, “function call” was a design pattern. It has since been <em>eliminated</em> from most programming languages; this has <em>simplified</em> not only the implementation of callbacks, but also the observer pattern and our original goal of state synchronization. Adding language-level support for the observer pattern to the language, as languages like <span class="lyx-mathjax mathjax-inline">$\CSHARP$</span> have begun to explore, <em>eliminates</em> the need for callbacks in our pattern tower, <em>simplifying</em> the expression of our goal.</p><p id="x_9_2_0_0_5">As another example, the addition of support for the actor model to a language makes obsolete many uses of shared memory for communication among components. In this sense, the pattern of a <em>shared store</em> has been eliminated not by being provided directly, but by being made irrelevant by a shift in perspective to a new way of thinking.</p><p id="x_9_2_0_0_6">Turning our attention to design patterns in the sense of <span class="citation citeauthor"><a class="citation" id="cite-216" href="#bib-Gamma1994">Gamma et al.</a></span> <em>per se</em>, Norvig offers three “levels of implementation” for patterns: “informal”, “formal” and “invisible” <span class="citation citep">(<a class="citation" id="cite-217" href="#bib-Norvig1996">Norvig 1996</a>)</span>. An “informal” implementation of a pattern is expressed in program text as prose comments naming the pattern alongside a from-scratch, manual implementation of the required, stereotypical elements of the pattern at every site where the pattern is needed. A “formal” implementation allows reuse by providing the pattern as a kind of library or language extension, often in the form of a suite of macros, invoked for each separate use of the pattern. Finally, an “invisible” implementation is “so much a part of [the] language that you don't notice” its presence. This taxonomy gives us another approach to the topic of elimination and simplification of patterns: we may say that a pattern is <em>simplified</em> when it moves from “informal” to “formal”, and <em>eliminated</em> when it is made entirely “invisible”.</p>
<h4 id="x_9_3_0_0_1"><a name="toc_9.3"></a><span class="counter section"><span>9.3</span></span><span class="heading-text section">Simplification as key quality attribute</span></h4><p id="x_9_3_0_0_2">A language which eliminates or simplifies patterns in program texts, concisely and robustly achieving their effects without forcing the programmer to spell them out in full detail, is qualitatively better than one which does not. This claim is supported in several ways.</p><p id="x_9_3_0_0_3">First, Felleisen's <em>Conciseness Conjecture</em> <span class="citation citep">(<a class="citation" id="cite-218" href="#bib-Felleisen1991">Felleisen 1991</a>)</span> states that the more expressive a programming language is, the fewer programming patterns one tends to observe in texts written in that language. Felleisen argues that this is important because “pattern-oriented style is detrimental to the programming process,” observing that “the most disturbing consequence of programming patterns is that they are an obstacle to an understanding of programs for both human readers and program-processing programs.” For example, store-passing style requires a reader to analyze an entire program to learn whether the store has been properly propagated, accessed, and updated. Worse, certain encodings can have more than one interpretation, and determining which is intended requires analysis of fine detail of the text. Felleisen gives the example of continuation-passing style in a call-by-name language, which may encode either unusual control structure or a call-by-value protocol. Automated tooling suffers in a similar way: even with the precision offered by encodings, the global analyses required can be daunting. Tooling is also at a disadvantage compared to a human reader, since the human is able to read and understand comments conveying the <em>intent</em> behind a piece of code, while the tool is left to reason from the structure of the code alone. Turning to design patterns from encodings, we see that the problems of analysis are only made worse. The imprecision of design patterns forces humans and automated tools alike to make approximate guesses as to the intended design-pattern-level meaning of a particular piece of code.</p>
<div class="footnote" id="fn_9_100"><span class="counter footnote-counter"><span>100</span></span>The full principle ends with “... and secure”, later defined in terms that make it essentially a synonym of “abstract”. This sense of “secure” was originally introduced by <span class="citation citet"><a class="citation" id="cite-222" href="#bib-Hoare1974"><span>Hoare<span class="parens"> (</span>1974<span class="parens">)</span></span></a></span>.<span class="plain-layout-boundary"></span></div><p id="x_9_3_0_0_4">Second, Felleisen's ideas surrounding expressiveness are formal reflections of more informal ideas of the quality of a given programming language, alluded to in the Perlis quote at the top of this chapter and discussed by researchers such as Brinch Hansen <span class="citation citep">(<a class="citation" id="cite-219" href="#bib-BrinchHansen1993">Brinch Hansen 1993</a>)</span> and Hoare <span class="citation citep">(<a class="citation" id="cite-220" href="#bib-Hoare1974">Hoare 1974</a>)</span>. Hoare, in an early and influential paper on programming-language design, writes that a programming language should give a programmer “the greatest assistance in the most difficult aspects of his art, namely program design, documentation, and debugging,” and that “a necessary condition for the achievement of any of these objectives is the utmost simplicity in the design of the language” <span class="citation citep">(<a class="citation" id="cite-221" href="#bib-Hoare1974">Hoare 1974</a>)</span>. Brinch Hansen, who frequently collaborated with Hoare, suggested that the primary contribution that a language makes toward achievement of this simplicity is “an abstract readable notation that makes the parts and structure of programs obvious to a reader,” and goes on to say that “a programming language should be abstract”:<label class="footnote-number" for="fn_9_100">100</label></p>
<blockquote id="x_9_3_0_0_6">
<p id="x_9_3_0_0_5">An abstract programming language <em>suppresses machine detail</em> [...] [and] relies on <em>abstract concepts</em> [...] We shall also follow the crucial principle of language design suggested by Hoare: <em>The behavior of a program written in an abstract language should always be explainable in terms of the concepts of that language and should never require insight into the details of compilers and computers.</em> Otherwise, an abstract notation has no significant value in reducing complexity. <span class="citation citep">(<a class="citation" id="cite-223" href="#bib-BrinchHansen1993">Brinch Hansen 1993</a> <span class="citation-after">emphasis in original</span>)</span></p></blockquote><p id="x_9_3_0_0_7">An abstract language, then, achieves “simplicity” in that the programmer's ideas find direct expression in terms of the language itself, rather than indirect expression in terms of “machine detail”. This allows the programmer to reason in terms of the ideas rather than their representation. This is directly analogous to the relationship Felleisen remarks on between highly expressive languages and the programming patterns they suppress: a language able to avoid the need for programming patterns is abstract, i.e. good, in the sense of Brinch Hansen.</p><p id="x_9_3_0_0_8">Third, the fields of Software Architecture and Software Engineering evaluate systems in terms of <em>quality attributes</em> <span class="citation citep">(<a class="citation" id="cite-224" href="#bib-Bass1998">Bass, Clements and Kazman 1998</a>; <a class="citation" id="cite-225" href="#bib-Clements2001">Clements, Kazman and Klein 2001</a>)</span>, or so-called “-ilities”, named for the common suffix of attributes such as maintainability, stability, portability, and so forth. While these attributes are, strictly speaking, only applicable to software architectures and not to programming models, they are not without value in our setting. Many “-ilities” benefit immediately from program pattern elimination. For example, <em>modifiability</em> depends on the programmer being able to understand the scope of a particular change: a global encoding of some pattern interferes with this aim. Likewise, <em>understandability</em> of a program hinges on concision and expressiveness, on the programmer's ability to say what they mean. In general, improvements in concision and expressiveness, and reduction of pattern boilerplate, should lead to improvements in terms of several frequently-discussed “-ilities”. In the analysis to follow I illustrate specific points of connection between the <span class="small-caps">Syndicate</span> model and both general and scenario-specific “-ilities”.</p><p id="x_9_3_0_0_9">Finally, some small support for the claim of this section comes from previous analysis of design patterns in context of their implementation in various programming languages. Norvig reports on a study of the Design Patterns book of Gamma et al. in which 16 of the 23 patterns described in the book either find “qualitatively simpler implementation” or become entirely “invisible” when comparing implementations in Lisp or Dylan with implementations in C++ <span class="citation citep">(<a class="citation" id="cite-226" href="#bib-Norvig1996">Norvig 1996</a>)</span>.</p>
<h4 id="x_9_4_0_0_1"><a name="toc_9.4"></a><span class="counter section"><span>9.4</span></span><span class="heading-text section">Event broadcast, the observer pattern and state replication</span></h4>
<div class="footnote" id="fn_9_101"><span class="counter footnote-counter"><span>101</span></span>ANSI Smalltalk does not include the “dependents” protocol because “there is nothing defined by the standard that requires any kind of dependency mechanism.” <span class="citation citep">(<a class="citation" id="cite-227" href="#bib-ANSI:Smalltalk:1997">X3J20 Committee for NCITS 1997</a>)</span> However, inspection of a September 1986 source listing of Smalltalk-80 shows the dependents protocol in the form in which it survives in most Smalltalks today.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_2">The <em>observer</em> pattern is a mainstay of object-oriented programming languages. Originating with Smalltalk,<label class="footnote-number" for="fn_9_101">101</label> its purpose is given by <span class="citation citet"><a class="citation" id="cite-228" href="#bib-Gamma1994"><span>Gamma et al.<span class="parens"> (</span>1994<span class="parens">)</span></span></a></span> as “a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” Its intent is to communicate <em>state changes</em> from a <em>subject</em> to a set of <em>observers</em>.</p>
<div class="footnote" id="fn_9_102"><span class="counter footnote-counter"><span>102</span></span><span class="citation citet"><a class="citation" id="cite-229" href="#bib-Hohpe2017"><span>Hohpe<span class="parens"> (</span>2017<span class="parens">)</span></span></a></span> has dubbed the distributed systems analogue of the observer pattern “the Subscribe-Notify conversational pattern”. Surprisingly, “state replication” does not appear to be well-attested as a design pattern per se, either in the traditional OO or asynchronous messaging realms. The notion of event broadcasting appears in the asynchronous messaging literature simply as the role played by a message broker <span class="citation citep">(<a class="citation" id="cite-230" href="#bib-Hohpe2004">Hohpe and Woolf 2004</a>; <a class="citation" id="cite-231" href="#bib-Eugster2001">Eugster, Guerraoui and Damm 2001</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_5">
<figure class="marginfigure" id="x_9_4_0_0_4">
<div class="lyx-mathjax mathjax-display" id="x_9_4_0_0_3">$\begin{array}{c}
\text{Event Broadcast}\\
\downarrow\\
\text{Observer}\\
\downarrow\\
\text{State Replication}
\end{array}$
</div><span class="plain-layout-boundary"></span></figure>The observer pattern frequently finds expression as part of a tower of patterns. Supporting it we find an <em>event broadcast</em> facility of some kind, and instances of the observer pattern in turn are often used to implement <em>state replication</em>. The three patterns differ in intent. State replication is used to synchronize disparate views on some stateful entity, while the observer pattern focuses on the<em> </em>fact of a <em>change</em> in a stateful entity, and event broadcasting is merely the vehicle by which some signal is delivered to a group of recipients. Roughly speaking, state replication is the integral to the observer pattern's differential, and event broadcast is a generic message transport mechanism. In particular, a state replica starts with an initial snapshot, while there is no such requirement for an observer requesting change-notifications from a subject.<label class="footnote-number" for="fn_9_102">102</label></p><p id="x_9_4_0_0_6">Many popular programming languages include implementations of the observer pattern in their standard library, yielding what Norvig terms a “formal” implementation level. Others, however, make use of the pattern without a library implementation, yielding an “informal” implementation. One layer up our tower of patterns, state replication seldom is supported other than “informally”, and one layer down, event broadcasting is often somewhere between “invisible” and informal-but-idiomatic.</p><p id="x_9_4_0_0_7">A running example shows the patterns in action. The example involves a display of a set of names of users present in an online chat room. The display is to update itself as users arrive or depart the room, starting with the list of users present at the moment the display is initialized. The underlying set of users is the subject, and the display is an observer. The example embodies <em>state replication</em> in that the view, as it is created, interrogates the subject for its current members, and uses observer-pattern notifications as indications that it should incorporate some change that has just taken place.</p>
<h6 class="unnumbered" id="x_9_4_0_0_8"><a name="toc_9.4"></a><span class="heading-text paragraph">Smalltalk.</span></h6><p id="x_9_4_0_0_9">Figure <a class="cross-reference" href="#fig:observer:st">69</a> is the GNU Smalltalk library implementation of the classic Smalltalk “dependents” protocol. As part of the standard library, it fits Norvig's criterion for a “formal” instance of the observer pattern. Line 1 establishes a context in which we are supplying definitions for class <tt>Object</tt>. Line 2 declares a <em>class variable</em>, <tt>Dependencies</tt>, on class <tt>Object</tt>, initially with value <tt>nil</tt>. The constructor for class <tt>Object</tt> (lines 36) places a new <tt>WeakKeyIdentityDictionary</tt> in the class variable.</p>
<figure id="x_9_4_0_0_11"><a name="fig:observer:st"></a>
<pre class="listing" id="x_9_4_0_0_10"><code>nil subclass: Object [
Dependencies := nil.
Object class &gt;&gt; initialize [
self == Object ifFalse: [^self].
Dependencies := WeakKeyIdentityDictionary new.
]
addDependent: anObject [
^(Dependencies at: self ifAbsentPut: [OrderedCollection new]) add: anObject
]
removeDependent: anObject [
| dependencies |
dependencies := Dependencies at: self ifAbsent: [^anObject].
dependencies remove: anObject ifAbsent: [].
dependencies size &lt; 1 ifTrue: [Dependencies removeKey: self ifAbsent: []].
^anObject
]
changed: aParameter [
| dependencies |
dependencies := Dependencies at: self ifAbsent: [nil].
dependencies notNil ifTrue: [dependencies do: [:d | d update: aParameter]]
]
changed [
self changed: self
]
update: aParameter [
"Default behavior is to do nothing. Called by #changed and #changed:"
]
]
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>69</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:st"></a><span class="lyx-argument">Observer pattern in Smalltalk<span class="plain-layout-boundary"></span></span>The GNU Smalltalk implementation of the classic Smalltalk dependents mechanism.<br/>(Excerpted from GNU Smalltalk version 3.2.91, &copy; 19902015 Free Software Foundation, Inc.)<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_12">The class variable <tt>Dependencies</tt> contains a dictionary mapping each <em>subject</em> to an <tt>OrderedCollection</tt> of <em>observers</em>. The methods <tt>addDependent:</tt> and <tt>removeDependent:</tt> maintain the structure. Line 20 in the method <tt>changed:</tt> is the heart of the implementation. It sequentially visits each observer in turn, invoking the <tt>update:</tt> method on each with the given parameter value. Idiomatic Smalltalk code conventionally uses the nullary method <tt>changed</tt> (lines 2224) to supply the subject itself as the parameter value of a change notification. The definition of <tt>update:</tt> within class <tt>Object</tt> ensures that <em>every</em> object in the system can act as an observer in this protocol.</p><p id="x_9_4_0_0_13">State replication <em>per se</em> does not appear as a library pattern in Smalltalk. Instead, it appears as an informal pattern, implemented on a case-by-case basis, often making use of the “dependents” protocol. We see an almost-“invisible” instance of event broadcasting on line 20 of figure <a class="cross-reference" href="#fig:observer:st">69</a> in the loop that delivers a call to the <tt>update:</tt> method of each observer object.</p><p id="x_9_4_0_0_14">Figure <a class="cross-reference" href="#fig:observer:st-example">70</a> shows a sketch of our example application. Class <tt>UserList</tt> implements the subject portion of the design, and class <tt>UserListDisplay</tt> implements the observer. The methods <tt>userArrived:</tt> and <tt>userDeparted:</tt> invoke the <tt>UserList</tt>'s <tt>changed</tt> method (lines 4 and 5) to notify observers that something has changed. In response, the <tt>update:</tt> method of <tt>UserListDisplay</tt> is run. Because the Smalltalk convention is to simply convey the <em>fact</em> of a change rather than any detail, <tt>update:</tt> must determine precisely what has changed in order to produce correct incremental output. The explicit call to <tt>update:</tt> on line 14 initializes the display with the set of users present at the time the display is created; if line 14 were omitted, no display updates would happen until the first time the <tt>UserList</tt> <tt>changed</tt>. Finally, the need for <tt>copy</tt> on line 22 is subtle. The <tt>users</tt> method of <tt>UserList</tt> returns a <em>reference</em> to the underlying set collection object, and collections in Smalltalk are imperatively updated. If <tt>copy</tt> on line 22 is omitted, the code fails to detect any changes after the initial update.</p>
<figure id="x_9_4_0_0_16"><a name="fig:observer:st-example"></a>
<pre class="listing" id="x_9_4_0_0_15"><code>Object subclass: UserList [
| users |
initialize [ users := Set new. ]
userArrived: u [ users add: u. self changed. ]
userDeparted: u [ users remove: u. self changed. ]
users [ ^users ]
]
Object subclass: UserListDisplay [
| userList prevUsers |
userList: ul [
prevUsers := Set new.
userList := ul.
userList addDependent: self.
self update: userList.
]
update: anObject [
| new old |
new := userList users - prevUsers.
old := prevUsers - userList users.
new do: [:u | Transcript nextPutAll: u, ' arrived.'; cr ].
old do: [:u | Transcript nextPutAll: u, ' departed.'; cr ].
prevUsers := userList users copy.
]
]
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>70</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:st-example"></a><span class="lyx-argument">Observer pattern example in Smalltalk<span class="plain-layout-boundary"></span></span>A GNU Smalltalk program making use of the “dependents” protocol.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h6 class="unnumbered" id="x_9_4_0_0_17"><a name="toc_9.4"></a><span class="heading-text paragraph">Ruby.</span></h6><p id="x_9_4_0_0_18">Figure <a class="cross-reference" href="#fig:observer:ruby">71</a> is the Ruby standard library implementation of the observer pattern as a <em>mixin</em> module supplying the pattern's subject-side behavior. This, too, is a “formal” implementation of the pattern in Norvig's sense. The code relies on the Ruby idiom of dynamic addition of instance variables to individual objects, creating the <tt>@observer_peers</tt> collection if it does not exist at <tt>add_observer</tt> time (line 3). The implementation is more general than the Smalltalk implementation in that each registered observer may optionally specify a method name to invoke. By default, an observer's <tt>:update</tt> method will be called.</p>
<figure id="x_9_4_0_0_20"><a name="fig:observer:ruby"></a>
<pre class="listing" id="x_9_4_0_0_19"><code>module Observable
def add_observer(observer, func=:update)
@observer_peers = {} unless defined? @observer_peers
@observer_peers[observer] = func
end
def delete_observer(observer)
@observer_peers.delete observer if defined? @observer_peers
end
def changed(state=true)
@observer_state = state
end
def notify_observers(*arg)
if defined? @observer_state and @observer_state
if defined? @observer_peers
@observer_peers.each do |k, v| k.send v, *arg end
end
@observer_state = false
end
end
end
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>71</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:ruby"></a><span class="lyx-argument">Observer pattern in Ruby<span class="plain-layout-boundary"></span></span>The Ruby implementation of the observer pattern. (Excerpted from the Ruby standard library version 2.5.0, &copy; 19982017 Yukihiro Matsumoto and other contributors.)<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_21">The implementation takes care to avoid unnecessary signals, delivering notifications from <tt>notify_observers</tt> only if the subject's <tt>changed</tt> method has been called since the previous <tt>notify_observers</tt> call. This can allow the programmer to <em>batch</em> multiple changes together, sending a single notification at an opportune time after a number of changes have taken place. While this technique is fragile unless the programmer is able to maintain tight control over the sequence of events at the subject, it can provide a form of <em>atomicity</em> for batched changes.</p><p id="x_9_4_0_0_22">Like Smalltalk, Ruby does not formally support the state replication pattern as such. When it comes to event broadcast, line 15 is an almost-“invisible” implementation of event broadcast that is practically identical to the analogous Smalltalk idiom.</p><p id="x_9_4_0_0_23">We omit a Ruby implementation of our <tt>UserList</tt> example, as it is substantially the same as the Smalltalk program, excepting the need for addition of a call to <tt>notify_observers</tt> after each call to <tt>changed</tt>.</p>
<h6 class="unnumbered" id="x_9_4_0_0_24"><a name="toc_9.4"></a><span class="heading-text paragraph">Java.</span></h6><p id="x_9_4_0_0_25">Java supplies a plethora of data classes and interfaces implementing variations on the observer pattern. Figure <a class="cross-reference" href="#fig:observer:java">72</a> shows one example from the standard Swing library. An observer is to implement the <tt>ChangeListener</tt> interface; its single method, <tt>stateChanged</tt>, is invoked by the subject when the relevant change occurs. The argument to <tt>stateChanged</tt> is a <tt>ChangeEvent</tt> bearing a single field, <tt>source</tt>, which by convention is a reference to the subject itself. Each variation on an <tt>EventListener</tt> in the Swing library comes with a corresponding subclass of <tt>EventObject</tt> carrying relevant details of a change, and may have more than one required handler method. For example, a <tt>ListDataListener</tt> implementation must respond to <tt>intervalAdded</tt>, <tt>intervalRemoved</tt> and <tt>contentsChanged</tt> events, each taking a <tt>ListDataEvent</tt>.</p>
<figure id="x_9_4_0_0_27"><a name="fig:observer:java"></a>
<pre class="listing" id="x_9_4_0_0_26"><code>public interface EventListener {}
public interface ChangeListener extends EventListener {
void stateChanged(ChangeEvent e);
}
public class EventObject {
protected transient Object source;
public EventObject(Object source) { this.source = source; }
public Object getSource() { return source; }
}
public class ChangeEvent extends EventObject {
public ChangeEvent(Object source) { super(source); }
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>72</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:java"></a><span class="lyx-argument">Observer pattern in Java<span class="plain-layout-boundary"></span></span>Abbreviated portion of an observer pattern from the Java Swing library. (Excerpted from the OpenJDK 7 source code, &copy; 19962003 Oracle and/or its affiliates.)<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_28">No public utility classes are made available to assist in the implementation of the subject role. This fact, along with the many variations and re-implementations of the pattern found both in the standard libraries and in third-party libraries and applications, leads us to the conclusion that Java offers only “informal” support for the observer pattern.</p><p id="x_9_4_0_0_29">Just as in Smalltalk and Ruby, no formal support for state replication is on offer in Java. Inspection of the uses of the private <tt>EventListenerList</tt> class central to the Swing instances of the observer pattern shows that, again just as in Smalltalk and Ruby, idiomatic Java subjects iterate over a collection object in order to broadcast change notifications.</p>
<h6 class="unnumbered" id="x_9_4_0_0_30"><a name="toc_9.4"></a><span class="heading-text paragraph">Erlang/OTP.</span></h6>
<figure id="x_9_4_0_0_32"><a name="fig:observer:erlang"></a>
<pre class="listing" id="x_9_4_0_0_31"><code>-record(state, {users, listeners}).
init([]) -&gt;
process_flag(trap_exit, true),
{ok, #state{users = [], listeners = []}}.
handle_info({arrive, Name}, State = #state{users = Users, listeners = Listeners}) -&gt;
[L ! {arrived, self(), Name} || L &lt;- Listeners],
{noreply, State#state{users = [Name | Users]}};
handle_info({depart, Name}, State = #state{users = Users, listeners = Listeners}) -&gt;
[L ! {departed, self(), Name} || L &lt;- Listeners],
{noreply, State#state{users = [N || N &lt;- Users, N =/= Name]}};
handle_info({sub, Pid}, State = #state{users = Users, listeners = Listeners}) -&gt;
link(Pid),
[Pid ! {arrived, self(), Name} || Name &lt;- Users],
{noreply, State#state{listeners = [Pid | Listeners]}};
handle_info({unsub, Pid}, State = #state{listeners = Listeners}) -&gt;
unlink(Pid),
{noreply, State#state{listeners = [P || P &lt;- Listeners, P =/= Pid]}};
handle_info({'EXIT', Pid, _Reason}, State = #state{listeners = Listeners}) -&gt;
{noreply, State#state{listeners = [P || P &lt;- Listeners, P =/= Pid]}}.
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>73</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:erlang"></a><span class="lyx-argument">Observer pattern in Erlang<span class="plain-layout-boundary"></span></span>An Erlang <tt>UserList</tt> program using the observer pattern.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_33">With Erlang/OTP we take a step away from shared-memory concurrency and move to a shared-nothing setting with strongly isolated processes. Here the distinction between the observer and state-replication patterns becomes more noticeable. Figure <a class="cross-reference" href="#fig:observer:erlang">73</a> shows the key portions of an actor implementing the <tt>UserList</tt> portion of our running example.</p>
<div class="footnote" id="fn_9_103"><span class="counter footnote-counter"><span>103</span></span>In particular, the <tt>observer</tt> module is a graphical debugging tool, unrelated to the observer pattern.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_9_104"><span class="counter footnote-counter"><span>104</span></span>Based on my first-hand experience of more than a decade of participation in the Erlang community.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_34">Erlang/OTP does not offer a library implementation of the observer pattern or of state replication,<label class="footnote-number" for="fn_9_103">103</label> making these patterns “informally” implemented in Norvig's terms. It does provide a “formal” library implementation of event broadcast called <tt>gen_event</tt>. The interface to <tt>gen_event</tt> requires a separate module for each kind of event callback; no standard callback implementation for the common case of sending an inter-actor message per event is provided. In addition, incorporating a <tt>gen_event</tt> broadcast mechanism as part of the behavior of a stateful actor is awkward, because each event source is implemented with a separate process. These additional processes must be managed carefully to avoid resource leaks, complicating what would ideally be a simple idiom. The <tt>gen_event</tt> module is seldom used outside of specialized situations, perhaps for these reasons. In cases where the observer pattern is appropriate, Erlang programmers generally prefer to roll their own broadcast mechanisms on a case-by-case basis.<label class="footnote-number" for="fn_9_104">104</label></p><p id="x_9_4_0_0_35">The code in figure <a class="cross-reference" href="#fig:observer:erlang">73</a> does just this. The figure shows part of a module implementing an Erlang/OTP <tt>gen_server</tt> service actor; the <tt>init/1</tt> function acts as constructor, <tt>handle_info/2</tt> handles messages delivered to the actor, and the <tt>state</tt> record declaration on line 1 specifies the structure used as the actor's private state value. The actor keeps track of a list representing a set of user names, as well as a list representing a set of observer process IDs.</p><p id="x_9_4_0_0_36">The actor implements two protocols: one corresponding to the <tt>UserList</tt> protocol we saw on lines 45 in the Smalltalk example program (figure <a class="cross-reference" href="#fig:observer:st-example">70</a>), and one corresponding to a use of the observer pattern to provide state replication. Lines 510 take care of the former, while lines 1119 handle the latter.</p>
<div class="footnote" id="fn_9_105"><span class="counter footnote-counter"><span>105</span></span>I have used <tt>handle_info/2</tt> for simplicity. A real implementation would prefer <tt>handle_call/3</tt> and <tt>handle_cast/2</tt>.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_37">Erlang/OTP <tt>gen_server</tt> actors, like Dataspace ISWIM actors, are functional event transducers. Each arriving message is passed to <tt>handle_info/2</tt> along with the actor's private state value.<label class="footnote-number" for="fn_9_105">105</label> The actor is expected to return a functionally-updated state value along with an instruction regarding a possible reply. In response to an <tt>{arrive, Name}</tt> tuple message (line 5; analogous to the Smalltalk program's <tt>userArrived:</tt> method) our actor broadcasts a message to its current subscriber list (line 6), making use of a list comprehension containing an asynchronous message send instruction. It then returns an updated <tt>state</tt> record (line 7), placing the new <tt>Name</tt> at the head of the <tt>users</tt> list. Similarly, a <tt>{depart, Name}</tt> message results in a broadcast and an update removing the <tt>Name</tt> from the <tt>users</tt> list (lines 810).</p>
<div class="footnote" id="fn_9_106"><span class="counter footnote-counter"><span>106</span></span>An alternative implementation might use a special “initial snapshot” message format instead.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_38">Without line 13, this program would be closer to the observer pattern as described by <span class="citation citeauthor"><a class="citation" id="cite-232" href="#bib-Gamma1994">Gamma et al.</a></span> than to an instance of state replication. To explain, we must examine the entirety of the clause of lines 1114. Line 11 matches a subscription request message, <tt>{sub, Pid}</tt>, carrying the process ID of an observing actor. Not only does our service add the new <tt>Pid</tt> to its <tt>listeners</tt> list, but it also supplies the new subscriber with a snapshot of the relevant portion of server state, i.e., the <tt>users</tt> list. It does so using the same protocol it uses for announcing subsequent incremental updates to the list.<label class="footnote-number" for="fn_9_106">106</label> There is an asymmetry here: if we announce the “arrival” of already-present users when a subscriber joins, we might expect it to be reasonable to announce the “departure” of those same users when a subscriber unsubscribes. However, no analogue of line 13 is present in the <tt>unsub</tt> clause (lines 1517).</p><p id="x_9_4_0_0_39">Part of the motivation for moving beyond the traditional scope of an observer pattern implementation, and toward a richer state replication design, is the strict “shared-nothing” isolation of Erlang processes. In shared-memory languages like Smalltalk, Ruby, and Java it makes sense for an observer to immediately interrogate the subject to access its current state; the two are co-located, and a simple call to a getter method suffices. In Erlang, however, analogous retrieval of the user list by an observer via RPC would not only be expensive, but could introduce concurrency bugs: the latency of the round-trip introduces an unavoidable lag during which further changes in the state of the processes in the system could take place. Conveying the relevant public aspects of the subject's state along with the change-notifications themselves elegantly solves this problem. It also obviates the need for anything like the call to <tt>copy</tt> we saw on line 22 of figure <a class="cross-reference" href="#fig:observer:st-example">70</a>. Finally, this subtle shift in the implementation of the observer pattern in shared-nothing languages provides a clue that many uses of the pattern might be better thought of as mere mechanisms for state replication, rather than as ends in themselves.</p>
<div class="footnote" id="fn_9_107"><span class="counter footnote-counter"><span>107</span></span>Line 3 is a standard incantation required by the language to ensure that exit signals are delivered as messages. Omitting line 3 would have the effect of causing our subject actor to crash if an observer process crashes.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_40">We conclude our discussion of Erlang with investigation of lines 12, 16, and 1819 of figure <a class="cross-reference" href="#fig:observer:erlang">73</a>. These subscribe to, unsubscribe from, and react to notifications of process termination, respectively.<label class="footnote-number" for="fn_9_107">107</label> The call to <tt>link</tt> on line 12 ensures that if an observer terminates, either cleanly or with an exception, the subject receives a notification message called an “exit signal” in Erlang parlance. The call to <tt>unlink</tt> on line 16 cancels this subscription, and the clause of lines 1819 treats receipt of an “exit signal” describing the termination of an observer as an implicit unsubscription. An understanding of this message-focused approach to error propagation allows us to see lines 6 and 9 in a new light. They are superficially similar to the one-line implementations of the event broadcast pattern seen in the Smalltalk (figure <a class="cross-reference" href="#fig:observer:st">69</a>, line 20) and Ruby (figure <a class="cross-reference" href="#fig:observer:ruby">71</a>, line 15) library code. The key difference is that in Smalltalk and Ruby each notification is a synchronous method call without error handling. An exception from an observer will cause the remaining observers to miss their notification, and may damage the subject. Here, each notification is an asynchronous message send, which (in Erlang) never results in an exception. Error handling is separated into the code dealing with links and exit signals.</p>
<h6 class="unnumbered" id="x_9_4_0_0_41"><a name="toc_9.4"></a><span class="heading-text paragraph"><span class="small-caps">Syndicate</span>.</span></h6>
<figure id="x_9_4_0_0_43"><a name="fig:observer:PL"></a>
<pre class="listing" id="x_9_4_0_0_42"><code>(assertion-struct user-present (list-id user-name))
(define (spawn-user-list-display list-id)
(spawn (during (user-present list-id $user-name)
(on-start (printf "~a arrived.\n" user-name))
(on-stop (printf "~a departed.\n" user-name)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>74</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:PL"></a><span class="lyx-argument">Observer pattern in <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span>A <span class="small-caps">Syndicate/rkt</span> <tt>UserList</tt> program.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_44">Finally, let us examine state replication, the observer pattern, and event broadcast in <span class="small-caps">Syndicate</span>. The design of <span class="small-caps">Syndicate</span> incorporates a number of lessons from the Erlang approach, but goes beyond it by placing state replication front and center in the programmer's mental model. The <span class="small-caps">Syndicate</span> design proceeds from the assumption that the <em>intent</em> of achieving state replication is more frequent than the intent of achieving the observer pattern, let alone a raw event broadcast. The language thus offers prominent, explicit linguistic support for sharing of public aspects of an actor's private state. Figure <a class="cross-reference" href="#fig:observer:PL">74</a> implements the <span class="small-caps">Syndicate/rkt</span> equivalent of the Smalltalk program of figure <a class="cross-reference" href="#fig:observer:st-example">70</a>.</p><p id="x_9_4_0_0_45">An immediate difference is that class <tt>UserList</tt> is completely absent, appearing in vestigial form only in the declaration of the <tt>user-present</tt> record type (line 1). The function <tt>spawn-user-list-display</tt> is comparable to the Smalltalk class <tt>UserListDisplay</tt>. It observes public aspects of the state of the user list, reacting to appearance or disappearance of set elements with appropriate print commands. In the Smalltalk example, we imagined a component whose role was to call <tt>userArrived:</tt> and <tt>userDeparted:</tt> appropriately for each separate user. The <span class="small-caps">Syndicate</span> program cuts out this intermediary. Instead, an actor responsible for signaling presence of a particular user asserts a <tt>user-present</tt> record for the appropriate duration, and that record is directly communicated to observers by the dataspace. For example, adding the code in figure <a class="cross-reference" href="#fig:observer:PL-extension">75</a> to figure <a class="cross-reference" href="#fig:observer:PL">74</a> causes the program to accept TCP/IP connections, ask for a name, send a greeting, and assert the connected user's presence in the user list until disconnection.</p>
<figure id="x_9_4_0_0_47"><a name="fig:observer:PL-extension"></a>
<pre class="listing" id="x_9_4_0_0_46"><code>(spawn (during/spawn (tcp-connection $id (tcp-listener 5999))
(assert (tcp-accepted id))
(on-start (send! (tcp-out id "What is your name? "))
(react (stop-when (message (tcp-in-line id $name))
(send! (tcp-out id (format "Hello, ~a!\n" name)))
(react (assert (user-present 'room1 name))))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>75</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:observer:PL-extension"></a><span class="small-caps">Syndicate/rkt</span> TCP service interacting with figure <a class="cross-reference" href="#fig:observer:PL">74</a><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_48">The dataspace connecting actors to each other takes on the role that was played by class <tt>UserList</tt>, keeping observers up-to-date as relevant state changes, cleaning up subscriptions on exit, handling failures, and so on. The notion of a subject has become diffuse and domain-specific, rather than being tightly bound to the identity of a single object in the system. The state replication pattern has become “invisible” in Norvig's sense.</p><p id="x_9_4_0_0_49">Object-oriented languages usually offer a notion of object <em>identity</em> that can be used as a marker for a specific topic of conversation. <span class="small-caps">Syndicate</span> does not offer anything like this. Instead, <span class="small-caps">Syndicate</span> encourages the programmer to take a relational view of shared state and demands explicit treatment of identity. The approach is similar to use of primary keys in relational databases. The programmer is free to choose a notion of identity appropriate to the domain.</p><p id="x_9_4_0_0_50"><span class="small-caps">Syndicate</span> emphasizes state replication, but does not preclude use of the observer pattern. Not all uses of the observer pattern are intended to support state replication. The observer pattern is, like state replication, “invisible” in <span class="small-caps">Syndicate</span>. All that is required is for the subject to send change-notification messages with an appropriate structure,</p><p id="x_9_4_0_0_52">
<p class="align-center" id="x_9_4_0_0_51"><tt>(send! (change-notification-record</tt> <em>subject-id change-details</em><tt>))</tt></p></p><p id="x_9_4_0_0_53">optionally also placing more aspects of its state into the dataspace as assertions or responding to RPC state queries. Observers express interest in such notifications in the usual way. Finally, the event broadcast pattern is also completely “invisible”, as it is provided directly by the mechanics of the dataspace model.</p><p id="x_9_4_0_0_54">Recall the asymmetry remarked upon earlier in the Erlang program of figure <a class="cross-reference" href="#fig:observer:erlang">73</a>. When a new observer subscribes, the subject synthesizes “arrival” messages describing the users already present in the room, but sends no analogous “departure” messages to an unsubscribing observer. As we saw in section <a class="cross-reference" href="#sec:DS-properties">4.5</a>, the dataspace ensures that each actor is sent events describing assertions added to or removed from the intersection of the group's assertion set and the specific interests of the actor itself. This set changes <em>either</em> when a peer makes or removes assertions, <em>or</em> when the actor asserts or retracts interests. The dataspace makes no distinction, relaying changes in the relevant set no matter the cause. Thus, unusually, <span class="small-caps">Syndicate</span> is symmetric in the exact way that we observed that our Erlang subject actor is not. When a subscriber retracts interest in a set of assertions, the dataspace issues a state change event that correspondingly removes any extant matching assertions from that actor's view of the world.</p>
<h6 class="unnumbered" id="x_9_4_0_0_55"><a name="toc_9.4"></a><span class="heading-text paragraph">Analysis.</span></h6>
<figure class="fullwidth" id="x_9_4_0_0_58"><a name="fig:Levels-of-implementation:observer"></a>
<p class="align-center" id="x_9_4_0_0_57"><span class="scriptsize">
<div class="tabular" id="x_9_4_0_0_56"><table class="tabular"><tr><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">Smalltalk</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">Ruby</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">Java</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">Erlang/OTP</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none"><span class="scriptsize"><span class="small-caps">Syndicate</span></span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">Event broadcasting</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal/invisible</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal/invisible</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal/invisible</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal/invisible</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true rightline-true usebox-none"><span class="scriptsize">invisible</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">Observer pattern</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">formal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">formal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true leftline-true rightline-true usebox-none"><span class="scriptsize">invisible</span><span class="plain-layout-boundary"></span></td></tr><tr><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">State replication</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true usebox-none"><span class="scriptsize">informal</span><span class="plain-layout-boundary"></span></td><td class="alignment-center valignment-top alignment-center valignment-top topline-true bottomline-true leftline-true rightline-true usebox-none"><span class="scriptsize">invisible</span><span class="plain-layout-boundary"></span></td></tr></table></div></span></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>76</span></span><span class="figcaption-text"><span class="lyx-argument">Levels of implementation of the observer pattern and related patterns<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Levels-of-implementation:observer"></a>Levels of implementation for state replication, the observer pattern, and event broadcasting<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_4_0_0_59">Implementations of the observer pattern vary widely between languages and scenarios within a language. While figure <a class="cross-reference" href="#fig:Levels-of-implementation:observer">76</a> summarizes the situation in terms of Norvig's “levels of implementation,” we must step beyond this and consider practical concerns, which make the following questions relevant to the programmer.</p>
<ol id="x_9_4_0_0_67"><li id="x_9_4_0_0_64">What information is conveyed as part of the signal delivered from a subject to an observer?
<ol id="x_9_4_0_0_63"><li id="x_9_4_0_0_60">Is the entity which changed identified?</li><li id="x_9_4_0_0_61">Is the aspect of that entity which changed identified?</li><li id="x_9_4_0_0_62">Is there room for a detailed description of the particular change?</li></ol></li><li id="x_9_4_0_0_65">How does the implementation interact with garbage collection?</li><li id="x_9_4_0_0_66">How does the implementation interact with errors?</li></ol>
<div class="footnote" id="fn_9_108"><span class="counter footnote-counter"><span>108</span></span>Smalltalk's “selectors” are Lisp's “symbols”.<span class="plain-layout-boundary"></span></div><p id="x_9_4_0_0_68">The Smalltalk implementation allows the subject to send a single object to observers. This is conventionally a reference to the subject itself, but may be any object. A strong secondary convention, when multiple aspects of a subject may change, is to use a selector<label class="footnote-number" for="fn_9_108">108</label> as the notification payload. This has clear weaknesses: it no longer reliably identifies the subject, making it potentially challenging for a single observer to observe <em>multiple</em> subjects at once, and it is a simple atom with no room for additional detail.</p><p id="x_9_4_0_0_69">The Ruby implementation is more flexible. Firstly, and most importantly, no matter the notification payload transmitted by the subject, each observer is given the opportunity to direct notifications on a per-subscription basis to specific entry points by passing an optional second argument (“<tt>func</tt>”) <tt>to</tt> the <tt>add_observer</tt> method. Secondly, the subject may invoke <tt>notify_observers</tt> with any number of any type of arguments. These are passed on as arguments to each observer's chosen handler method. The Erlang implementation, “informal” as it is, is similarly flexible. No particular notification format or payload is required.</p><p id="x_9_4_0_0_70">The <span class="small-caps">Syndicate</span> implementation is likewise flexible, but for a different reason. The specifics of any information communicated from a subject to observers is part of the ordinary <span class="small-caps">Syndicate</span> protocol design for the group. If the identity or nature of the entity which changed is relevant to the protocol, some value denoting it will be included in each assertion and message; likewise for the aspect which changed and any specific details of a given change.</p><p id="x_9_4_0_0_71">The interactions between the observer pattern and garbage collection are straightforward to explain, but can be difficult to address in realistic programs. Consider the Ruby implementation of the <tt>Observable</tt> module (figure <a class="cross-reference" href="#fig:observer:ruby">71</a>). Its use of an ordinary dictionary object establishes strong references to its observers. In cases where an observer becomes otherwise unreachable, the burden is on the programmer to explicitly break the connection between the two to avoid resources leaks or unwanted notifications. The situation is identical in the Java Swing <tt>EventListenerList</tt> subject implementation and is similar in Smalltalk, where a <em>global</em> dictionary with weakly-held keys achieves the same effect as Ruby's per-subject instance variable. In all three cases, care must be taken by the programmer to avoid accidental reference cycles and to develop a rigorous understanding of the lifecycles of all the objects involved.</p><p id="x_9_4_0_0_72">Erlang and <span class="small-caps">Syndicate</span>, however, take a different approach. Actor lifetimes in both languages are under explicit programmer control. Despite this, there are no problems with dangling references. In the case of Erlang, such references are cleaned up as part of a subject's reaction to exit signals from terminated observers. However, solicitation of and responses to exit signals must be explicitly specified by the programmer. In <span class="small-caps">Syndicate</span>, fine-grained conversational <em>frames</em> associated syntactically with <em>facets</em> allow subjects and observers to precisely and automatically delimit the scope and duration of relationships. In the example, observers of <tt>user-present</tt> assertions may see them retracted due to an explicit <em>or</em> implicit retraction, as a conversation comes to an end, or a facet or entire actor terminates. Both Erlang and <span class="small-caps">Syndicate</span> are <em>symmetric</em> in that not only may subjects monitor their observers' lifecycles, but observers may also attend to the presence of observed subjects. In Erlang, this is achieved with links; in <span class="small-caps">Syndicate</span>, by the guaranteed availability and visibility of assertions of interest alongside other assertions. An observer may express interest in <tt>(user-present</tt><em> id</em> <tt>_)</tt> assertions; a subject may express interest in <tt>(observe (user-present</tt><em> id</em> <tt>_))</tt> assertions.</p><p id="x_9_4_0_0_73">Finally, in every implementation of event broadcasting we have seen in object-oriented languages, the same error handling problems arise. An exception signaled by an observer's callback method will by default “spill over” into the context of the <em>subject</em>, potentially damaging it, even though it is the <em>observer</em> at fault. Worse, if the failing observer is in the middle of the subscriber list, entries in the list following the failure will not receive the notification. Error propagation with stack discipline in a situation where different <em>segments</em> of the stack belong to different <em>components</em> in a group is inappropriate.</p><p id="x_9_4_0_0_74">Erlang and <span class="small-caps">Syndicate</span> both do better. Erlang's links and exit signals allow non-linear propagation of failure signals along graphs of components. <span class="small-caps">Syndicate</span> generalizes the idea of Erlang's links, observing that the “liveness” attribute of an actor is just another piece of public state, representable as an assertion like anything else. All of a terminating actor's assertions are automatically withdrawn in the dataspace model; those that describe a “liveness” property of interest can be monitored like any other. This dovetails with the notion of a conversational frame again, where presence of an assertion will frequently delimit a (sub)conversation. The assertions removed as a peer crashes act like exit signals in that they cause well-defined events to be delivered to conversational counterparties.</p><p id="x_9_4_0_0_75">Beyond those three basic questions, some general issues with the observer pattern are worth highlighting. First, by encoding event dispatch among concurrent components as ordinary synchronous method call, common implementations make maintainability of and visibility into a design employing the observer pattern difficult. Programmers must determine for themselves the boundaries between ordinary code and event-driven code, and must reconstruct networks of interacting components by careful inspection of the details of their implementations. <span class="small-caps">Syndicate</span> separates protocol design into a separate programming phase, allowing maintenance of each protocol specification as an artifact of its own, and allowing development of tools specialized for visualization of dataspace traffic, thereby improving maintainability and visibility for concurrent programs. Second, the granularity of event selection in most implementations is coarse; in Smalltalk, for example, the granularity is usually at the level of an entire object. Observers must both filter and demultiplex their notifications to determine whether and, if so, how a particular change is relevant to them. <span class="small-caps">Syndicate</span> allows filtering of information to granularity limited only by the protocol design, and demultiplexes incoming events precisely to individual handler clauses in facet endpoints, thereby improving specificity and efficiency of communication in a concurrent program. Third, it is embarrassingly common when programming with the observer pattern in a synchronous, sequential object-oriented language to accidentally cause an infinite loop of mutual change-notifications, because such notifications do not include enough information to determine whether they are redundant. <span class="small-caps">Syndicate</span> only delivers notifications to observers when a true change is made to the contents of the dataspace; that is, updates in <span class="small-caps">Syndicate</span> are automatically idempotent, thereby improving robustness and reliability of concurrent programs. Finally, as we saw in the case of Java, “informal” implementations of the pattern lead to multiplication of effort with concomitant multiplication of bugs. By bringing state replication into the language once and for all, <span class="small-caps">Syndicate</span> rules out the possibility of competing, inconsistent implementations of the same idea, thereby improving understandability and maintainability of programs.</p>
<h4 id="x_9_5_0_0_1"><a name="toc_9.5"></a><span class="counter section"><span>9.5</span></span><span class="heading-text section">The state pattern</span></h4><p id="x_9_5_0_0_2">The <em>state</em> pattern is a technique used in certain object-oriented languages to simulate the <tt>become</tt> operation from the original actor model <span class="citation citep">(<a class="citation" id="cite-233" href="#bib-Hewitt1973">Hewitt, Bishop and Steiger 1973</a>)</span>. Gamma et al. write that a use of the pattern allows an object “to alter its behavior when its internal state changes,” and that the object “will appear to change its class” <span class="citation citep">(<a class="citation" id="cite-234" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span>. Languages like Self that support dynamic inheritance do not need the pattern: an update to a so-called <em>parent</em> slot automatically adjusts the available state and behavior of an object <span class="citation citep">(<a class="citation" id="cite-235" href="#bib-Ungar1991">Ungar et al. 1991</a>)</span>. This shows that it is possible for an “invisible” implementation of the pattern to exist. Languages like Java and C++, where an object's interface and class are fixed for its lifetime, are where the pattern finds most application.</p><p id="x_9_5_0_0_6">
<figure class="marginfigure" id="x_9_5_0_0_5">
<p class="align-center" id="x_9_5_0_0_4"><img id="x_9_5_0_0_3" src="statepattern.svg" style="width: auto; height: 3.0in;"/></p><span class="plain-layout-boundary"></span></figure></p>
<div class="footnote" id="fn_9_109"><span class="counter footnote-counter"><span>109</span></span>The example is due to <span class="citation citet"><a class="citation" id="cite-236" href="#bib-Nystrom2014"><span>Nystrom<span class="parens"> (</span>2014<span class="parens">)</span></span></a></span>, also available at <a href="http://gameprogrammingpatterns.com/state.html">http://gameprogrammingpatterns.com/state.html</a>.<span class="plain-layout-boundary"></span></div><p id="x_9_5_0_0_7">A state machine representing a video game character's response to key press and release events exemplifies the pattern.<label class="footnote-number" for="fn_9_109">109</label> When the player is standing still, pressing the <tt>JUMP</tt> key causes the player to start a jump sequence. If, in mid-air, the <tt>DOWN</tt> key is pressed, the player should transition into a dive. However, when standing still, the <tt>DOWN</tt> key causes the player to move into a ducking stance. While ducking, release of the <tt>DOWN</tt> key reverts to the standing state. Each state should have associated with it a specific visual appearance (sprite) for the player character.</p>
<h6 class="unnumbered" id="x_9_5_0_0_8"><a name="toc_9.5"></a><span class="heading-text paragraph">Java.</span></h6>
<figure id="x_9_5_0_0_10"><a name="fig:state:java"></a>
<pre class="listing" id="x_9_5_0_0_9"><code>interface KeyHandler {
void handlePress(PlayerWrapper p, Key k);
void handleRelease(PlayerWrapper p, Key k);
}
class PlayerWrapper {
KeyHandler state = new StandingState(this);
public void handlePress(Key k) { state.handlePress(this, k); }
public void handleRelease(Key k) { state.handleRelease(this, k); }
public void setSprite(Sprite s) { /* ... */ }
}
class StandingState implements KeyHandler {
public StandingState(PlayerWrapper p) { p.setSprite(Sprite.STANDING); }
public void handlePress(PlayerWrapper p, Key k) {
if (k == Key.JUMP) p.state = new JumpingState(p);
if (k == Key.DOWN) p.state = new DuckingState(p);
}
public void handleRelease(PlayerWrapper p, Key k) {}
}
class JumpingState implements KeyHandler {
public JumpingState(PlayerWrapper p) { p.setSprite(Sprite.JUMPING); }
public void handlePress(PlayerWrapper p, Key k) {
if (k == Key.DOWN) p.state = new DivingState(p);
}
public void handleRelease(PlayerWrapper p, Key k) {}
}
class DuckingState implements KeyHandler {
public DuckingState(PlayerWrapper p) { p.setSprite(Sprite.DUCKING); }
public void handlePress(PlayerWrapper p, Key k) {}
public void handleRelease(PlayerWrapper p, Key k) {
if (k == Key.DOWN) p.state = new StandingState(p);
}
}
class DivingState implements KeyHandler {
public DivingState(PlayerWrapper p) { p.setSprite(Sprite.DIVING); }
public void handlePress(PlayerWrapper p, Key k) {}
public void handleRelease(PlayerWrapper p, Key k) {}
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>77</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:state:java"></a>State pattern example in Java<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_5_0_0_11">Java implementations of the state pattern are “informal”. The Java program of figure <a class="cross-reference" href="#fig:state:java">77</a> sketches a state pattern based implementation of the example state machine. Key state pattern characteristics are replication of a suite of methods, once in a “wrapper” class (<tt>PlayerWrapper</tt>), and again in an interface (<tt>KeyHandler</tt>) implemented by each “state” class. A separate “state” class is created for each state in the state machine. The interface (and “state” class) version of each method takes an additional argument referencing the “wrapper”. The “wrapper” class version of each method directly delegates to the current “state” object. In more complex situations, a “state” class may use instance variables of its own to keep track of information relevant during its tenure.</p>
<h6 class="unnumbered" id="x_9_5_0_0_12"><a name="toc_9.5"></a><span class="heading-text paragraph"><span class="small-caps">Syndicate</span>.</span></h6>
<figure id="x_9_5_0_0_14"><a name="fig:state:PL"></a>
<pre class="listing" id="x_9_5_0_0_13"><code>(assertion-struct key-down (key))
(assertion-struct player-sprite (variation))
(define (standing-state)
(react (assert (player-sprite 'STANDING))
(stop-when (asserted (key-down 'JUMP)) (jumping-state))
(stop-when (asserted (key-down 'DOWN)) (ducking-state))))
(define (jumping-state)
(react (assert (player-sprite 'JUMPING))
(stop-when (asserted (key-down 'DOWN)) (diving-state))))
(define (ducking-state)
(react (assert (player-sprite 'DUCKING))
(stop-when (retracted (key-down 'DOWN)) (standing-state))))
(define (diving-state)
(react (assert (player-sprite 'DIVING))))
(spawn #:name 'player
(on-start (standing-state)))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>78</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:state:PL"></a>State pattern example in <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_5_0_0_15">The <span class="small-caps">Syndicate/rkt</span> program shown in figure <a class="cross-reference" href="#fig:state:PL">78</a> implements the same state machine using facet <em>mixins</em>, abstractions of units of behavior and state that are named and reusable in multiple contexts. Recall from section <a class="cross-reference" href="#sec:rkt-Core-forms">6.4</a> that <span class="small-caps">Syndicate/rkt</span> allows abstraction over facet creation using ordinary procedures. Here, each state becomes a separate <em>facet</em> rather than a separate <em>class</em>, abstracted into its own procedure so that it may be reused as state transitions take place. Events arriving from the dataspace trigger these transitions: use of <tt>stop-when</tt> ensures that the active state facet <em>terminates</em>, and the handler invokes a procedure that ensures that a new state facet replaces the old. The player actor dynamically includes an appropriate starting facet at initialization time. In more complex state machines, lexical variables and facet-local fields may be used freely for state-specific storage. As in Scheme, where states in a state machine are frequently implemented as mutually tail-calling procedures, the presentation of the state pattern here is “invisible”.</p>
<h6 class="unnumbered" id="x_9_5_0_0_16"><a name="toc_9.5"></a><span class="heading-text paragraph">Analysis.</span></h6>
<div class="footnote" id="fn_9_110"><span class="counter footnote-counter"><span>110</span></span><span class="small-caps">Syndicate</span> cannot claim a unique ability to avoid the interface (<tt>KeyHandler</tt>) required by Java: languages like Smalltalk and Python get by without such interface declarations, while retaining many of the other features of the pattern seen in Java.<span class="plain-layout-boundary"></span></div><p id="x_9_5_0_0_17">The most noticeable difference between the two implementations is the ability of <span class="small-caps">Syndicate/rkt</span> to avoid the duplication that comes with mentioning each method in both the “wrapper”, the interface, and each “state” class.<label class="footnote-number" for="fn_9_110">110</label> Where in Java the programmer must manually arrange for the “wrapper” class <tt>PlayerWrapper</tt> to delegate to matching methods on its current state object, the <span class="small-caps">Syndicate/rkt</span> program's facets directly extend the interaction surface of the containing actor. In essence, the language's built-in demultiplexing and dispatch mechanism is reused to perform the delegation implemented manually in the Java program.</p><p id="x_9_5_0_0_18">A related difference is that in the Java program two objects must collaborate, with a reference to the “wrapper” passed to each “state” method, and a reference to the current state object held in the “wrapper”. In the <span class="small-caps">Syndicate/rkt</span> program, only one object (actor) exists in the dataspace, and the instance variable required in the Java has disappeared, being replaced by the implicit state of the actor's facet tree. Sharing between the “wrapper” and a “state” in the Java program must be allowed for in terms of the visible interface of the “wrapper” object, while in <span class="small-caps">Syndicate/rkt</span>, sharing can be arranged by lexical closure, by passing references to shared fields, or by each state facet publishing shared assertions of its own, as in the example.</p><p id="x_9_5_0_0_19">In this example, every state responds to the same kind of transition event, namely key presses and releases. If different states need to react to other situations in the simulated world, the situation in Java can quickly become complex. For example, the player character may respond to collisions with certain types of objects differently in different states, forcing addition of a <tt>handleCollision()</tt> method to the “wrapper” class, the interface, and all “state” classes—even those for which collisions are irrelevant. In <span class="small-caps">Syndicate</span>, only those facets reactive to an event need mention it, adding additional endpoints to attract and respond to the events concerned.</p><p id="x_9_5_0_0_20">Finally, multiple facets may be active simultaneously in a single actor, allowing rich dynamic possibilities for mixing-in of state and behavior not available to the Java program. In object-oriented languages like Java, up-front planning is required to properly scope per-instance state and to install delegating “wrapper” method implementations.</p>
<h4 id="x_9_6_0_0_1"><a name="toc_9.6"></a><span class="counter section"><span>9.6</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:The-cancellation-pattern"></a><a name="sec:The-cancellation-pattern"></a>The cancellation pattern</span></h4><p id="x_9_6_0_0_2">The <em>cancellation</em> pattern, known as <em>Cancel Task</em> in the business process modeling literature <span class="citation citep">(<a class="citation" id="cite-237" href="#bib-Russell2016">Russell, van der Aalst and ter Hofstede 2016</a>)</span>, appears whenever a long-running, asynchronous task may be interrupted. For example, one common reason for interrupting a task is that the party requesting its execution has lost interest in its outcome. Programming languages with support for asynchronous task execution often support the pattern; for example, the .NET library includes a class <tt>CancellationToken</tt> for use with its task execution machinery, and many implementations of “promises” for JavaScript include cancellability as a feature. A classic example may even be seen in the famous <em>parallel-or</em> operator <span class="citation citep">(<a class="citation" id="cite-238" href="#bib-Plotkin1977">Plotkin 1977</a>)</span>, provided we allow ourselves to imagine a realistic implementation which aborts the longer-running of the two branches of a use of parallel-or once the other yields a result.</p><p id="x_9_6_0_0_3">Cancellation is similar to, but distinct from, an error or exception. As Denicola writes,</p>
<blockquote id="x_9_6_0_0_5">
<p id="x_9_6_0_0_4">A canceled operation is not "successful", but it did not really "fail" either. We want cancellation to propagate in the same way as an exception, but it is not an error. <span class="citation citep">(<a class="citation" id="cite-239" href="#bib-Denicola2016">Denicola 2016</a>)</span></p></blockquote><p id="x_9_6_0_0_6"><span class="small-caps">Syndicate</span> propagates exceptions via automatic retraction of assertions on failure, and this is how it propagates cancellation as well.</p>
<div class="footnote" id="fn_9_111"><span class="counter footnote-counter"><span>111</span></span>The example can be seen at <a href="http://bluebirdjs.com/docs/api/cancellation.html">http://bluebirdjs.com/docs/api/cancellation.html</a>.<span class="plain-layout-boundary"></span></div><p id="x_9_6_0_0_7">To illustrate the pattern, we follow an example drawn from the API documentation of the Bluebird promise library for JavaScript.<label class="footnote-number" for="fn_9_111">111</label> In the example, an incremental search feature submits requests to an HTTP-based search service as the user types. Because the search service may not answer as quickly as the user can type, we wish to be able to abandon previously-started, not-yet-completed searches each time an update to the search term is given. An on-screen “spinning icon” display should appear whenever a search is in progress, disappearing again once results are available.</p>
<h6 class="unnumbered" id="x_9_6_0_0_8"><a name="toc_9.6"></a><span class="heading-text paragraph">JavaScript.</span></h6><p id="x_9_6_0_0_9">The JavaScript language has historically relied on <em>callbacks</em> for structuring its asynchronous tasks, but latterly has shifted to widespread use of <em>promises</em> instead. However, despite much discussion <span class="citation citep">(<a class="citation" id="cite-240" href="#bib-Denicola2016">Denicola 2016</a>)</span>, the specification of the behavior of ES6 promises <span class="citation citep">(<a class="citation" id="cite-241" href="#bib-ECMA-262">ECMA 2015</a> <span class="citation-after">section 25.4</span>)</span> does not include cancellation, leaving JavaScript itself with an “informal” implementation of the pattern each time it is required. Individual implementations of the specification, especially those developed prior to ratification of the standard such as the previously-mentioned Bluebird, include cancellation as an option, yielding “formal” implementations of the pattern when combining a JavaScript engine with a particular promise library.</p>
<figure id="x_9_6_0_0_11"><a name="fig:cancellation:bluebird-http"></a>
<pre class="listing" id="x_9_6_0_0_10"><code>function makeCancellableRequest(url) {
return new Promise(function(resolve, reject, onCancel) {
var xhr = new XMLHttpRequest();
xhr.on("load", resolve);
xhr.on("error", reject);
xhr.open("GET", url, true);
xhr.send(null);
onCancel(function() { xhr.abort(); });
});
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>79</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:cancellation:bluebird-http"></a><span class="lyx-argument">Cancellation pattern example in JavaScript+Bluebird<span class="plain-layout-boundary"></span></span>Cancellation pattern example in JavaScript+Bluebird.<br/>Adapted from <a href="http://bluebirdjs.com/docs/api/cancellation.html">http://bluebirdjs.com/docs/api/cancellation.html</a>.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_6_0_0_12">Figure <a class="cross-reference" href="#fig:cancellation:bluebird-http">79</a> shows a use of Bluebird promises to implement a cancellable HTTP <tt>GET</tt> request. The result of a call to <tt>makeCancellableRequest</tt> is a <em>promise</em> object with a <tt>cancel</tt> method in addition to the usual interface. Bluebird allows the configuration function given to the <tt>Promise</tt> constructor to accept an optional third <tt>onCancel</tt> argument (line 2), which itself is a callback that configures an action to be taken in case the client of the constructed promise decides to cancel it. Here, line 8 specifies that the ongoing <tt>XMLHttpRequest</tt> is to be <tt>abort</tt>ed if the promise returned by <tt>makeCancellableRequest</tt> is canceled.</p>
<figure id="x_9_6_0_0_14"><a name="fig:cancellation:bluebird-incremental-search"></a>
<pre class="listing" id="x_9_6_0_0_13"><code>var searchPromise = Promise.resolve();
function incrementalSearch(searchTerm) {
searchPromise.cancel();
showSpinner();
var thisSearch = makeCancellableRequest("/search?q=" + encodeURIComponent(searchTerm))
.then( function(results) { showResults(results); })
.catch( function(e) { showSearchError(e); })
.finally( function() { if (!thisSearch.isCancelled()) { hideSpinner(); } });
searchPromise = thisSearch;
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>80</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:cancellation:bluebird-incremental-search"></a><span class="lyx-argument">Incremental search using JavaScript+Bluebird<span class="plain-layout-boundary"></span></span>Incremental search using JavaScript+Bluebird.<br/>Adapted from <a href="http://bluebirdjs.com/docs/api/cancellation.html">http://bluebirdjs.com/docs/api/cancellation.html</a>.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_6_0_0_15">Figure <a class="cross-reference" href="#fig:cancellation:bluebird-incremental-search">80</a> implements the core of our illustrative example. The function <tt>incrementalSearch</tt> is to be called with the current search term after every keystroke makes an alteration to the on-screen search field. A global variable, <tt>searchPromise</tt>, is used to remember the most recently-started interaction with the search service. Each time <tt>incrementalSearch</tt> is called, the previous search is canceled (line 3), and a new search is started (line 5) after making sure the “spinner” is displayed (line 4).</p><p id="x_9_6_0_0_16">Each new search ends in one of three outcomes: success, in which case the callbacks of lines 6 and 8 execute; error, in which case lines 7 and 8 execute; or cancellation, in which case <em>only</em> line 8 runs. The test in the <tt>if</tt> statement on line 8 makes sure not to hide the “spinner” if the search has been canceled. After all, cancellation happens only when a new search replaces the currently-active one. If the user were able to also cancel the search without starting a new one, the test on line 8 would become more complex. In general, it can be difficult to decide on the correct placement and timing of such code.</p>
<h6 class="unnumbered" id="x_9_6_0_0_17"><a name="toc_9.6"></a><span class="heading-text paragraph"><span class="small-caps">Syndicate</span>.</span></h6>
<div class="footnote" id="fn_9_112"><span class="counter footnote-counter"><span>112</span></span>Cancellation of a web-request is idempotent.<span class="plain-layout-boundary"></span></div><p id="x_9_6_0_0_18">The notion of an assertion-mediated <em>conversation frame</em> serves here as the heart of <span class="small-caps">Syndicate</span>'s approach to task cancellation, making the pattern “invisible” in Norvig's terminology. A <span class="small-caps">Syndicate/rkt</span> equivalent to <tt>makeCancellableRequest</tt> is shown in figure <a class="cross-reference" href="#fig:cancellation:PL-http">81</a>. Clients trigger creation of a request-specific actor (line 2) by expressing interest in <tt>http-request</tt> tuples. As the actor starts up, it sends the request (line 3). When a response comes in, the actor terminates its root facet (line 5), replacing it with a facet that asserts the response body (line 6). The other situation that causes termination of the root facet is withdrawal of interest in the result. In either case, termination of the facet causes a message canceling the request to be issued (line 4).<label class="footnote-number" for="fn_9_112">112</label> The net effect of figure <a class="cross-reference" href="#fig:cancellation:PL-http">81</a> is to adapt the imperative commands involved in web requests to the declarative, conversation-frame-based approach of assertion-mediated coordination.</p>
<figure id="x_9_6_0_0_20"><a name="fig:cancellation:PL-http"></a>
<pre class="listing" id="x_9_6_0_0_19"><code>(assertion-struct http-request (id url body))
(spawn (during/spawn (observe (http-request $id $url _))
(on-start (web-request-send! id url))
(on-stop (web-request-cancel! id))
(stop-when (message (web-response-complete id _ $body))
(react (assert (http-request id url body))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>81</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:cancellation:PL-http"></a>Cancellation pattern example in <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_9_6_0_0_22"><a name="fig:cancellation:PL-incremental-search"></a>
<pre class="listing" id="x_9_6_0_0_21"><code>(assertion-struct search-term-field (contents))
(assertion-struct search-results (results))
(spawn (during (search-term-field $term)
(define id (gensym 'search-id))
(during (http-request id (format "/search?q=~a" term) $results)
(assert (search-results results)))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>82</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:cancellation:PL-incremental-search"></a>Incremental search using <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_6_0_0_23">Figure <a class="cross-reference" href="#fig:cancellation:PL-incremental-search">82</a> implements the portion of the example that responds to changes in the text in the search term field. The UI component (not shown) maintains a (unique) <tt>search-term-field</tt> assertion, ensuring that it contains the up-to-date query text. In response, for each distinct <tt>term</tt> (line 3) a new request ID is generated (line 4) and an HTTP request is begun (line 5). Upon its completion, a <tt>search-results</tt> record is asserted. However, if the search term changes before the request completes, the entire facet constructed on lines 46 is terminated. In turn, this retracts interest in the results of the unwanted HTTP request, which then cancels itself via the code in figure <a class="cross-reference" href="#fig:cancellation:PL-http">81</a>.</p>
<div class="footnote" id="fn_9_113"><span class="counter footnote-counter"><span>113</span></span>This issue is further discussed in section <a class="cross-reference" href="#sec:limitations">11.3</a>. In this specific case, a “<tt>during/not</tt>” macro could be introduced to abstract away from the details of implementing logical negation this way.<span class="plain-layout-boundary"></span></div><p id="x_9_6_0_0_24">No mention has been made of the “spinner” thus far. We may achieve the desired effect by introducing a <tt>show-spinner</tt> flag, asserting it only in the presence of a <tt>search-term-field</tt> assertion not paired with a <tt>search-results</tt> assertion. Figure <a class="cross-reference" href="#fig:cancellation:PL-incremental-search-loading">83</a> shows the technique. Because we wish to react to the <em>presence</em> of a <tt>search-term-field</tt> but the <em>absence</em> of a <tt>search-results</tt>, we must use the <tt>assert!</tt>/<tt>retract!</tt> commands to invert the sense of the inner <tt>during</tt>.<label class="footnote-number" for="fn_9_113">113</label></p>
<figure id="x_9_6_0_0_26"><a name="fig:cancellation:PL-incremental-search-loading"></a>
<pre class="listing" id="x_9_6_0_0_25"><code>(assertion-struct show-spinner ())
(spawn (during (search-term-field _)
(on-start (assert! (show-spinner)))
(on-stop (retract! (show-spinner)))
(during (search-results _)
(on-start (retract! (show-spinner)))
(on-stop (assert! (show-spinner))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>83</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:cancellation:PL-incremental-search-loading"></a>Incremental search “loading” indicator in <span class="small-caps">Syndicate/rkt</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_9_6_0_0_27">The actual display of the outputs from our program—the “spinner” and any search results that might be available—can be done with separate actors responding to changes in the dataspace. Presence of a <tt>show-spinner</tt> flag assertion causes addition of the loading indicator to the UI; a change in asserted <tt>search-results</tt> causes an update to the relevant widget.</p>
<h6 class="unnumbered" id="x_9_6_0_0_28"><a name="toc_9.6"></a><span class="heading-text paragraph">Analysis.</span></h6><p id="x_9_6_0_0_29">Central to the pattern is the idea of <em>chaining</em> cancellations: if task <span class="lyx-mathjax mathjax-inline">$A$</span> has generated asynchronous sub-tasks <span class="lyx-mathjax mathjax-inline">$B$</span> and <span class="lyx-mathjax mathjax-inline">$C$</span>, then cancellation of <span class="lyx-mathjax mathjax-inline">$A$</span> should automatically lead to the cancellation of <span class="lyx-mathjax mathjax-inline">$B$</span> and <span class="lyx-mathjax mathjax-inline">$C$</span>. In JavaScript, as in .NET, Go, E, Erlang and other languages where some analogue of the pattern appears, such chaining is arranged <em>manually</em> by the programmer. In <span class="small-caps">Syndicate</span>, however, the use of facets and assertions to frame (sub)conversations ensures that when a facet terminates, its withdrawn assertions cause the termination of facets in peers engaged in conversation with it. The process is automatic, and follows without programmer effort as a side-effect of the <span class="small-caps">Syndicate</span>'s protocol-centric design. That is, <span class="small-caps">Syndicate</span>'s cancellation mechanism readily composes, often without explicit “wiring”. </p><p id="x_9_6_0_0_30">In languages with exceptions, interaction of cancellation with exception signaling is unclear. Our JavaScript example demonstrates error propagation along links between promises, but does not address JavaScript's exception mechanism. Solutions must be found on a case-by-case basis: the JavaScript promises API omits cancellation, so there is no standard way to connect cancellation to and from exception flow. In <span class="small-caps">Syndicate</span>, exceptions cause assertion withdrawal, which automatically triggers a cancellation cascade where necessary.</p><p id="x_9_6_0_0_31">Finally, cancellation requires extra care in order to maintain consistency of global invariants. The conditions under which the “spinner” is hidden in the JavaScript example are subtle and could potentially become complicated under even quite simple additions to the scenario. By contrast, <span class="small-caps">Syndicate</span> encourages decomposition of the problem into two phases. First, actors contribute to an overall predicate deciding whether the “spinner” should be shown. Then, a single actor applies the decision from the first phase to the display. Aside from the awkwardness of <tt>assert!</tt>/<tt>retract!</tt>, the code in figure <a class="cross-reference" href="#fig:cancellation:PL-incremental-search-loading">83</a> can almost be read as the declarative statement, “show the spinner when a search is active but no results have yet appeared.”</p>
<h4 id="x_9_7_0_0_1"><a name="toc_9.7"></a><span class="counter section"><span>9.7</span></span><span class="heading-text section">The demand-matcher pattern</span></h4><p id="x_9_7_0_0_2">A common pattern in concurrent systems is <em>demand-matching</em>: tracking of <em>demand</em> for some resource or service, and adding and removing corresponding <em>supply</em> in response to changes in demand. Despite its prevalence in many different types of software, this pattern has not, to my knowledge, previously been given a name. The structure of this section is therefore different to those that have preceded it. Instead of detailed examination of the pattern's appearance in several languages, this section describes the demand-matcher pattern in the style of <span class="citation citet"><a class="citation" id="cite-242" href="#bib-Gamma1994"><span>Gamma et al.<span class="parens"> (</span>1994<span class="parens">)</span></span></a></span> in order to bring the concept into focus. An understanding of the idea shows that <span class="small-caps">Syndicate</span>'s design makes the pattern “invisible”.</p><p id="x_9_7_0_0_3">The demand-matcher pattern's purpose is<em> explicit lifetime management</em>. Even garbage-collected languages require patterned coding to deal with extra-linguistic resources such as sockets, file handles, or large memory buffers. These coding patterns track demand for a resource so that it may be created when required and destroyed in a timely manner when no longer relevant. On the construction side, <em>factory objects</em> and the <em>flyweight</em> pattern exemplify the concept; on the destruction side, close methods and reference-counting are two strategies commonly used.</p><p id="x_9_7_0_0_4">Many instances can be found in a wide variety of programs. For example, every program offering TCP <em>server</em> functionality is an example of the demand-matcher pattern, in any programming language. Demand for the services of the server is indicated by the appearance of a new connection. On UNIX-like systems, this demand is signaled at a fundamental level by <tt>accept(2)</tt> returning a new connected TCP socket. The server provides supply by allocating resources to the new connection, maintaining connection-specific conversational state, and beginning the sub-conversation associated with the new connection. When the remote party disconnects, this <em>drop</em> in demand is signaled by the closing of the connected socket, and the server responds by releasing the connection's resources and cleaning up associated conversational state.</p><p id="x_9_7_0_0_5">Correctly matching supply to demand—that is, correctly allocating and releasing a resource as the need for it waxes and wanes—is motivated by the same concerns that motivate automatic garbage collection. If a programmer does not correctly scope the lifetime of some resource to the lifetime of conversations involving that resource, the resulting program may suffer resource leaks (e.g. unclosed sockets) or dangling references (attempts to write to a closed socket).</p><p id="x_9_7_0_0_6">In <span class="small-caps">Syndicate</span>, facet-based assertion-tracking obviates these patterns. To allocate a resource, a client asserts interest in it. The server responds by constructing a facet whose <tt>on-start</tt> action creates the underlying resource and whose <tt>on-stop</tt> action destroys it. The server's facet lifetime, and hence the resource's lifetime, is scoped by the consumer's continued assertion of interest. Once that interest is withdrawn, the server-side facet terminates, thereby releasing the resource. <span class="small-caps">Syndicate</span>'s facets allow the programmer to bidirectionally associate resources with conversational frames—to bring external resources into the conversational state. Furthermore, dataspace programming allows a straightforward aggregation of interest in a resource because requests following the first one may simply discover the already existing instance of the resource. Similarly, dataspaces allow the easy realization of load-balancing schemes.</p><p id="x_9_7_0_0_7">We have seen many instances of demand-matching in this dissertation already. Informative specimens may be found in example <a class="cross-reference" href="#example:timestate-impl">8.12</a>, figures <a class="cross-reference" href="#fig:Hewitt's-Turing-syllogism">60</a> and <a class="cross-reference" href="#fig:rkt:Automatic-Make-like-compiler">61</a>, and particularly examples <a class="cross-reference" href="#example:mutable-cell-plus-advertisement">8.27</a> and <a class="cross-reference" href="#example:rpc:interest-assertion">8.31</a>, in addition to many of the examples in this chapter.</p>
<h6 class="unnumbered" id="x_9_7_0_0_8"><a name="toc_9.7"></a><span class="heading-text paragraph">Intent</span></h6><p id="x_9_7_0_0_9">Track <em>demand</em> for some resource or service; add and remove corresponding <em>supply</em> in response to changes in demand.</p>
<h6 class="unnumbered" id="x_9_7_0_0_10"><a name="toc_9.7"></a><span class="heading-text paragraph">Participants</span></h6>
<ul id="x_9_7_0_0_14"><li id="x_9_7_0_0_11">Client: source of demand. Must signal changes in demand for service to the Demand Matcher.</li><li id="x_9_7_0_0_12">Demand Matcher: monitors demand and supply levels and brings them into balance when changes are detected; commonly spawns Service instances in response to increases in demand.</li><li id="x_9_7_0_0_13">Service: satisfies demand. Usually signals its existence and/or status to the Demand Matcher to help it perform its balancing task.</li></ul>
<h6 class="unnumbered" id="x_9_7_0_0_15"><a name="toc_9.7"></a><span class="heading-text paragraph">Known&nbsp;uses </span></h6>
<div class="footnote" id="fn_9_114"><span class="counter footnote-counter"><span>114</span></span><a href="https://www.freedesktop.org/wiki/Software/dbus/">https://www.freedesktop.org/wiki/Software/dbus/</a><span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_9_115"><span class="counter footnote-counter"><span>115</span></span><a href="https://aws.amazon.com/elasticloadbalancing/">https://aws.amazon.com/elasticloadbalancing/</a><span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_9_116"><span class="counter footnote-counter"><span>116</span></span><a href="https://aws.amazon.com/articles/1636185810492479">https://aws.amazon.com/articles/1636185810492479</a><span class="plain-layout-boundary"></span></div>
<ul id="x_9_7_0_0_22"><li id="x_9_7_0_0_16">Every TCP service program treats incoming connections as demand, and allocates and deallocates internal resources as connections come and go.</li><li id="x_9_7_0_0_17">The UNIX <tt>inetd</tt> service can be configured to execute programs in response to incoming TCP connections. The recent <tt>systemd</tt> suite of programs can be configured similarly.</li><li id="x_9_7_0_0_18">The <tt>dbus</tt> service bus allows for applications and daemons to be instantiated “on demand when their services are needed.”<label class="footnote-number" for="fn_9_114">114</label></li><li id="x_9_7_0_0_19">Worker pools, e.g. Amazon's “Elastic Load Balancing” product, which “automatically scales its request handling capacity to meet the demands of application traffic.”<label class="footnote-number" for="fn_9_115">115</label> “As Elastic Load Balancing sees changes in the traffic profile, it will scale up or down.”<label class="footnote-number" for="fn_9_116">116</label></li><li id="x_9_7_0_0_20">“Leasing” of resources and “renewal reminders” <span class="citation citep">(<a class="citation" id="cite-243" href="#bib-Hohpe2017">Hohpe 2017</a>)</span> serve as a mechanism for tracking demand. For example, DHCP <span class="citation citep">(<a class="citation" id="cite-244" href="#bib-rfc2131">Droms 1997</a>)</span> allocates IP addresses and issues a lease in response to a message from a client. Decrease in demand happens automatically when an issued lease expires. A second example can be seen in the WebSub protocol <span class="citation citep">(<a class="citation" id="cite-245" href="#bib-WebSub">W3C 2016</a>)</span>, which associates a lease with each subscription and in addition sends a “renewal reminder” when a lease nears expiry.</li><li id="x_9_7_0_0_21">Work items in job queues are implicitly demands for allocation of some compute and/or IO resource, which is automatically freed once its work item completes. A frequently-seen embellishment is the notion of a <em>limited resource</em>, where only a certain number of resources may be in use at once, and if demand exceeds the possible supply, clients must wait for a resource to become free before they may proceed.</li></ul>
<h6 class="unnumbered" id="x_9_7_0_0_23"><a name="toc_9.7"></a><span class="heading-text paragraph">Related&nbsp;concepts&nbsp;and&nbsp;patterns</span></h6>
<ul id="x_9_7_0_0_28"><li id="x_9_7_0_0_24">Flyweight <span class="citation citep">(<a class="citation" id="cite-246" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span>, as seen in e.g. symbol tables: interning a symbol is similar to demand for its existence; symbol tables that weakly hold their entries rely on the garbage-collector to lazily detect absence of demand, releasing the associated resource in response.</li><li id="x_9_7_0_0_25">The “Demand Matcher” participant is often an instance of Factory <span class="citation citep">(<a class="citation" id="cite-247" href="#bib-Gamma1994">Gamma et al. 1994</a>)</span>.</li><li id="x_9_7_0_0_26">Garbage collection (distributed and non-distributed). Abstractly, garbage collection tracks demand for (references to) resources (objects), releasing each resource once its existence is no longer required. Garbage collection would be an example of the Demand Matcher pattern, except for the latter's ability to <em>manufacture</em> demanded resources when demand <em>increases</em>, a feature not offered by garbage collectors.</li><li id="x_9_7_0_0_27">Supervision in Erlang <span class="citation citep">(<a class="citation" id="cite-248" href="#bib-Armstrong2003">Armstrong 2003</a>)</span>. A supervisor monitors actors <em>supplying</em> some service, often created in response to some signal of demand. The supervisor takes action to ensure <em>stable supply</em>, restarting crashing actors as necessary.</li></ul>
<h4 id="x_9_8_0_0_1"><a name="toc_9.8"></a><span class="counter section"><span>9.8</span></span><span class="heading-text section">Actor-language patterns</span></h4><p id="x_9_8_0_0_2">In addition to the broadly-applicable programming patterns thus far discussed, the design of <span class="small-caps">Syndicate</span> eliminates the need for certain more narrowly-focused features seen in actor-based languages such as Erlang. In particular, the introduction of facets in combination with the <tt>react/suspend</tt> construct of section <a class="cross-reference" href="#par:Blocking-expressions">6.5</a> eliminates some patterned uses of <em>selective receive</em>, in those languages with such a construct, and decoupling of presence information from actor identity eliminates complications in protocols making use of <em>request delegation</em>.</p>
<h6 class="unnumbered" id="x_9_8_0_0_3"><a name="toc_9.8"></a><span class="heading-text paragraph">Selective receive.</span></h6>
<div class="footnote" id="fn_9_117"><span class="counter footnote-counter"><span>117</span></span>For those cases where selective-receive-like <em>unavailability</em> is required, it can be implemented as a library routine surrounding a few fields and an internal queue. This explicit representation of a queue of pending messages has some distant relationship to the “activators” of <span class="citation citet"><a class="citation" id="cite-249" href="#bib-Frolund1994"><span>Frølund and Agha<span class="parens"> (</span>1994<span class="parens">)</span></span></a></span> in that it marshals incoming events, suspending further activity until some palatable arrangement of them has been arrived at.<span class="plain-layout-boundary"></span></div><p id="x_9_8_0_0_4">Erlang's <em>selective receive</em> facility allows a process to scan its mailbox for messages matching a certain pattern, yielding the first match or <em>blocking</em> until a matching message is later received. This is used to build RPC-style interaction as a library facility that appears to a client as an ordinary procedure call, hiding the details of communication. The chief drawback of the use of selective receive is a lack of <em>availability</em>. While the actor is in a state waiting for specific messages to arrive, it cannot attend to ordinary requests from peers, thereby increasing the risk of deadlock. <span class="small-caps">Syndicate</span>'s facets eliminate RPC-like patterns involving selective receive entirely, allowing actors to remain available even when managing ongoing sub-conversations with peers.<label class="footnote-number" for="fn_9_117">117</label></p>
<figure id="x_9_8_0_0_6"><a name="fig:Erlang-RPC-client"></a>
<pre class="listing" id="x_9_8_0_0_5"><code>do_call(Process, Request) -&gt;
Mref = erlang:monitor(process, Process),
Process ! {'$gen_call', {self(), Mref}, Request},
receive
{Mref, Reply} -&gt;
erlang:demonitor(Mref, [flush]),
{ok, Reply};
{'DOWN', Mref, _, _, Reason} -&gt;
exit(Reason)
end.
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>84</span></span><span class="figcaption-text"><span class="lyx-argument">Simple RPC client code in Erlang<span class="plain-layout-boundary"></span></span><a class="label-anchor" href="#fig:Erlang-RPC-client"></a>Simple RPC client code in Erlang.<br/>Adapted from <tt>gen:do_call</tt> from Erlang/OTP 19.2, &copy;19962017 Ericsson AB.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_9_118"><span class="counter footnote-counter"><span>118</span></span>The code has been simplified, eliding timeout handling and support for cross-node calls in distributed Erlang.<span class="plain-layout-boundary"></span></div><p id="x_9_8_0_0_7">For example, figure <a class="cross-reference" href="#fig:Erlang-RPC-client">84</a> shows the essence of the library routine <tt>gen:do_call</tt> from Erlang/OTP 19.2.<label class="footnote-number" for="fn_9_118">118</label> Line 1 declares the routine as a function expecting the server's process ID and some value describing the RPC request to issue. Line 2 subscribes to lifecycle information about the server: if it crashes while the subscription is active, a <tt>'DOWN'</tt> message is delivered to subscribing processes. The call to <tt>erlang:monitor</tt> yields a globally unique reference, which here is cleverly used for two purposes: not only does it uniquely identify the subscription just established, it is also pressed into service as an identifier for the specific RPC request instance being executed. Line 3 delivers the request in an envelope. The envelope includes four things: the <tt>Request</tt> itself; an atom, <tt>'$gen_call'</tt>, identifying the RPC protocol that is expected; the sender's own process ID, <tt>self()</tt>; and the <tt>Mref</tt> unique identifier for the request instance.</p><p id="x_9_8_0_0_8">Line 4 opens the selective receive expression. Here, the process expects one of two messages to arrive. If an envelope containing the reply, uniquely labeled with this request's <tt>Mref</tt>, arrives first (line 5), the process cancels its subscription to lifecycle information of the server process (line 6) and returns the result (line 7). If an indication that the server has crashed arrives first (line 8), with context again uniquely identified by <tt>Mref</tt>, then the routine causes <em>this</em> process to crash with the same “exit reason”, thus propagating exceptions across process boundaries in a structured way.</p><p id="x_9_8_0_0_9">If a <tt>'DOWN'</tt> message arrives first, the OTP library relies on the convention that no reply message will arrive later. This works well, though it does rule out patterns of delegation we return to below (section <a class="cross-reference" href="#par:Transparent-request-delegation">9.8</a>). However, if a <em>reply</em> arrives first, a <tt>'DOWN'</tt> message may still be issued in the window between control returning to line 5, and the unsubscription of line 6 taking effect. For this reason, after an unsubscription has taken effect, programmers must take care to use selective receive to discard any pending <tt>'DOWN'</tt> messages that might be queued.</p><p id="x_9_8_0_0_10">Here, the programmer of the routine has done this by passing <tt>flush</tt> to <tt>erlang:demonitor</tt>. Quoting from the Erlang/OTP documentation <span class="citation citep">(<a class="citation" id="cite-250" href="#bib-EricssonAB2017">Ericsson AB 2017</a>)</span>,</p>
<blockquote id="x_9_8_0_0_14">
<p id="x_9_8_0_0_11">Calling <tt>demonitor(Mref, [flush])</tt> is equivalent to the following, but more efficient:</p>
<p id="x_9_8_0_0_13">
<pre class="listing" id="x_9_8_0_0_12"><code>demonitor(Mref),
receive
{_, Mref, _, _, _} -&gt; true
after 0 -&gt; true
end
</code></pre></p></blockquote>
<figure id="x_9_8_0_0_16"><a name="fig:Syndicate-RPC-client"></a>
<pre class="listing" id="x_9_8_0_0_15"><code>(define (do-call self-pid process request)
(define request-id (gensym 'request-id))
(react/suspend (k)
(on (asserted (present process))
(send! (rpc-request process self-pid request-id request)))
(stop-when (retracted (present process))
(error 'do-call "Server exited before replying!"))
(stop-when (message (rpc-reply self-pid request-id $reply))
(k reply))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>85</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Syndicate-RPC-client"></a>Approximate <span class="small-caps">Syndicate</span> analogue of figure <a class="cross-reference" href="#fig:Erlang-RPC-client">84</a><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_9_119"><span class="counter footnote-counter"><span>119</span></span>Note, however, that <tt>k</tt> is not mentioned on line 7, which means that any exception handler in the context of <tt>do-call</tt> has no opportunity to catch the error signaled by line 7. The actor simply terminates. Local adjustment of <tt>do-call</tt> can rectify the problem; more sophisticated integration of Racket exceptions, partial continuations, and facets remains as future work.<span class="plain-layout-boundary"></span></div><p id="x_9_8_0_0_17"><span class="small-caps">Syndicate</span> eliminates the need for these uses of selective receive. The rough equivalent of figure <a class="cross-reference" href="#fig:Erlang-RPC-client">84</a> is shown in figure <a class="cross-reference" href="#fig:Syndicate-RPC-client">85</a>. The use of <tt>react/suspend</tt> on line 3 reifies a partial continuation, making <tt>do-call</tt> a blocking procedure just like Erlang's <tt>do_call</tt>.<label class="footnote-number" for="fn_9_119">119</label> The protocol sketched here assumes that the server asserts <tt>(present</tt> <tt><span class="lyx-mathjax mathjax-inline">$\mathit{id}$</span>)</tt> as a placeholder for an appropriate domain-specific indication of presence; lines 6 and 7 in figure <a class="cross-reference" href="#fig:Syndicate-RPC-client">85</a> react to retraction of presence, which corresponds to handling of the <tt>'DOWN'</tt> message on lines 8 and 9 of figure <a class="cross-reference" href="#fig:Erlang-RPC-client">84</a>. Because the facet expressing interest in <tt>present</tt> assertions is terminated either when a reply is received or the server crashes, and the facet's interests are retracted at its termination, the situation of needing to flush a pending server termination message never arises.</p><p id="x_9_8_0_0_18">Generally, the fact that <span class="small-caps">Syndicate</span>'s facets combine subscriptions and event handlers, so that one never exists without the other, ensures that messages are delivered to relevant handlers, and conversely, that irrelevant messages are never handled at all.</p>
<h6 class="unnumbered" id="x_9_8_0_0_19"><a name="toc_9.8"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Transparent-request-delegation"></a><a name="par:Transparent-request-delegation"></a>Transparent request delegation.</span></h6><p id="x_9_8_0_0_20">An RPC server process in Erlang/OTP may, upon receiving an RPC request, forward the request to some other “worker” process, which replies on its behalf. Clients use Erlang's “monitor” facility to detect failures in server processes. However, if a server forwards a request, the client is left monitoring the original server process and not the worker process that has just been given responsibility for delivering the reply. If the worker process crashes, the client is left hanging; conversely, if the service process crashes, but the worker process is still running normally, the client will falsely assume its RPC request failed. Worse, because of the hard-coded assumption that a crash implies that no reply will subsequently arrive, the client will later be faced with a “martian packet”; that is, a reply from the worker will arrive after the necessary context information has already been discarded.</p>
<div class="footnote" id="fn_9_120"><span class="counter footnote-counter"><span>120</span></span>This non-transparency is similar to the delegation involved in HTTP's redirect responses, with their <tt>Location</tt> headers. HTTP reverse-proxying, by contrast, is a form of transparent delegation.<span class="plain-layout-boundary"></span></div><p id="x_9_8_0_0_21">A few workarounds exist. The worker may forward the reply to the server process, which relays it in turn to the original requestor, thereby avoiding the “martian packet” scenario. The server may monitor the worker, perhaps crashing if it notices the worker crash, or perhaps remembering its obligations and synthesizing crash signals specifically for the clients affected by the crash. The worker may monitor the server, crashing if it notices the server crash, thereby at least avoiding wasted effort; however, it is important to note that a race condition exists here: the worker may finish its work and deliver the reply to the client before it receives notification that the server has crashed, bringing us back to a “martian packet” scenario. Finally, the transparency of delegation may be discarded, and the server may reply to the client with the identity of the worker, essentially telling it to expect a real reply later from a different source.<label class="footnote-number" for="fn_9_120">120</label></p><p id="x_9_8_0_0_22">Delegation in <span class="small-caps">Syndicate</span> does not suffer from any of these problems. <span class="small-caps">Syndicate</span> presence indications are not tied to actor identity: instead, presence may be as coarse- or fine-grained as the domain requires. For example, a <span class="small-caps">Syndicate</span> service may use a protocol that advertises the fact that a reply is on its way <em>for a certain request ID</em>:</p><p id="x_9_8_0_0_24">
<p class="align-center" id="x_9_8_0_0_23"><tt>(request-in-progress service-id request-id)</tt></p></p><p id="x_9_8_0_0_25">A service that does not delegate requests manages these request-specific assertions itself, while a delegating service passes responsibility for maintaining <tt>request-in-progress</tt> assertions along with the task at hand. In each case, the assertion of interest contains the same information: the client is unaware of the identity of the specific actor handling the request, but nonetheless is able to monitor the request's progress.</p><p id="x_9_8_0_0_26">This benefit was achieved by generalizing away from using implementation-specific identifiers (process IDs) as proxies for domain-specific information (the possibility of receiving a reply to a request). Having broken this tight coupling, we are now free to explore additional possibilities not previously available. For example, we may extend <tt>request-in-progress</tt> assertions to include more detailed progress information for long-running tasks simply by adding a field; clients monitoring request progress are thus automatically informed as milestones go by.</p></p><p id="x_10_3_0_0_5">
<h3 id="x_10_0_0_0_1"><a name="toc_10"></a><span class="counter chapter"><span>10</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:PERFORMANCE"></a><a name="CHAP:PERFORMANCE"></a>Evaluation: Performance</span></h3>
<div class="lyx-mathjax mathjax-definitions" id="x_10_0_0_0_2">\(\newcommand{\SOFTO}[1]{\tilde{O}(#1)}
\)</div><p id="x_10_0_0_0_3">Established approaches to concurrency generally have well-understood performance models that programmers use when reasoning about the expected and actual behavior of their programs. The actor model, for example, naturally admits <span class="lyx-mathjax mathjax-inline">$\SOFTO 1$</span> message delivery and <span class="lyx-mathjax mathjax-inline">$\SOFTO 1$</span> process creation in most implementations; the abstract performance of the Relational database model can be understood in terms of table scans and index characteristics; and so on. The <span class="small-caps">Syndicate</span> model includes features such as multicast and state change notifications not present in other approaches to concurrency, and does not fit the established performance models. Therefore, we must develop a <span class="small-caps">Syndicate</span>-specific performance model that programmers can rely on in the design and evaluation of their <span class="small-caps">Syndicate</span> programs, and in the understanding of the <span class="small-caps">Syndicate</span> programs of others. We begin by considering the abstract costs of <span class="small-caps">Syndicate</span> actions (section <a class="cross-reference" href="#sec:Cost-intuition">10.1</a>), which we then confirm with measurements of asymptotic performance characteristics of representative protocols (section <a class="cross-reference" href="#sec:Measuring-abstract-performance">10.2</a>). Finally, we touch on the concrete performance of the <span class="small-caps">Syndicate/rkt</span> prototype implementation (section <a class="cross-reference" href="#sec:Concrete-performance">10.3</a>).</p>
<h4 id="x_10_1_0_0_1"><a name="toc_10.1"></a><span class="counter section"><span>10.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Cost-intuition"></a><a name="sec:Cost-intuition"></a>Reasoning about routing time and delivery time</span></h4>
<div class="footnote" id="fn_10_121"><span class="counter footnote-counter"><span>121</span></span>Facets within actors are similar to actors within a dataspace, and the costs of routing <em>within</em> an actor can be understood by analogy to routing within a dataspace.<span class="plain-layout-boundary"></span></div><p id="x_10_1_0_0_2">The key to <span class="small-caps">Syndicate</span>'s performance is the implementation of dataspace-model actions.<label class="footnote-number" for="fn_10_121">121</label> A model of performance must give the programmer a sense of the costs involved in the interpretation of the three possible types of action. Interpretation of a spawn action is like interpretation of a state change notification, because the initial assertion set conveyed with a leaf actor is transformed into just such an action. Interpretation of message and state change notification actions involves two steps, with associated costs: computation of the set of recipients (“routing”) followed by delivery of an event to each identified recipient (“delivery”).</p><p id="x_10_1_0_0_3">Programmers might reasonably expect that the routing time of state change notifications should be bounded by the number of assertions in each notification, which is why the incremental semantics using patches instead of full sets is so important. A complication arises, however, when one considers that patches involving wildcards refer to <em>infinite</em> sets of assertions. The trie-based representation of assertion sets takes care to represent such infinite sets tractably, but the programmer cannot assume a routing time bounded by the size of the <em>representation</em> of the notification. To see this, consider that asserting <span class="lyx-mathjax mathjax-inline">$\star$</span> forces a traversal of the entirety of the <span class="lyx-mathjax mathjax-inline">$?$</span>-prefixed portion of the dataspace to discover <em>every</em> active interest.</p><p id="x_10_1_0_0_4">Fortunately, routing time of SCNs <em>can</em> be bounded by the size of the representation of the <em>intersection</em> of the patch with the dataspace itself. When processing a patch <span class="lyx-mathjax mathjax-inline">$\frac{\ROUTES_{i}}{\ROUTES_{o}}$</span> to a dataspace <span class="lyx-mathjax mathjax-inline">$R$</span>, the function <span class="lyx-mathjax mathjax-inline">$\COMBINEname$</span> (figure <a class="cross-reference" href="#fig:combine-function">39</a>) explores <span class="lyx-mathjax mathjax-inline">$R$</span> only along paths that are in <span class="lyx-mathjax mathjax-inline">$\ROUTES_{i}$</span> or <span class="lyx-mathjax mathjax-inline">$\ROUTES_{o}$</span>. Thus, when reasoning about SCN routing time, programmers must set their performance expectations based on both the patches being issued and the assertions established in the environment to be modified by each patch. After routing has identified the actors to receive state change notifications, the associated delivery time should be linear in the number of recipients.</p><p id="x_10_1_0_0_5">The costs of message actions are simpler to understand than those of SCN actions, allowing us to make more precise statements on expected upper bounds. The key variable is the fraction of each message that must be examined to route it to a set of destinations. For example, some <span class="small-caps">Syndicate</span> protocols treat messages as pairs of an address, used to select recipients, and a body that is not examined during routing. That is, messages are of the form <span class="lyx-mathjax mathjax-inline">$(\mathit{address},\mathit{body})$</span>, and assertions of interest are of the form <span class="lyx-mathjax mathjax-inline">$\Obs{(\mathit{address},\star)}$</span>. For such protocols, the routing process should take time in <span class="lyx-mathjax mathjax-inline">$\SOFTO{|\mathit{address}|}$</span>. More general messaging protocols effectively use more of each message as address information. In such cases, routing time should be bounded by <span class="lyx-mathjax mathjax-inline">$\SOFTO{|\mathit{message}|}$</span>. In either case, noting that <span class="lyx-mathjax mathjax-inline">$|\mathit{address}|\leq|\mathit{message}|$</span>, delivery to all <span class="lyx-mathjax mathjax-inline">$n$</span> interested recipients should take time in <span class="lyx-mathjax mathjax-inline">$\SOFTO n$</span>, for <span class="lyx-mathjax mathjax-inline">$\SOFTO{|\mathit{message}|+n}$</span> overall processing time. Encoding actor-style unicast messaging is then a special case, where the address is a target process ID, <span class="lyx-mathjax mathjax-inline">$\SOFTO{|\mathit{address}|}=\SOFTO 1$</span>, the size of the message body is irrelevant, and <span class="lyx-mathjax mathjax-inline">$n=1$</span>, yielding <span class="lyx-mathjax mathjax-inline">$\SOFTO 1$</span> expected per-message cost.</p>
<h4 id="x_10_2_0_0_1"><a name="toc_10.2"></a><span class="counter section"><span>10.2</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Measuring-abstract-performance"></a><a name="sec:Measuring-abstract-performance"></a>Measuring abstract <span class="small-caps">Syndicate</span> performance</span></h4><p id="x_10_2_0_0_2">Notwithstanding the remarks above, we cannot yet make precise statements about complexity bounds on routing and delivery costs in <span class="small-caps">Syndicate</span> in general. The difficulty is the complex interaction between the protocol chosen by the programmer and the data structures and algorithms used to represent and manipulate assertion sets in the <span class="small-caps">Syndicate</span> implementation.</p><p id="x_10_2_0_0_3">We can, however, measure the performance of <span class="small-caps">Syndicate/rkt</span> on representative protocols. For example, we expect that:</p>
<ul id="x_10_2_0_0_8"><li id="x_10_2_0_0_4">simple actor-style unicast messaging performs in <span class="lyx-mathjax mathjax-inline">$\SOFTO 1$</span>;</li><li id="x_10_2_0_0_5">multicast messaging performs within <span class="lyx-mathjax mathjax-inline">$\SOFTO{|\mathit{message}|+n}$</span>;</li><li id="x_10_2_0_0_6">state change notification performance can be understood; and</li><li id="x_10_2_0_0_7"><span class="small-caps">Syndicate</span> programs can smoothly interoperate with the “real world.”</li></ul>
<h6 class="unnumbered" id="x_10_2_0_0_9"><a name="toc_10.2"></a><span class="heading-text paragraph">Unicast messaging.</span></h6>
<figure id="x_10_2_0_0_15"><a name="fig:Message-latencies"></a>
<figure id="x_10_2_0_0_11"><a name="fig:Message-latencies-Unicast"></a><img id="x_10_2_0_0_10" src="Figures/performance/cost-per-msg.svg"/><figcaption><span class="counter figure"><span>86(a)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Message-latencies-Unicast"></a>Unicast<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_10_2_0_0_13"><a name="fig:Message-latencies-Broadcast"></a><img id="x_10_2_0_0_12" src="Figures/performance/cost-per-broadcast.svg"/><figcaption><span class="counter figure"><span>86(b)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Message-latencies-Broadcast"></a>Broadcast<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p class="align-center" id="x_10_2_0_0_14">&emsp;&emsp;</p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>86</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Message-latencies"></a>Message routing and delivery latencies, sec/msg vs. <span class="lyx-mathjax mathjax-inline">$k$</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_10_2_0_0_16">We demonstrate a unicast, actor-like protocol using a simple “ping-pong” program. The program starts <span class="lyx-mathjax mathjax-inline">$k$</span> actors in a single <span class="small-caps">Syndicate</span> dataspace, with the <span class="lyx-mathjax mathjax-inline">$i$</span>th peer asserting the subscription <span class="lyx-mathjax mathjax-inline">$?(\mathtt{ping},\star,i)$</span>. When it receives a message <span class="lyx-mathjax mathjax-inline">$(\mathtt{ping},j,i)$</span>, it replies by sending <span class="lyx-mathjax mathjax-inline">$(\mathtt{ping},i,j)$</span>. Once all <span class="lyx-mathjax mathjax-inline">$k$</span> peers have started, a final process numbered <span class="lyx-mathjax mathjax-inline">$k+1$</span> starts and exchanges messages with one of the others until ten seconds have elapsed. It then records the overall mean message delivery latency.</p><p id="x_10_2_0_0_17">Figure <a class="cross-reference" href="#fig:Message-latencies-Unicast">86(a)</a> shows message latency as a function of the number of actors. Each point along the <span class="lyx-mathjax mathjax-inline">$x$</span>-axis corresponds to a complete run with a specific value for <span class="lyx-mathjax mathjax-inline">$k$</span>. It confirms that, as expected, total routing and delivery latency is roughly <span class="lyx-mathjax mathjax-inline">$\SOFTO 1$</span>.</p>
<h6 class="unnumbered" id="x_10_2_0_0_18"><a name="toc_10.2"></a><span class="heading-text paragraph">Broadcast messaging.</span></h6><p id="x_10_2_0_0_19">To analyze the behavior of broadcasting, we measure a variation on the “ping-pong” program which broadcasts each ping to all <span class="lyx-mathjax mathjax-inline">$k$</span> participants. Each <em>sent</em> message results in <span class="lyx-mathjax mathjax-inline">$k$</span> <em>delivered</em> messages. Figure <a class="cross-reference" href="#fig:Message-latencies-Broadcast">86(b)</a> shows mean latency of each delivery against <span class="lyx-mathjax mathjax-inline">$k$</span>. This latency is comprised of a fixed per-delivery cost along with that delivery's share of a fixed <em>per-transmission</em> routing cost. In small groups, the fixed routing cost is divided among few actors, while in large groups it is divided among many, becoming an infinitesimal contributor to overall delivery latency. Latency of each delivery, then, is roughly <span class="lyx-mathjax mathjax-inline">$\SOFTO{\frac{1}{k}+1}$</span>. Aggregating to yield latency for each transmission gives <span class="lyx-mathjax mathjax-inline">$\SOFTO{1+k}$</span>, as expected.</p>
<h6 class="unnumbered" id="x_10_2_0_0_20"><a name="toc_10.2"></a><span class="heading-text paragraph">State Change Notifications.</span></h6><p id="x_10_2_0_0_21">Protocols making use of state change notifications fall into one of two categories: either the number of assertions relevant to an actor's interests depends on the number of actors in the group, or it does not. Hence, we measure one of each kind of protocol.</p><p id="x_10_2_0_0_22">The first program uses a protocol with assertion sets independent of group size. A single “publishing” actor asserts the set <span class="lyx-mathjax mathjax-inline">$\{\mathtt{A}\}$</span>, a single atom, and <span class="lyx-mathjax mathjax-inline">$k$</span> “subscribers” are started, each asserting <span class="lyx-mathjax mathjax-inline">$\{?\mathtt{A}\}$</span>. Exactly <span class="lyx-mathjax mathjax-inline">$k$</span> patch events <span class="lyx-mathjax mathjax-inline">$\frac{\{\mathtt{A}\}}{\emptyset}$</span> are delivered. Each event has constant, small size, no matter the value of <span class="lyx-mathjax mathjax-inline">$k$</span>.</p><p id="x_10_2_0_0_23">The second program demonstrates a protocol sensitive to group size, akin to a “chatroom” protocol. The program starts <span class="lyx-mathjax mathjax-inline">$k$</span> “peer” actors in total. The <span class="lyx-mathjax mathjax-inline">$i$</span>th peer asserts a patch containing both <span class="lyx-mathjax mathjax-inline">$(\mathtt{presence},i)$</span> and <span class="lyx-mathjax mathjax-inline">$?(\mathtt{presence},\star)$</span>. It thereby informs peers of its own existence while observing the presence of every other actor in the dataspace. Consequently, it initially receives a patch indicating its own presence along with that of the <span class="lyx-mathjax mathjax-inline">$i-1$</span> previously-started peers, followed by <span class="lyx-mathjax mathjax-inline">$k-i-1$</span> patches, one at a time as each subsequently-arriving peer starts up.</p>
<figure id="x_10_2_0_0_29"><a name="fig:SCN-cost"></a>
<figure id="x_10_2_0_0_25"><a name="fig:SCN-cost-Independent"></a><img id="x_10_2_0_0_24" src="Figures/performance/cost-per-scn-1.svg"/><figcaption><span class="counter figure"><span>87(a)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:SCN-cost-Independent"></a>Independent of <span class="lyx-mathjax mathjax-inline">$k$</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_10_2_0_0_27"><a name="fig:SCN-cost-Dependent"></a><img id="x_10_2_0_0_26" src="Figures/performance/cost-per-scn-2.svg"/><figcaption><span class="counter figure"><span>87(b)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:SCN-cost-Dependent"></a>Dependent upon <span class="lyx-mathjax mathjax-inline">$k$</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<p class="align-center" id="x_10_2_0_0_28">&emsp;&emsp;</p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>87</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:SCN-cost"></a>State Change Notification cost, sec/notification vs. <span class="lyx-mathjax mathjax-inline">$k$</span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_10_2_0_0_30">Measuring the time-to-inertness of differently-sized examples of each program and dividing by the number of state change notification events delivered shows that in both cases the processing required to compute and deliver each state change notification is roughly constant even as <span class="lyx-mathjax mathjax-inline">$k$</span> varies (figure <a class="cross-reference" href="#fig:SCN-cost">87</a>).</p>
<h6 class="unnumbered" id="x_10_2_0_0_31"><a name="toc_10.2"></a><span class="heading-text paragraph">Communication with the “outside world”.</span></h6><p id="x_10_2_0_0_32">An implementation of a TCP/IP “echo” service validates the claim that <span class="small-caps">Syndicate</span> can effectively structure a concurrent program that interacts with the wider world, because this service is a typical representative of many network server applications.</p><p id="x_10_2_0_0_33">The implementation-provided TCP driver actor provides a pure <span class="small-caps">Syndicate</span> interface to socket functionality. A new connection is signaled by a new assertion. The program responds by spawning an actor for the connection. When the connection closes, the driver retracts the assertion, and the per-connection actor reacts by terminating.</p>
<figure id="x_10_2_0_0_36"><a name="fig:Marginal-cost-of-connection"></a><img id="x_10_2_0_0_34" src="Figures/performance/echo-server-cost.svg"/><span class="plain-layout-boundary"></span>
<p class="align-center" id="x_10_2_0_0_35"><figcaption><span class="counter figure"><span>88</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Marginal-cost-of-connection"></a>Marginal cost of additional connections, sec/conn. vs. <span class="lyx-mathjax mathjax-inline">$k$</span><span class="plain-layout-boundary"></span></span></figcaption></p><span class="plain-layout-boundary"></span></figure><p id="x_10_2_0_0_37">The scalability of the server is demonstrated by gradually ramping up the number of active connections. The client program alternates between adding new connections and performing work spread evenly across all open connections. During each connection-opening phase, it computes the mean per-connection time taken for the server to become ready for work again after handling the batch of added connections. Figure <a class="cross-reference" href="#fig:Marginal-cost-of-connection">88</a> plots the value of <span class="lyx-mathjax mathjax-inline">$k$</span>, the total number of connections at the end of a phase, on the (logarithmic) <span class="lyx-mathjax mathjax-inline">$x$</span>-axis; on the <span class="lyx-mathjax mathjax-inline">$y$</span>-axis, it records mean seconds taken for the server to handle each new arrival. The marginal cost of each additional connection remains essentially constant and small, though the results are noisy and subject to GC effects.</p>
<h4 id="x_10_3_0_0_1"><a name="toc_10.3"></a><span class="counter section"><span>10.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Concrete-performance"></a><a name="sec:Concrete-performance"></a>Concrete <span class="small-caps">Syndicate</span> performance</span></h4>
<div class="footnote" id="fn_10_122"><span class="counter footnote-counter"><span>122</span></span>Both figures are for a single core. <span class="small-caps">Syndicate/rkt</span> does not yet take advantage of multiple cores because Racket requires special programming for multi-core operation.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_10_123"><span class="counter footnote-counter"><span>123</span></span>The temptation to dismiss the <span class="small-caps">Syndicate</span> design on grounds of performance must be resisted. A relevant comparison is the development of Smalltalk, a dynamic object-oriented programming system. Early Smalltalk implementations <span class="citation citep">(<a class="citation" id="cite-251" href="#bib-Kay1993">Kay 1993</a>)</span> required custom hardware for reasonable performance, and it was not until the Self research program bore fruit <span class="citation citep">(<a class="citation" id="cite-252" href="#bib-Chambers1992">Chambers 1992</a>; <a class="citation" id="cite-253" href="#bib-Holzle1994">Hölzle 1994</a>; <a class="citation" id="cite-254" href="#bib-Holzle1995">Hölzle and Ungar 1995</a>)</span> some twenty years later that dynamic object-oriented systems attained performance levels enabling their use in a wide array of production applications.<span class="plain-layout-boundary"></span></div><p id="x_10_3_0_0_2">We have seen that the <em>abstract </em>(big-O) performance of <span class="small-caps">Syndicate</span> dataspace implementations using the trie structure satisfies our expectations. However, programmers rely not only on big-O evaluations, but also on absolute performance figures. In absolute terms, looking only at micro-benchmarks such as those explored above, we see that message-passing performance is quite respectable. The results of figures <a class="cross-reference" href="#fig:Message-latencies">86</a>, <a class="cross-reference" href="#fig:SCN-cost">87</a> and <a class="cross-reference" href="#fig:Marginal-cost-of-connection">88</a> were all produced on my commodity 2015-era desktop Linux machine, an Intel Core i7-3770 running at 3.4 GHz; figure <a class="cross-reference" href="#fig:Message-latencies-Unicast">86(a)</a> shows that <span class="small-caps">Syndicate/rkt</span> can <em>route</em> approximately 30,000 messages per second, while figure <a class="cross-reference" href="#fig:Message-latencies-Broadcast">86(b)</a> shows that it can <em>deliver</em> approximately 1,000,000 messages per second.<label class="footnote-number" for="fn_10_122">122</label> As a rough comparison, a crude “ping-pong” program written to Racket's built-in <tt>thread</tt>, <tt>thread-send</tt>, and <tt>thread-receive</tt> APIs yields approximately 780,000 point-to-point messages (i.e., each message involving both routing and delivery) per second. We may conclude that the <span class="small-caps">Syndicate/rkt</span> prototype's absolute routing performance is roughly a factor of twenty slower than the optimized point-to-point routing infrastructure available in a production language implementation. Assertion-set manipulation is new, so we have nothing to compare it against; that said, there are clear directions for improving the constant factors.<label class="footnote-number" for="fn_10_123">123</label></p><p id="x_10_3_0_0_3">More broadly, the speed of the prototype <span class="small-caps">Syndicate</span> implementations has not prevented effective use and evaluation of the programs written thus far. Of the larger <span class="small-caps">Syndicate</span> case studies, the 2D platformers are most challenging from a performance perspective: to achieve a 60 Hz frame rate, a program must never exceed a hard per-frame time budget of 16.67ms. Platformer “A”, written primarily using protocols involving <span class="small-caps">Syndicate</span> <em>messages</em>, has no trouble maintaining a high frame rate even with tens of moving agents on-screen; platformer “B”, written primarily using protocols manipulating <em>assertions</em>, only manages a high frame rate with one or two simultaneously moving agents on the screen. To see why, consider again figures <a class="cross-reference" href="#fig:Message-latencies">86</a> and <a class="cross-reference" href="#fig:SCN-cost">87</a>: at 30,000 messages per second, we may send up to 500 messages per frame before exceeding our 60 Hz frame budget; but SCN processing is substantially slower. Even the very simple program whose measurements are shown in figure <a class="cross-reference" href="#fig:SCN-cost">87</a> does not exceed some 2,500 SCNs per second, which at 60 Hz gives us a budget of approximately 40 SCNs per frame. Clearly, future work on optimization of SCN processing will be of great benefit to applications like platformer “B” which have real-time constraints and make use of assertion-manipulation-heavy protocols. However, the platform games are an outlier; none of the other case studies places such extreme demands on the implementation. For example, the graphical window-layout GUI system reliably responds to user input within one or two frame times, despite making use of assertion-based protocols; few things tend to change from frame to frame, unlike the animation-heavy platformer.</p><p id="x_10_3_0_0_4">The next-most-challenging case study from a concrete performance perspective is the TCP/IP stack. On a wired 100GB Ethernet, an IPv4 ICMP “ping” round trip between two Linux machines adjacent on the network takes ~0.4ms; the highly-optimized C-language Linux kernel TCP/IP stack is used at both ends of the link. Approximately the same round trip times are achieved if we replace the responding party's kernel-based IP stack with a simple C program responding to pings using the Linux <tt>packet(7)</tt> packet-capture mechanism. Switching to the <span class="small-caps">Syndicate/rkt</span> implementation of TCP/IP, by contrast, yields round trips of ~3.5ms, suggesting that it adds ~3ms of round trip latency. In a more realistic setting, pinging the same machine from a computer on the other side of the city (around ten network hops away), we see ~22ms round trips via the Linux kernel's IP stack and ~25ms via the <span class="small-caps">Syndicate/rkt</span> stack: the extra 3ms from <span class="small-caps">Syndicate</span> starts to look less significant in context of ordinary network conditions. The <span class="small-caps">Syndicate</span> DNS resolver, which I have used for my day-to-day browsing since 2012, is certainly not as quick as the system's own resolver, written in C; but the ~11ms of latency it introduces is barely noticeable in the context of day-to-day web browsing.</p></p><p id="x_11_3_0_0_26">
<h3 id="x_11_0_0_0_1"><a name="toc_11"></a><span class="counter chapter"><span>11</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:DISCUSSION"></a><a name="CHAP:DISCUSSION"></a>Discussion</span></h3><p id="x_11_0_0_0_2">Chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> sketched a map of the design space of concurrency models, placing each at a point in a multi-dimensional landscape. The chapter concluded with a discussion of the properties of an interesting point in that landscape. In this chapter I show that <span class="small-caps">Syndicate</span> uniquely occupies this point in the design space and that it offers linguistic support for each of the categories <a class="cross-reference" href="#c:conversation-size">C1</a><a class="cross-reference" href="#c:durability">C12</a> defining the dimensions of the space. I also make connections between <span class="small-caps">Syndicate</span> and areas of related work not examined in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a>. Finally, no design can be perfect for all scenarios; therefore, I conclude the chapter with a discussion of limitations of the <span class="small-caps">Syndicate</span> design and the dataspace model.</p>
<h4 id="x_11_1_0_0_1"><a name="toc_11.1"></a><span class="counter section"><span>11.1</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:Placing-PL-on-the-map"></a><a name="sec:Placing-PL-on-the-map"></a>Placing <span class="small-caps">Syndicate</span> on the map</span></h4><p id="x_11_1_0_0_2">Section <a class="cross-reference" href="#sec:Surveying-the-landscape">3.6</a> gave a collection of desiderata for a concurrency model, expressed in terms of characteristics <a class="cross-reference" href="#c:conversation-size">C1</a><a class="cross-reference" href="#c:durability">C12</a> described in section <a class="cross-reference" href="#sec:A-concurrency-design-landscape">3.1</a>. <span class="small-caps">Syndicate</span> satisfies each of the particulars listed. No other model discussed in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> manages to satisfy all at once, though the fact space model (section <a class="cross-reference" href="#sec:The-fact-space-model">3.5</a>) comes close. As discussed in section <a class="cross-reference" href="#sec:Syndicate's-approach-to-concurrency">2.5</a>, <span class="small-caps">Syndicate</span> is like an integration of the fact space model into a programming language design (as opposed to middleware) and goes beyond the fact space model in its strong epistemic focus and support for explicit representation of conversations, conversational frames, and conversational state.</p>
<figure id="x_11_1_0_0_4"><a name="fig:PL-chat-room-user-agent"></a>
<pre class="listing" id="x_11_1_0_0_3"><code>(define (user-agent name socket-id)
(assert (present name))
(on (message (tcp-in-line socket-id $line))
(send! (speak name line)))
(during (present $who)
(on-start (send! (tcp-out socket-id (format "~a arrived\n" who))))
(on-stop (send! (tcp-out socket-id (format "~a left\n" who))))
(on (message (speak who $text))
(send! (tcp-out socket-id (format "~a: ~a\n" who text))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>89</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PL-chat-room-user-agent"></a><span class="small-caps">Syndicate</span> chat room user agent<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_11_1_0_0_6"><a name="fig:complete-PL-chat-server"></a>
<pre class="listing" id="x_11_1_0_0_5"><code>#lang syndicate
(require/activate syndicate/drivers/tcp2)
(require racket/format)
(message-struct speak (who what))
(assertion-struct present (who))
(spawn #:name 'chat-server
(during/spawn (tcp-connection $id (tcp-listener 5999))
(assert (tcp-accepted id))
(define me (gensym 'user))
(assert (present me))
(on (message (tcp-in-line id $line))
(send! (speak me (bytes-&gt;string/utf-8 line))))
(during (present $user)
(on-start (send! (tcp-out id (string-&gt;bytes/utf-8 (~a user " arrived\n")))))
(on-stop (send! (tcp-out id (string-&gt;bytes/utf-8 (~a user " left\n")))))
(on (message (speak user $text))
(send! (tcp-out id (string-&gt;bytes/utf-8 (~a user ": " text "\n"))))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>90</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:complete-PL-chat-server"></a>A complete <span class="small-caps">Syndicate</span> TCP/IP chat server program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_11_1_0_0_7"> Each of the concurrency models of chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> was illustrated with an implementation of a portion of a running example, a toy “chat server”. Figure <a class="cross-reference" href="#fig:PL-chat-room-user-agent">89</a> gives a <span class="small-caps">Syndicate</span> equivalent at a similar level of abstraction. However, we do not have to be satisfied with pseudo-code: the real implementation is available to us. Figure <a class="cross-reference" href="#fig:complete-PL-chat-server">90</a> is a Racket source file that implements a complete TCP/IP chat server listening on port 5999. A fully-realized form of figure <a class="cross-reference" href="#fig:PL-chat-room-user-agent">89</a> appears within figure <a class="cross-reference" href="#fig:complete-PL-chat-server">90</a> as lines 1017.</p>
<div class="footnote" id="fn_11_124"><span class="counter footnote-counter"><span>124</span></span>Here we translate <span class="small-caps">Syndicate</span> assertions into messages sent via a non-<span class="small-caps">Syndicate</span> medium, the reverse of the situation discussed in example <a class="cross-reference" href="#example:sleep">8.17</a>.<span class="plain-layout-boundary"></span></div><p id="x_11_1_0_0_8">As the chat server program starts up, a single actor, <tt>chat-server</tt>, is created. It expresses interest in notifications of connections appearing on port 5999 (line 7). In response, the TCP driver activated on line 2 causes creation of a server socket listening on the specified port. If the <tt>chat-server</tt> actor were to terminate, the TCP driver would notice the drop in demand and stop accepting new connections. Each time a new connection arrives, an actor for the connection is <tt>spawn</tt>ed (line 7). The new actor signals the driver that the connection has been successfully accepted (line 8) and goes on to establish two related conversations. The first, lines 912, reacts to lines of input from the TCP socket, relaying them as <tt>speak</tt> messages to peers in the dataspace. The second, lines 1317, reacts to each separate user present in the space. As the actor learns that a new user exists, it sends a notification over TCP (line 14); when that user departs, it sends a matching notification (line 15).<label class="footnote-number" for="fn_11_124">124</label> While connected, anything that user says is prefixed with the user's name and delivered via TCP (lines 1617).</p><p id="x_11_1_0_0_9">The <span class="small-caps">Syndicate</span> program shown is superficially similar to the sketch of a fact space program shown in figure <a class="cross-reference" href="#fig:Factspace-style-chat-room">9</a> (page <a class="cross-reference pageref" href="#fig:Factspace-style-chat-room">&mdash;</a>). An immediate difference is that the <span class="small-caps">Syndicate</span> program uses <em>messages</em> for utterances of connected users, while the fact space program uses tuples, roughly analogous to assertions. A second difference is that no matter the cause, each facet of the <span class="small-caps">Syndicate</span> program retracts its assertions from the shared space as it terminates, where the fact space program only does the same if the connection to the tuplespace is broken or closed. Fact space actors joining and leaving conversations dynamically must keep track of their published resources by hand. A more subtle difference between the two programs is that the <span class="small-caps">Syndicate</span> program attends only to utterances from users who have explicitly marked themselves as present. The fact space sketch responds to <em>all</em> <tt>Message</tt> tuples, no matter the existence of a corresponding <tt>Presence</tt> tuple. To adapt the fact space sketch to be equivalent in this way to the <span class="small-caps">Syndicate</span> program, we would have to add additional book-keeping to track which users the actor knows to be present. To adapt the <span class="small-caps">Syndicate</span> program to be equivalent to the fact space program, however, all we would have to do is hoist the endpoint of lines 1617 above and outside the <tt>during</tt> clause of line 13, changing <tt>user</tt> to <tt>$user</tt> in the <tt>speak</tt> pattern. The alteration reflects a change in ontological relationship between <tt>present</tt> assertions and <tt>speak</tt> messages: after the change, the latter are no longer <em>framed</em> by the former.</p><p id="x_11_1_0_0_10">(<a class="cross-reference" href="#c:conversation-size">C1</a>; <a class="cross-reference" href="#c:demux">C2</a>; <a class="cross-reference" href="#c:data-to-control">C7</a>) Turning to the criteria described in section <a class="cross-reference" href="#sec:A-concurrency-design-landscape">3.1</a> (page <a class="cross-reference pageref" href="#sec:A-concurrency-design-landscape">&mdash;</a>), the dataspace model offers a single primitive mechanism that unifies one-to-one and many-to-many messaging and state exchange. <span class="small-caps">Syndicate</span> programmers design their assertions and messages to include correlation information that identifies relevant conversational context in domain-specific terms; because the language routes messages and assertions via pattern matching, the design directly supports arbitrary numbers of participants in a conversation. <span class="small-caps">Syndicate</span>'s facets provide the associated control structure and directly express the correspondence between protocol-level conversational context and actor-level control context. The assertions of interest in an event handler endpoint serve as the interface between data and control, demultiplexing incoming events to the correct facets and event handlers. <span class="small-caps">Syndicate</span> programmers use nested sub-facets to capture sub-conversations within conversational contexts. Nesting of facets reflects nesting of contexts and captures relationships of ontological dependency between a containing and a contained conversational frame.</p><p id="x_11_1_0_0_11">(<a class="cross-reference" href="#c:integration">C3</a>; <a class="cross-reference" href="#c:signalling">C4</a>) Endpoints allow arbitrary reactions to changes in the dataspace, but an important special case is to maintain a local copy of shared information. <span class="small-caps">Syndicate</span> includes <em>streaming query forms</em> which take on the task of integrating changes from the dataspace with the contents of local fields. Conversely, <span class="small-caps">Syndicate</span>'s assertion endpoints automatically transfer changes in local fields into the dataspace.</p><p id="x_11_1_0_0_12">(<a class="cross-reference" href="#c:integrity">C5</a>; <a class="cross-reference" href="#c:data-to-control">C7</a>; <a class="cross-reference" href="#c:control-to-data">C8</a>) <span class="small-caps">Syndicate</span> automatically maintains dataspace integrity in case of partial failure because its dataspaces offer a <em>set</em> view of a <em>bag</em> of assertions. When an actor fails or terminates, the dataspace removes all assertions belonging to the actor from the bag. If this affects the set perspective on the bag, then the dataspace notifies the remaining actors. This <em>fate-sharing</em> <span class="citation citep">(<a class="citation" id="cite-255" href="#bib-Clark1988">Clark 1988</a>)</span> of state and actor lifetime thus turns into a tool for maintaining application-level invariants. This idea extends beyond maintaining data invariants to maintaining <em>control</em> invariants. <span class="small-caps">Syndicate</span>'s <tt>during</tt> and <tt>during/spawn</tt> forms create and destroy facets in response to assertions appearing and disappearing; in turn, those created facets assert derived knowledge back into the dataspace and establish related subscriptions and event handlers. Each such facet exists only as long as the assertion that led to its creation. This allows the programmer to rely on invariants connecting presence of assertions in the dataspace with existence of matching facets in an actor. For example, in our chat server, programmers may straightforwardly ensure that every connected user has an asserted <tt>present</tt> tuple and every <tt>present</tt> tuple describes a connected user. Exceptions fit the model smoothly, because they cause actor termination, which retracts all active assertions.</p><p id="x_11_1_0_0_13">(<a class="cross-reference" href="#c:consistency">C6</a>) The core mechanism of the dataspace model, state replication over a lossless medium, offers an analog of <em>strong eventual consistency</em> <span class="citation citep">(<a class="citation" id="cite-256" href="#bib-Viotti2016">Viotti and Vukolić 2016</a>)</span> to the programmer. This allows reasoning about <em>common knowledge</em> <span class="citation citep">(<a class="citation" id="cite-257" href="#bib-Fagin2004">Fagin et al. 2004</a>)</span>. An actor maintaining some assertion knows both that interested peers learn of the assertion and that each such peer knows that all others learn of the assertion. By providing this guarantee at the language level, <span class="small-caps">Syndicate</span> lets programmers rely on this additional form of epistemic reasoning in their protocol designs.</p>
<div class="footnote" id="fn_11_125"><span class="counter footnote-counter"><span>125</span></span>Unlike traditional GC, this resource management strategy allows<em> synthesis</em> of resources merely by naming them!<span class="plain-layout-boundary"></span></div><p id="x_11_1_0_0_14">(<a class="cross-reference" href="#c:resources">C9</a>) <span class="small-caps">Syndicate</span> programs may react to retraction of assertions as well as their establishment. This allows interpretation of particular assertions as demand for some resource. The TCP driver is a clear example: it allocates and releases sockets to match <tt>tcp-connection</tt> assertions in the dataspace. This approach to resource management is a form of garbage collection where domain-specific descriptions of resources take the place of pointers, and resources are released once the last expression of interest in them disappears. As such, this idiom is frequently used in <span class="small-caps">Syndicate</span> programs.<label class="footnote-number" for="fn_11_125">125</label> Even service startup ordering problems can be solved in this way, interpreting interest in <em>service presence</em> <span class="citation citep">(<a class="citation" id="cite-258" href="#bib-Konieczny2009">Konieczny et al. 2009</a>)</span> as a request for service startup or shutdown.</p><p id="x_11_1_0_0_15">In section <a class="cross-reference" href="#sec:The-fact-space-model">3.5</a>, we discussed an enhancement to the running example where each user's presence record would also include a <em>status message</em>. Figure <a class="cross-reference" href="#fig:Aggregating-distinct-facts">10</a> (page <a class="cross-reference pageref" href="#fig:Aggregating-distinct-facts">&mdash;</a>) sketched the additional book-keeping required to track both presence and status of each user. The <span class="small-caps">Syndicate</span> equivalent makes use of the erasure of irrelevant information performed by the <span class="lyx-mathjax mathjax-inline">$\FINSTName$</span> metafunction (definition <a class="cross-reference" href="#def:mf:inst">5.24</a>):</p>
<div class="verbatim" id="x_11_1_0_0_17">
<pre class="verbatim" id="x_11_1_0_0_16"><code>(during (present $who _)
(on-start (send! (tcp-out socket-id (format "~a arrived\n" who))))
(on-stop (send! (tcp-out socket-id (format "~a left\n" who)))))
(on (asserted (present $who $status))
(send! (tcp-out socket-id (format "~a status: ~a\n" who status))))
</code></pre></div>
<div class="footnote" id="fn_11_126"><span class="counter footnote-counter"><span>126</span></span>This unit-testing facility is a contribution of my colleague Sam Caldwell.<span class="plain-layout-boundary"></span></div><p id="x_11_1_0_0_18">(<a class="cross-reference" href="#c:debuggability">C10</a>) As we saw in section <a class="cross-reference" href="#sec:Programming-tools">7.4</a>, <span class="small-caps">Syndicate</span> implementations can capture program traces in terms of the actions and events of the underlying dataspace model. These traces can then be visualized in various ways, yielding insight into system state and activity. Similar trace information acts as the basis of an experimental unit-testing facility,<label class="footnote-number" for="fn_11_126">126</label> where executable specifications of expected behavior in terms of patterns over traces run alongside the program under test, signaling an error if an unwanted interaction is discovered.</p><p id="x_11_1_0_0_19">(<a class="cross-reference" href="#c:evolvability">C11</a>) <span class="small-caps">Syndicate</span>'s facets and fields allow easy addition of new conversations and conversational state to an existing actor without affecting other conversations that actor might be engaged in. In <span class="small-caps">Syndicate/rkt</span>, Racket's own abstraction facilities (procedures and macros) allow programmers to extract facets into reusable chunks of functionality, allowing “mixin” style augmentation of an actor's behavior. When it comes to altering a <em>conversation</em> to include more or fewer participants, programmers adjust their protocol definitions—if required. A protocol's schema may allow participants to freely express interest in certain assertions. Where such expressions of interest would interfere, however, the protocol must be revised, and the corresponding facets of actors must be updated to match. However, such changes are local to the facets concerned and do not affect neighboring facets.</p><p id="x_11_1_0_0_20">(<a class="cross-reference" href="#c:durability">C12</a>) Finally, tighter integration of <span class="small-caps">Syndicate</span> with existing experimental support for reloading of Racket modules is future work. Experience thus far is that the combination is promising: a <span class="small-caps">Syndicate</span> protocol for describing the availability of new code allows actors to serialize their own state and pass it to their post-upgrade replacements. <span class="citation citet"><a class="citation" id="cite-259" href="#bib-Felleisen1988a"><span>Felleisen et al.<span class="parens"> (</span>1988<span class="parens">)</span></span></a></span> raise the idea of abstract representations of continuations—that is, of ongoing tasks. It may be promising to explore this idea in the setting of serialization of actor state, since it may have benefits for code upgrade, orthogonal persistence, and program state visualization.</p>
<h4 id="x_11_2_0_0_1"><a name="toc_11.2"></a><span class="counter section"><span>11.2</span></span><span class="heading-text section">Placing <span class="small-caps">Syndicate</span> in a wider context</span></h4><p id="x_11_2_0_0_2">The map of concurrency-model design space sketched in chapter <a class="cross-reference" href="#CHAP:APPROACHES-TO-COORDINATION">3</a> introduced many ideas, languages, designs and systems related to <span class="small-caps">Syndicate</span>. Here, we touch on other inspirational and related work. In particular, <span class="small-caps">Syndicate</span> and the underlying dataspace model invite comparison to general techniques for functional I/O as well as to process calculi, actor-based models of concurrency, and messaging middleware.</p>
<h5 id="x_11_2_1_0_1"><a name="toc_11.2.1"></a><span class="counter subsection"><span>11.2.1</span></span><span class="heading-text subsection">Functional I/O</span></h5><p id="x_11_2_1_0_2">Communication is intrinsically effectful. As a result, designers of functional languages <span class="citation citep">(<a class="citation" id="cite-260" href="#bib-PeytonJones2010">Peyton Jones 2001</a>; <a class="citation" id="cite-261" href="#bib-Felleisen2009">Felleisen et al. 2009</a>)</span> have been faced with the challenge of reconciling effectful with pure programming when extending their ideas to functional <em>systems</em>.</p>
<h6 class="unnumbered" id="x_11_2_1_0_3"><a name="toc_11.2.1"></a><span class="heading-text paragraph">Worlds and Universes.</span></h6><p id="x_11_2_1_0_4"><span class="citation cite"><a class="citation" id="cite-262" href="#bib-Felleisen2009"><span>Felleisen et al.<span class="parens"> (</span>2009<span class="parens">)</span></span></a></span> propose <em>Worlds</em>, one of the roots of this work. A World is a context within which a functional program responds to a fixed set of events chosen for teaching novice programmers. Concurrency is inherent in the model; the user's actions are interleaved with other events occurring in the system, making concurrency an integral part of the design process. The following sample World maintains a counter, incremented as time passes, that is reset on key-press and drawn to the screen each time it changes:</p>
<div class="verbatim" id="x_11_2_1_0_6">
<pre class="verbatim" id="x_11_2_1_0_5"><code>(big-bang 0 [on-tick (lambda (i) (+ i 1))]
[on-key (lambda (i k) 0)]
[to-draw (lambda (i) (text (~a i) 20 "black"))])
</code></pre></div><p id="x_11_2_1_0_7">A World program is neither continuation-passing-style nor monadic. Rather than composing chains of sequential actions, the programmer focuses on formulating responses to asynchronous events. In this context, the programmer must keep in mind that the event following an action is not knowable.</p>
<div class="lyx-mathjax mathjax-definitions" id="x_11_2_1_0_8">\(\newcommand{\WorldState}{\mathit{WorldState}}
\)</div><p id="x_11_2_1_0_10">Despite their concurrency, Worlds yield a functional model of I/O, since each transition function reacting to events is pure. Each transition function has roughly the type
<div class="lyx-mathjax mathjax-display" id="x_11_2_1_0_9">\[
\WorldState\times\mathit{Event}\rightarrow\WorldState\times\mathit{Actions}
\]
</div>sometimes omitting the <span class="lyx-mathjax mathjax-inline">$\mathit{Event}$</span> input or <span class="lyx-mathjax mathjax-inline">$\mathit{Actions}$</span> output. The insight that the specific details of each transition function's type signature can be generalized into instantiations of this general signature was one of the steps that led to Network Calculus and the dataspace model. Furthermore, the “operating system” underpinning a particular World keeps track of its state between invocations of transition functions; this, too, was early inspiration for Network Calculus. The behavior of a World program is all possible functional compositions of its event handlers with appropriate streams of events, again directly comparable to Network Calculus and the dataspace model.</p><p id="x_11_2_1_0_11">World programs compose to form a <em>Universe</em>, communicating in a strict hub-and-spoke topology. Though each World runs in parallel with its neighbors in the Universe, Worlds are themselves single-threaded and cannot create or destroy Worlds dynamically. When Worlds fail, the hub is informed of their disappearance. The dataspace model can be seen as a generalization of this structure that also recursively demotes each Universe to a mere World in some larger Universe.</p><p id="x_11_2_1_0_12">Worlds and Universes suffice for teaching novices, but they do not scale to “real” software. Following Hudak and Sundaresh in evaluating functional approaches to I/O <span class="citation citep">(<a class="citation" id="cite-263" href="#bib-Hudak1988">Hudak and Sundaresh 1988</a>)</span>, we see that World programs enjoy good support for equational reasoning and interactive use but have only limited support for handling error situations. Furthermore, the fixed set of events offered to Worlds, the strictness of the communications topology, and the associated concurrency model in Universes impose serious restrictions that are lifted by the design of the dataspace model.</p>
<h6 class="unnumbered" id="x_11_2_1_0_13"><a name="toc_11.2.1"></a><span class="heading-text paragraph">Monadic I/O.</span></h6><p id="x_11_2_1_0_14"><span class="citation citet"><a class="citation" id="cite-264" href="#bib-PeytonJones1993"><span>Peyton Jones and Wadler<span class="parens"> (</span>1993<span class="parens">)</span></span></a></span> propose <em>monadic I/O</em>, famously and successfully subsequently incorporated into Haskell <span class="citation citep">(<a class="citation" id="cite-265" href="#bib-PeytonJones2010">Peyton Jones 2001</a>)</span>. The monadic approach to combination of functional programming and effectful programming is to reify side-effecting operations as values, and to use monadic type structure to enforce correct sequencing and other constraints on interpretation of these effect values. While a number of benefits flow from this design, there is a tendency for the resulting monads to mimic the familiar concepts, style, and techniques of imperative programming languages. For example, Haskell uses its monadic I/O facility to offer the programmer exceptions, mutable reference cells, threads, locks, file handles and so forth. These are accessed via <em>procedure calls</em> that can often be directly mapped to similar procedures in imperative languages.</p><p id="x_11_2_1_0_15">The dataspace model shares the notion of reification of actions with the monadic approach. However, it differs strongly in two respects. First, it is event-based. The monadic model directly parallels traditional approaches to input, including blocking actions, callbacks and events. Second, the dataspace model uses a single language of general-purpose actions—state change notifications and messages—as a <em>lingua franca</em> through which many disparate protocols are expressed. The monadic approach uses many different monadic languages and interpreters. For example, Haskell's <tt>IO</tt> monad includes special-purpose representations for a fixed, large suite of actions, while the dataspace model offers only message- and assertion-based information exchange, and expects neighboring actors to interpret encoded descriptions of actions relayed via messages and assertions. On the one hand, the dataspace approach is modularly extensible, but on the other hand, it limits itself to a single form of interactivity, whereas monadic type structure can be used to encode a wide range of effects.</p>
<h6 class="unnumbered" id="x_11_2_1_0_16"><a name="toc_11.2.1"></a><span class="heading-text paragraph">Concurrent ML.</span></h6><p id="x_11_2_1_0_17">CML <span class="citation citep">(<a class="citation" id="cite-266" href="#bib-Reppy1991">Reppy 1991</a>; <a class="citation" id="cite-267" href="#bib-Reppy1999">Reppy 1999</a>)</span> is a combinator language for coordinating I/O and concurrency, available in SML/NJ and Racket <span class="citation citep">(<a class="citation" id="cite-268" href="#bib-plt-tr1">Flatt and PLT 2010</a> <span class="citation-after">version 6.2.1, S11.2.1</span>)</span>. CML uses synchronous channels to coordinate preemptively-scheduled threads in a shared-memory environment. Like <span class="small-caps">Syndicate</span>, CML treats I/O, communication, and synchronization uniformly. In contrast to <span class="small-caps">Syndicate</span>, CML is at heart <em>transactional</em>. Where CML relies on garbage collection of threads and explicit “abort” handlers to release resources involved in rolled-back transactions, <span class="small-caps">Syndicate</span> monitors assertions of interest to detect situations when a counterparty is no longer interested in the outcome of a particular action. CML's threads inhabit a single, unstructured shared-memory space; it has no equivalent of <span class="small-caps">Syndicate</span>'s process isolation and layered media.</p>
<h5 id="x_11_2_2_0_1"><a name="toc_11.2.2"></a><span class="counter subsection"><span>11.2.2</span></span><span class="heading-text subsection">Functional operating systems</span></h5><p id="x_11_2_2_0_2">The dataspace model harks back to early research on functional operating systems <span class="citation citep">(<a class="citation" id="cite-269" href="#bib-Henderson1982">Henderson 1982</a>; <a class="citation" id="cite-270" href="#bib-Stoye1986">Stoye 1986</a>)</span>, as it is literally a message-based functional OS for coordinating concurrent components “in the large”. <span class="citation citet"><a class="citation" id="cite-271" href="#bib-Hudak1988"><span>Hudak and Sundaresh<span class="parens"> (</span>1988<span class="parens">)</span></span></a></span> survey approaches to functional I/O; the dataspace model is distantly related to their “stream-based I/O” formulation. They suggest that a functional I/O system should provide support for (1) equational reasoning, (2) efficiency, (3) interactivity, (4) extensibility, and (5) handling of “anomalous situations,” or errors.</p>
<h6 class="unnumbered" id="x_11_2_2_0_3"><a name="toc_11.2.2"></a><span class="heading-text paragraph">Equational reasoning.</span></h6><p id="x_11_2_2_0_4">Like Worlds and Universes, the dataspace model allows for equational reasoning because event handlers are functional state transducers. When side-effects are absolutely required, they can be encapsulated in a process, limiting their scope. The state of the system as a whole can be partitioned into independent processes, allowing programmers to avoid global reasoning when designing and unit-testing their code <span class="citation citep">(<a class="citation" id="cite-272" href="#bib-Eastlund2009">Eastlund and Felleisen 2009</a>; <a class="citation" id="cite-273" href="#bib-Sullivan1990">Sullivan and Notkin 1990</a>)</span>.</p>
<h6 class="unnumbered" id="x_11_2_2_0_5"><a name="toc_11.2.2"></a><span class="heading-text paragraph">Efficiency.</span></h6><p id="x_11_2_2_0_6">A functional implementation of a dataspace manages both its own state and the state of its contained processes in a linear way. Hudak and Sundaresh, discussing their “stream” model of I/O, remark that the state of their kernel “is a single-threaded object, and so can be implemented efficiently”. The dataspace model shares this advantage with streams.</p><p id="x_11_2_2_0_7">There are no theoretical obstacles to providing more efficient and scalable implementations of the core dataspace model abstractions. Siena <span class="citation citep">(<a class="citation" id="cite-274" href="#bib-Carzaniga2000">Carzaniga, Rosenblum and Wolf 2000</a>)</span> and Hermes <span class="citation citep">(<a class="citation" id="cite-275" href="#bib-Pietzuch2002">Pietzuch and Bacon 2002</a>)</span> both use subscription and advertisement information to construct efficient routing <em>trees</em>. Using a similar technique for dataspace implementation would permit scale-out of the corresponding layer without changing any code in application processes.</p>
<h6 class="unnumbered" id="x_11_2_2_0_8"><a name="toc_11.2.2"></a><span class="heading-text paragraph">Interactivity.</span></h6><p id="x_11_2_2_0_9">The term “interactivity” in this context relates to the ability of the system to interleave communication and computation with other actors in the system, and in particular to permit user actions to affect the evolution of the system. The dataspace model naturally satisfies this requirement because all processes are concurrently-evolving, communicating entities.</p>
<h6 class="unnumbered" id="x_11_2_2_0_10"><a name="toc_11.2.2"></a><span class="heading-text paragraph">Extensibility.</span></h6><p id="x_11_2_2_0_11">The dataspace model is extensible in that the ground dataspace multiplexes raw Racket events without abstracting away from them. Hence, driver processes can be written to adapt the system to any I/O facilities that Racket offers in the future. The collection of request and response types for the “stream” model given by Hudak and Sundaresh <span class="citation citep">(<a class="citation" id="cite-276" href="#bib-Hudak1988">Hudak and Sundaresh 1988</a> <span class="citation-after">section 4.1</span>)</span> is static and non-extensible because their operating system is monolithic, with device drivers baked in to the kernel. On the one hand, monolithicity means that the possible communication failures are obvious from the set of device drivers available; on the other hand, its simplistic treatment of user-to-driver communication means that the system cannot express the kinds of failures that arise in microkernel or distributed systems. Put differently, a monolithic stream system is not suitable for a functional approach to systems programming.</p><p id="x_11_2_2_0_12">The dataspace model action type (figure <a class="cross-reference" href="#fig:DS-program-syntax">12</a>) appears to block future extensions because it consists of a finite set of variants. This appearance is deceiving. Actions are merely the interface between a program and its context. Extensibility is due to the information exchanged between a program and its peers. In other words, the action type is similar to the limited set of core forms in the lambda calculus, the limited set of methods in HTTP and the handful of core system calls in Unix: a finite kernel generating an infinite spectrum of possibilities.</p>
<h6 class="unnumbered" id="x_11_2_2_0_13"><a name="toc_11.2.2"></a><span class="heading-text paragraph">Errors.</span></h6><p id="x_11_2_2_0_14">In distributed systems, a request can fail in two distinct ways. Some “failures” are successful communications with a service, which just happens to fail at some requested task; but some failures are caused by the unreachability of the service requested. <span class="small-caps">Syndicate</span> represents the former kind of failure via protocols capable of expressing error responses to requests. For the latter kind of failure, it uses assertions as presence information to detect unavailability and crashes.</p>
<h5 id="x_11_2_3_0_1"><a name="toc_11.2.3"></a><span class="counter subsection"><span>11.2.3</span></span><span class="heading-text subsection">Process calculi</span></h5><p id="x_11_2_3_0_2">A major family of concurrency models is based on <span class="lyx-mathjax mathjax-inline">$\pi$</span>-calculus <span class="citation citep">(<a class="citation" id="cite-277" href="#bib-Milner1992">Milner, Parrow and Walker 1992</a>)</span> and its many derivatives.</p>
<h6 class="unnumbered" id="x_11_2_3_0_3"><a name="toc_11.2.3"></a><span class="heading-text paragraph">The Conversation Calculus.</span></h6><p id="x_11_2_3_0_4">Spiritually closest to the dataspace model is the Conversation Calculus <span class="citation citep">(<a class="citation" id="cite-278" href="#bib-Caires2010">Caires and Vieira 2010</a>; <a class="citation" id="cite-279" href="#bib-Vieira2008">Vieira, Caires and Seco 2008</a>)</span>, based on <span class="lyx-mathjax mathjax-inline">$\pi$</span>-calculus. Its <em>conversational contexts</em> scope multi-party interactions. Named contexts nest hierarchically, forming a tree. Processes running within a context may communicate with others in the same context and processes running in their context's immediate container. Contexts on distinct tree branches may share a name and thus connect transparently through hyperlinks. The Conversation Calculus also provides a Lisp-style <tt>throw</tt> facility that aborts to the closest <tt>catch</tt> clause. This mechanism enables supervisor-like recovery strategies for exceptions.</p><p id="x_11_2_3_0_5">Although the Conversation Calculus and the dataspace model serve different goals—the former is a calculus of services while the latter is the core of a language design—the two are similar. Like a dataspace, a conversational context has both a spatial meaning as a location for computation and a behavioral meaning as a delimiter for a session or protocol instance. Both models permit communication <em>within</em> their respective kinds of boundary as well as <em>across</em> them.</p><p id="x_11_2_3_0_6">The two models starkly differ in two aspects. First, the dataspace model cannot <em>transparently</em> link subnets into logical overlay networks because its actors are nameless. Instead, inter-subnet routing has to be implemented in an explicit manner, based on state-change notifications. Proxy actors tunnel events and actions across links between subnets; once such a link is established, actors may ignore the actual route. Any implementation of Conversation Calculus must realize just such routing <em>within</em> the implementation; the dataspace model provides the same expressiveness as a library feature <em>external</em> to the implementation.</p><p id="x_11_2_3_0_7">Second, Conversation Calculus lacks state-change notifications and does not automatically signal peers when conversations come to an end—normally or through failure. Normal termination in Conversation Calculus is a matter of convention, while exceptions signal failure to containing contexts but <em>not</em> to remote participants in the conversational context. In contrast, the state-change notification events of the dataspace model signal failure to all interested parties transparently.</p>
<h6 class="unnumbered" id="x_11_2_3_0_8"><a name="toc_11.2.3"></a><span class="heading-text paragraph">Mobile Ambients.</span></h6><p id="x_11_2_3_0_9"><span class="citation cite"><a class="citation" id="cite-280" href="#bib-Cardelli2000a"><span>Cardelli and Gordon<span class="parens"> (</span>2000<span class="parens">)</span></span></a></span> describe the <em>Mobile Ambient Calculus</em>. An <em>ambient</em> is a nestable grouping of processes, an “administrative domain” within which computation and communication occur.</p><p id="x_11_2_3_0_10">At first glance, Mobile Ambients and the dataspace model are duals. While the dataspace model focuses on routing data between domains, from which code mobility can be derived via encodings, Mobile Ambients derives message routing by encoding it in terms of a primitive notion of process mobility. By restricting ourselves to transporting <em>data</em> rather than <em>code</em> from place to place, we avoid a large class of mobility-related complication and closely reflect real networks, which transport only first-order data. Moving higher-order data (functions, objects) happens via encodings. Furthermore, mobility of code is inherently point-to-point, and the <span class="lyx-mathjax mathjax-inline">$\pi$</span>-calculus-like names attached to ambients reflect this fact. <span class="small-caps">Syndicate</span>'s pattern-based routing is a natural fit for a more general class of conversational patterns in which duplication of messages is desired.</p>
<h5 id="x_11_2_4_0_1"><a name="toc_11.2.4"></a><span class="counter subsection"><span>11.2.4</span></span><span class="heading-text subsection">Formal actor models</span></h5><p id="x_11_2_4_0_2">Another major family of concurrency models has its roots in the actor model of Hewitt and others <span class="citation citep">(<a class="citation" id="cite-281" href="#bib-Hewitt1973">Hewitt, Bishop and Steiger 1973</a>; <a class="citation" id="cite-282" href="#bib-Agha1997">Agha et al. 1997</a>; <a class="citation" id="cite-283" href="#bib-DeKoster2016b">De Koster, Van Cutsem and De Meuter 2016</a>)</span>. A particularly influential branch of the family, having some similarities to the dataspace model, is due to Agha and colleagues <span class="citation citep">(<a class="citation" id="cite-284" href="#bib-Agha1997">Agha et al. 1997</a>; <a class="citation" id="cite-285" href="#bib-Callsen1994">Callsen and Agha 1994</a>; <a class="citation" id="cite-286" href="#bib-Varela1999">Varela and Agha 1999</a>)</span>.</p><p id="x_11_2_4_0_3">Varela and Agha's variation on the actor model <span class="citation citep">(<a class="citation" id="cite-287" href="#bib-Varela1999">Varela and Agha 1999</a>)</span> groups actors into hierarchical <em>casts</em> via <em>director</em> actors, which control some aspects of communication between their casts and other actors. If multicast is desired, it must be explicitly implemented by a director. While casts and directors have some semblance to the layered dataspace model, the two differ in many aspects. The availability of publish/subscribe to dataspace actors automatically provides multicast without forcing all members of a layer to use the same conversational pattern. Directors are computationally active, but dataspaces are not. In their place, the dataspace model employs <em>relay actors</em> that connect adjacent layers. Finally, Varela and Agha's system lacks state-change notification events and thus cannot deal with failures easily. They propose mobile <em>messenger</em> actors for localizing failure instead.</p><p id="x_11_2_4_0_4">In Callsen and Agha's ActorSpace <span class="citation citep">(<a class="citation" id="cite-288" href="#bib-Callsen1994">Callsen and Agha 1994</a>)</span> actors join and leave <em>actorspaces</em>. Each actorspace provides a scoping mechanism for pattern-based multicast and anycast message delivery. Besides communication via actorspace, a separate mechanism exists to let actors address each other directly. In contrast, <span class="small-caps">Syndicate</span> performs all communication with interest-based routing and treats dataspaces as specialized actors, enforcing abstraction boundaries and making it impossible to distinguish between a single actor or an entire dataspace providing some service. Actors may join multiple actorspaces, whereas dataspace model actors may only inhabit a single dataspace, reflecting physical and logical layering and giving an account of locality. In the dataspace model, actors “join” multiple dataspaces by spawning proxy actors, which tunnel events and actions through intervening layered dataspaces. Finally, ActorSpace does not specify a failure model, whereas dataspaces signal failure with state-change notification events.</p><p id="x_11_2_4_0_5"><span class="citation cite"><a class="citation" id="cite-289" href="#bib-Peschanski2007"><span>Peschanski et al.<span class="parens"> (</span>2007<span class="parens">)</span></span></a></span> describe an actor-style system with multicast channels connecting actors, but do not consider layering of actor locations. They consider link failure, channel failure and location failure as distinct concepts, whereas the dataspace model unifies all of these in the state-change event mechanism. They describe their multicast routing technique as “additive”, comparing to the “subtractive” discard-relation-based technique of <span class="citation citet"><a class="citation" id="cite-290" href="#bib-Ene2001"><span>Ene and Muntean<span class="parens"> (</span>2001<span class="parens">)</span></span></a></span>. The formal model of dataspaces is a hybrid of additive and subtractive: actors are grouped in a dataspace, providing a crisp scope for broadcast, within which a discard-like subtractive operation is applied.</p><p id="x_11_2_4_0_6"><span class="citation cite"><a class="citation" id="cite-291" href="#bib-Fiege2002"><span>Fiege et al.<span class="parens"> (</span>2002<span class="parens">)</span></span></a></span> consider <em>scoping</em> of actors. Their notion of actor visibility differs from ours: dataspace model actors explicitly route messages and presence between layers using <span class="lyx-mathjax mathjax-inline">$\Out{\cdot}$</span> and friends, whereas their actors are automatically visible to all other actors having a common super-scope. Their scopes form a directed acyclic graph rather than a tree, whereas dataspace layering is strictly tree-like. Their <em>event mappings</em> are similar in function to relay actors in dataspace model programs, translating between protocols at adjacent layers.</p><p id="x_11_2_4_0_7">Finally, actor models to date lack an explicit interface to the outside world. I/O remains a brute-force side-effect instead of a messaging mechanism. The functional approach to messaging and recursive layers of the dataspace model empowers us to treat this question as an implementation decision.</p>
<h5 id="x_11_2_5_0_1"><a name="toc_11.2.5"></a><span class="counter subsection"><span>11.2.5</span></span><span class="heading-text subsection">Messaging middleware</span></h5><p id="x_11_2_5_0_2">A comparison of <span class="small-caps">Syndicate</span> with publish/subscribe brokers <span class="citation citep">(<a class="citation" id="cite-292" href="#bib-Eugster2003">Eugster et al. 2003</a>)</span> supplies an additional perspective. Essentially, a dataspace corresponds to a broker: the subset of assertions declaring interests is the subscription table of a broker; the event and action queues at each actor are broker “queues”; characteristic protocols are used for communication between parties connected to a broker; etc. In short, the dataspace model can be viewed as a formal semantics of brokers. The <span class="small-caps">Syndicate/rkt</span> “broker” actor (appendix <a class="cross-reference" href="#APPENDIX:POLYGLOT">C</a>) exposes a WebSocket-based protocol connecting <span class="small-caps">Syndicate/rkt</span> programs with <span class="small-caps">Syndicate/js</span> programs running in the browser, taking an important first step toward investigation of <span class="small-caps">Syndicate</span> in a distributed setting.</p>
<h4 id="x_11_3_0_0_1"><a name="toc_11.3"></a><span class="counter section"><span>11.3</span></span><span class="heading-text section"><a class="label-anchor" href="#sec:limitations"></a><a name="sec:limitations"></a>Limitations and challenges</span></h4><p id="x_11_3_0_0_2">As we have seen, <span class="small-caps">Syndicate</span> is able to succinctly express solutions to a wide range of concurrency and coordination problems. However, it also suffers from weaknesses in addressing others. In this section, we explore some of the challenges to the dataspace model and the <span class="small-caps">Syndicate</span> language.</p>
<h6 class="unnumbered" id="x_11_3_0_0_3"><a name="toc_11.3"></a><span class="heading-text paragraph"><a class="label-anchor" href="#par:Firewalls"></a><a name="par:Firewalls"></a>Security properties.</span></h6><p id="x_11_3_0_0_4">Imagine a <span class="small-caps">Syndicate</span> encoding of the traditional actor model, where each actor knows its own identity and communications are conveyed as messages carrying tuples <span class="lyx-mathjax mathjax-inline">$(\mathit{id},\mathit{payload})$</span>. An actor with id <span class="lyx-mathjax mathjax-inline">$x$</span> would assert <span class="lyx-mathjax mathjax-inline">$?(x,\star)$</span> in order to receive messages addressed to it; a peer <span class="lyx-mathjax mathjax-inline">$y$</span> would send messages <span class="lyx-mathjax mathjax-inline">$\langle x,\mathtt{"hello"}\rangle$</span>. However, nothing in the dataspace model prevents <span class="lyx-mathjax mathjax-inline">$y$</span>, upon learning the name <span class="lyx-mathjax mathjax-inline">$x$</span>, expressing interest <span class="lyx-mathjax mathjax-inline">$?(x,\star)$</span> itself, thereby receiving a carbon-copy of all messages addressed to <span class="lyx-mathjax mathjax-inline">$x$</span>. To prevent this, some notion of <em>permissible assertions</em> for a given actor must be brought to bear.</p>
<div class="lyx-mathjax mathjax-definitions" id="x_11_3_0_0_5">\(\newcommand{\FFW}{f_{\mathit{fw}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_11_3_0_0_6">\(\newcommand{\FINNER}{f_{\mathit{inner}}}
\)</div>
<div class="lyx-mathjax mathjax-definitions" id="x_11_3_0_0_7">\(\newcommand{\FIREWALL}[2]{\mathit{firewall}\;#1\;#2}
\)</div>
<figure id="x_11_3_0_0_9"><a name="fig:Firewalling-dataspace-model"></a>
<div class="lyx-mathjax mathjax-display" id="x_11_3_0_0_8">\begin{align*}
\FFW &amp; :\forall\tau.(\TASet\times\TBehF{\tau}\rightarrow\TBehF{\tau})\\
\FFW\ \ROUTES\ \FINNER\;e\;u &amp; =\begin{cases}
\EXIT{\VECOF{\FIREWALL{\ROUTES}a}} &amp; \text{if }\FINNER\;e\;u=\EXIT{\VECOF a}\\
\CONTINUE{\VECOF{\FIREWALL{\ROUTES}a},u'} &amp; \text{if }\FINNER\;e\;u=\CONTINUE{\VECOF a,u'}
\end{cases}\\
\\
\FIREWALL{\ROUTES}{\AMsg c} &amp; =\begin{cases}
\AMsg c &amp; \text{if }c\in\ROUTES\\
\cdot &amp; \text{otherwise}
\end{cases}\\
\FIREWALL{\ROUTES}{\CPatch{\ROUTESADD}{\ROUTESDEL}} &amp; =\CPatch{\ROUTESADD\cap\ROUTES}{\ROUTESDEL\cap\ROUTES}\\
\FIREWALL{\ROUTES}{\left(\AActor{\CBoot}{\ROUTES'}\right)} &amp; =\AActor{f'}{\left(\ROUTES'\cap\ROUTES\right)}\\
\text{where }f'=\lambda(). &amp; \begin{cases}
\INIT{\VECOF{\FIREWALL{\ROUTES}a},\CBehPack{\tau}{\FFW\,\ROUTES\,f''}u} &amp; \text{if }\CBoot()=\INIT{\VECOF a,\CBehPack{\tau}{f''}u}\\
\EXIT{\VECOF{\FIREWALL{\ROUTES}a}} &amp; \text{if }\CBoot()=\EXIT{\VECOF a}
\end{cases}\\
\FIREWALL{\ROUTES}{\left(\ADS{\VECOF P}\right)} &amp; =\ADS{\left(\VECOF{\FIREWALL{\ROUTES}P}\right)}
\end{align*}
</div><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>91</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Firewalling-dataspace-model"></a>“Firewalling” dataspace model actors<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_11_3_0_0_11">Placing a trusted <em>firewall</em> between an untrusted actor and its dataspace can be used to enforce limits on the assertions made by an actor and its potential children. Key to the idea is that actor behaviors in the dataspace model are mere functions, opening the possibility of writing functions to <em>filter</em> the action and event streams traveling to and from an actor's behavior. In terms of the dataspace model formalism, a firewall can be as simple as shown in figure <a class="cross-reference" href="#fig:Firewalling-dataspace-model">91</a>. The real <span class="small-caps">Syndicate/rkt</span> implementation is scarcely more complex. Use of a firewall to isolate untrustworthy actors such as <span class="lyx-mathjax mathjax-inline">$y$</span> can thus restore the security properties of the actor model. If our actor <span class="lyx-mathjax mathjax-inline">$y$</span>, supposed to receive only messages addressed to <span class="lyx-mathjax mathjax-inline">$id_{y}$</span>, is spawned with an action <span class="lyx-mathjax mathjax-inline">$P_{y}$</span>, we can enforce its good behavior by interpreting
<div class="lyx-mathjax mathjax-display" id="x_11_3_0_0_10">\[
\FIREWALL{\left(\left(\left(\star,\star\right)-\;\Obs{\left(\star,\star\right)}\right)\cup\;\Obs{\left(id_{y},\star\right)}\right)}{P_{y}}
\]
</div>instead of <span class="lyx-mathjax mathjax-inline">$P_{y}$</span> itself. It remains future work to more closely integrate access controls with the dataspace model. Preliminary work toward a type system for the dataspace model also suggests that static enforcement of some of these properties is possible <span class="citation citep">(<a class="citation" id="cite-293" href="#bib-Caldwell2017">Caldwell, Garnock-Jones and Felleisen 2017</a>)</span>.</p>
<h6 class="unnumbered" id="x_11_3_0_0_12"><a name="toc_11.3"></a><span class="heading-text paragraph">Locks and mutual exclusion.</span></h6>
<div class="footnote" id="fn_11_127"><span class="counter footnote-counter"><span>127</span></span>This property of tuples is known as “generativity” in the literature <span class="citation citep">(<a class="citation" id="cite-294" href="#bib-Gelernter1985">Gelernter 1985</a> <span class="citation-after">section 2, p. 82</span>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_11_3_0_0_13">Programs such as Dijkstra's “dining philosophers” require <em>locks</em> for controlling access to a shared, scarce resource. In the shared-memory concurrency model, <em>semaphores</em> act as such locks. Performing a “down” operation on a semaphore is interpreted as claiming a resource; the corresponding “up” operation signifies resource release. The tuplespace model is able to implement the necessary mutual exclusion by assigning a specific tuple in the store as a quasi-physical representative of a lock. As tuples <em>move</em> from place to place, each tuple having an independent lifetime, the notion of a current <em>holder</em> of a tuple makes sense.<label class="footnote-number" for="fn_11_127">127</label> The locking protocol for a tuplespace, then, is to perform an <tt>out(lock)</tt> action to initialize the lock to its unlocked state, to perform <tt>in(lock)</tt> to claim the lock, and to release it by once more performing <tt>out(lock)</tt>. The actor model and other message-passing models must choose some other strategy, lacking shared state entirely; a common solution there is to <em>reify</em> a lock as an actor mediating access to the contested resource.</p>
<div class="footnote" id="fn_11_128"><span class="counter footnote-counter"><span>128</span></span>At heart, this problem is about <em>atomic transfer of ownership</em> of some resource. Interestingly, no realizable electronic computer network has any means of expressing such transfers. The actor model and <span class="small-caps">Syndicate</span> both share this characteristic with such physical networks. This raises questions as to whether tuplespaces can be implemented “primitively” at all, or whether they must always be encoded in terms of some underlying message-passing system.<span class="plain-layout-boundary"></span></div>
<div class="footnote" id="fn_11_129"><span class="counter footnote-counter"><span>129</span></span>Erlang can use exit signals to achieve a similar outcome, as can other actor languages with an analogous construct. Various suggestions have been made to overcome the “lost tuple” problem in tuplespace languages <span class="citation citep">(<a class="citation" id="cite-295" href="#bib-Bakken1995">Bakken and Schlichting 1995</a>)</span>.<span class="plain-layout-boundary"></span></div><p id="x_11_3_0_0_14"><span class="small-caps">Syndicate</span>'s dataspaces are in some ways quite similar to tuplespaces. A key difference is that <span class="small-caps">Syndicate</span> assertions do not have the independent existence of tuples: multiple independent assertions of the same value cannot be distinguished from just one, and any observers expressing interest in a given assertion <em>all</em> receive updates regarding its presence in the dataspace. There is therefore no way for <span class="small-caps">Syndicate</span>'s assertion-manipulation primitives to directly implement locking or mutual exclusion; the dataspace itself is not stateful in the right way. However, borrowing from the actor model, an <em>indirect</em> implementation of locking is perfectly possible, as we have seen already in figure <a class="cross-reference" href="#fig:Semaphore-protocol">35</a>.<label class="footnote-number" for="fn_11_128">128</label> The necessary state of each lock must be held within some actor, which is then able to make authoritative decisions about which peer is to be assigned the lock at any one time. This strategy is exactly the same as that required to implement locking in the actor model. A key improvement over both the equivalent actor model lock implementation and the tuplespace approach to locking is the ability of <span class="small-caps">Syndicate</span> protocols to rely on automatic assertion retraction on actor termination or failure: here, a lock-holder that crashes automatically releases the lock, freeing the lock-maintaining actor to assign the lock to some other waiting client.<label class="footnote-number" for="fn_11_129">129</label></p>
<h6 class="unnumbered" id="x_11_3_0_0_15"><a name="toc_11.3"></a><span class="heading-text paragraph">Message-based vs. assertion-based signaling.</span></h6><p id="x_11_3_0_0_16"><span class="small-caps">Syndicate</span> not only allows but forces a kind of temporal decoupling of components: every time a request travels via the dataspace, the programmer may rely on eventually getting the answer needed, but does not know in general how soon. Other things may also happen in the meantime. Some protocol domains rely intrinsically on tight temporal bounds—sometimes on the “synchrony” hypothesis, on being able to access any part of the application's state in “no time at all”—and for these problems, <span class="small-caps">Syndicate</span> may be of limited application. Implementation of an IRC server makes for an interesting case study here: traditional implementations take advantage of being able to “stop the world” and query the global server state. However, even there we can adapt to the forced decoupling mandated by <span class="small-caps">Syndicate</span> and get some advantages. Appendix <a class="cross-reference" href="#APPENDIX:IRC-CASE-STUDY">B</a> presents the case study in more detail.</p>
<h6 class="unnumbered" id="x_11_3_0_0_17"><a name="toc_11.3"></a><span class="heading-text paragraph">Capturing and embedding of sets of assertions.</span></h6><p id="x_11_3_0_0_18">Patterns in <span class="small-caps">Syndicate</span> match individual assertions from the dataspace, and pattern variables capture single host-language values. Similarly, the assertion <em>templates</em> in<tt> </tt>endpoints only allow embedding of fields holding single host-language values. From time to time, direct extraction or insertion of assertion <em>sets</em> would be valuable. For example, the “broker” program connecting <span class="small-caps">Syndicate/rkt</span> to <span class="small-caps">Syndicate/js</span> (appendix <a class="cross-reference" href="#APPENDIX:POLYGLOT">C</a>) relays arbitrary assertion sets in bulk between the Racket and JavaScript sides of the network connection, whether those sets are finite or not. Given that the existing <span class="small-caps">Syndicate</span> pattern language only allows matching of single values, the broker relies on ad-hoc extensions to the language design in order to perform its task.</p>
<h6 class="unnumbered" id="x_11_3_0_0_19"><a name="toc_11.3"></a><span class="heading-text paragraph">Complex “joins” on assertions.</span></h6><p id="x_11_3_0_0_20">In the IRC server example discussed in Appendix <a class="cross-reference" href="#APPENDIX:IRC-CASE-STUDY">B</a>, the program must communicate an initial set of channel members upon channel join. Setting aside interactions with the complications of <tt>NICK</tt>/<tt>QUIT</tt> tracking discussed in the appendix, one might imagine using <span class="small-caps">Syndicate/rkt</span>'s <tt>immediate-query</tt> form to imperatively compute the initial set of channel members:</p>
<div class="verbatim" id="x_11_3_0_0_22">
<pre class="verbatim" id="x_11_3_0_0_21"><code>(define conns (immediate-query [query-set (ircd-channel-member Ch $c) c]))
(define nicks (immediate-query [query-set (ircd-connection-info conns $n) n]))
(send-initial-name-list! Ch nicks)
</code></pre></div><p id="x_11_3_0_0_23">Unfortunately, this doesn't work, because as we have just discussed, embedding sets of values like <tt>conns</tt> into an assertion set is not currently supported. An alternative is to iterate over <tt>conns</tt>, performing an <tt>immediate-query</tt> for each peer connection, making <span class="lyx-mathjax mathjax-inline">$n+1$</span> round trips to the dataspace. A future <span class="small-caps">Syndicate</span> design could perhaps include some way of specifying a <em>join</em>-like construct: a way of asserting “interest in all records <tt>(ircd-connection-info <span class="lyx-mathjax mathjax-inline">$c$</span> <span class="lyx-mathjax mathjax-inline">$n$</span>)</tt> where <span class="lyx-mathjax mathjax-inline">$c$</span> is drawn from any record <tt>(ircd-channel-member Ch <span class="lyx-mathjax mathjax-inline">$c$</span>)</tt>,” retrieving the information of interest in a single round trip.</p>
<h6 class="unnumbered" id="x_11_3_0_0_24"><a name="toc_11.3"></a><span class="heading-text paragraph">Negative knowledge and “snapshots.”</span></h6><p id="x_11_3_0_0_25">It can be awkward to express programs that interpret the <em>absence </em>of a particular assertion as logically meaningful, a form of negation; recall the machinations that the code of figure <a class="cross-reference" href="#fig:cancellation:PL-incremental-search-loading">83</a> (page <a class="cross-reference pageref" href="#fig:cancellation:PL-incremental-search-loading">&mdash;</a>) was forced to engage in. There, the facet <em>assumed</em> absence of relevant knowledge at startup, acting as if no relevant assertions were present. It then updated its beliefs upon discovery of relevant knowledge, and altered its actions accordingly. This difficulty is related to the “open world” nature of <span class="small-caps">Syndicate</span> dataspaces. Relatedly, as discussed in section <a class="cross-reference" href="#subsec:Styles-of-interaction">4.8</a>, in situations where one may validly make a closed-world assumption, it is awkward to gather a “complete” set of facts relevant to a given query. For example, consider again the task of the IRC server when a user joins an existing IRC channel. The server must collect and send the new user a list of all users already present in the channel before transitioning into an incremental membership-maintenance mode. This is the inverse of the IRC <em>client</em> example motivating the use of <tt>assert!</tt> and <tt>retract!</tt> seen in section <a class="cross-reference" href="#sec:Ad-hoc-assertions">6.6</a>. The IRC server solves the problem by establishing interest in assertions describing channel membership, then waiting for a rather arbitrary length of time—two dataspace-and-back round trip times—before calling the membership information it has gathered at that point “enough” and transmitting it. How long is long enough to wait? In this case, two round trips sufficed, but in general, <em>no limit can be placed</em>. At its root, the reason is that expression of interest in a record may result in lazy production of that record. A special, but important, case is that of a <em>relay</em> actor whose responsibility is to convey expressions of interest across some gap—be it a network link, or simply a bridge between two adjacent nested dataspaces—and to convey the resulting assertions back in the other direction. Each relay introduces latency between detection of interest in an assertion and production of the assertion itself. Actors interested in assertions cannot in general predict any upper bound on this latency.</p></p><p id="x_12_2_0_0_9">
<h3 id="x_12_0_0_0_1"><a name="toc_12"></a><span class="counter chapter"><span>12</span></span><span class="heading-text chapter"><a class="label-anchor" href="#CHAP:CONCLUSION"></a><a name="CHAP:CONCLUSION"></a>Conclusion</span></h3>
<h4 id="x_12_1_0_0_1"><a name="toc_12.1"></a><span class="counter section"><span>12.1</span></span><span class="heading-text section">Review</span></h4><p id="x_12_1_0_0_2">The thesis that this dissertation defends is</p><p id="x_12_1_0_0_4">
<div class="thesisstatement" id="x_12_1_0_0_3"><span class="small-caps">Syndicate</span> provides a new, effective, realizable linguistic mechanism for sharing state in a concurrent setting.</div></p><p id="x_12_1_0_0_5">As in the introduction, we can examine this piece by piece.</p>
<dl id="x_12_1_0_0_16"><dt id="x_12_1_0_0_6">Mechanism&nbsp;for&nbsp;sharing&nbsp;state.</dt><dd id="x_12_1_0_0_7"> We have seen that, as promised, the dataspace model (chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-I:DATASPACES">4</a>) directly focuses on the management, scoping, and sharing of conversational state among collaborating actors. Actors exchange state-change notification events with their surroundings, describing accumulated conversational knowledge. Dataspaces use epistemic knowledge of actors' interests to route information and record provenance to maintain integrity of the store after partial failure.</dd><dt id="x_12_1_0_0_8">Linguistic&nbsp;mechanism.</dt><dd id="x_12_1_0_0_9"> The full <span class="small-caps">Syndicate</span> language design (chapter <a class="cross-reference" href="#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE">5</a>) equips a host language used to write leaf actors in a dataspace with new linguistic constructs: facets, endpoints and fields. Facets manifest conversations and conversational state within an actor. Each facet comprises a bundle of private state, shared state, subscriptions and event-handlers. Programmers tie facet lifetimes to the lifetimes of conversational frames. Facets nest, forming a structure that mirrors the logical structure of ongoing conversations.</dd><dt id="x_12_1_0_0_10">Realizability.</dt><dd id="x_12_1_0_0_11"> A new data structure, the assertion trie, provides efficient pattern matching and event routing at the heart of <span class="small-caps">Syndicate/rkt</span> and <span class="small-caps">Syndicate/js</span>, the two prototype <span class="small-caps">Syndicate</span> implementations (chapters <a class="cross-reference" href="#CHAP:TUTORIAL">6</a> and <a class="cross-reference" href="#CHAP:IMPLEMENTATION">7</a>).</dd><dt id="x_12_1_0_0_12">Effectiveness.</dt><dd id="x_12_1_0_0_13"> The effectiveness of the design is shown through examination of programming idioms (chapter <a class="cross-reference" href="#CHAP:IDIOMATIC-SYNDICATE">8</a>), discussion of programming patterns and design patterns eliminated from <span class="small-caps">Syndicate</span> programs (chapter <a class="cross-reference" href="#CHAP:PATTERNS">9</a>), and through preliminary confirmation of the expected performance of the implementation approach taken (chapter <a class="cross-reference" href="#CHAP:PERFORMANCE">10</a>).</dd><dt id="x_12_1_0_0_14">Novelty.</dt><dd id="x_12_1_0_0_15"> While <span class="small-caps">Syndicate</span> draws on prior work, it stands alone at an interesting point in the design space of concurrency models (chapter <a class="cross-reference" href="#CHAP:DISCUSSION">11</a>).</dd></dl>
<h4 id="x_12_2_0_0_1"><a name="toc_12.2"></a><span class="counter section"><span>12.2</span></span><span class="heading-text section">Next steps</span></h4><p id="x_12_2_0_0_2">The <span class="small-caps">Syndicate</span> design gives programmers a new tool and a new way of thinking about coordination of concurrent components in <em>non-distributed</em> programs. This dissertation has developed an intuition, a computational model, and the beginnings of a programming model for <span class="small-caps">Syndicate</span>. There are several possible paths forward from here.</p>
<h6 class="unnumbered" id="x_12_2_0_0_3"><a name="toc_12.2"></a><span class="heading-text paragraph">Enhancements to the formal models.</span></h6><p id="x_12_2_0_0_4">First, development of a <span class="small-caps">Syndicate</span> type system could allow programmers to capture and check specifications not only for structural properties of the data to be placed in each dataspace, but behavioral properties of actors participating in <span class="small-caps">Syndicate</span> conversations, including their roles, responsibilities and obligations. Second, the core dataspace model does not include any kind of programmer-visible name or name-like entity, but many protocols depend on some notion of globally unique token; equipping the formal model with either <em>unique</em> or <em>unguessable</em> tokens would allow exploration of the formal properties of such protocols and the programs that implement them. Finally, as part of work toward a model of distributed <span class="small-caps">Syndicate</span>, separating the <em>grouping</em> aspect of dataspaces from their <em>layering</em> aspect would allow investigation of “subnets”: fragmentary dataspaces that combine to form a logical whole.</p>
<h6 class="unnumbered" id="x_12_2_0_0_5"><a name="toc_12.2"></a><span class="heading-text paragraph">System model.</span></h6><p id="x_12_2_0_0_6">The few experiments exploring <span class="small-caps">Syndicate</span> tool support so far have been promising, suggesting that the design might offer a new perspective on broader systems questions. Development of protocols for process control, for generalized “streams” of assertions, and for console-based or graphical user interaction with programs would allow experimentation with operating systems design. The <span class="small-caps">Syndicate/rkt</span> prototype implementation already includes use of contracts <span class="citation citep">(<a class="citation" id="cite-296" href="#bib-Dimoulas2016">Dimoulas et al. 2016</a>)</span> to check field invariants; perhaps new kinds of contract could be employed to check actor, role, or conversation invariants within and between dataspaces. The “firewall” mechanism for securing access to the dataspace could be combined with ideas from certificate theory <span class="citation citep">(<a class="citation" id="cite-297" href="#bib-rfc2693">Ellison et al. 1999</a>)</span> to explore multiuser <span class="small-caps">Syndicate</span>. Strategies for orthogonal persistence of <span class="small-caps">Syndicate</span> actors could allow investigation of database-like, long-lived dataspaces. The existing “broker” approach to integrating <span class="small-caps">Syndicate/rkt</span> with <span class="small-caps">Syndicate/js</span> could be generalized to support polyglot <span class="small-caps">Syndicate</span> programming more generally. Finally, the implementations of <span class="small-caps">Syndicate</span> to date have employed single-threaded, cooperative concurrency; introduction of true parallelism would be an important step toward a distributed <span class="small-caps">Syndicate</span> implementation.</p>
<h6 class="unnumbered" id="x_12_2_0_0_7"><a name="toc_12.2"></a><span class="heading-text paragraph">Distributed systems.</span></h6><p id="x_12_2_0_0_8">The centrality of state machine replication to distributed systems <span class="citation citep">(<a class="citation" id="cite-298" href="#bib-Lamport1984">Lamport 1984</a>)</span> is one of the reasons to hope <span class="small-caps">Syndicate</span> might work well in a distributed setting, given the centrality of state replication to the dataspace model. Communication via assertions, rather than messages, can lead to protocols that automatically withstand lost messages, even in the presence of certain kinds of “glitching”. That is, replication by state-change notification is in some sense self-synchronizing. <span class="small-caps">Syndicate</span> programs must already cope with certain forms of partial failure familiar from distributed systems; for example, messages can be “lost” if they are routed through a relay actor that crashes at an inopportune moment. Even though the underlying dataspace itself guarantees reliable message delivery, this guarantee only applies on a “hop-by-hop” basis. It would be interesting to attempt to scale this nascent resilience up to a distributed setting, perhaps even transplanting some of the benefits of <span class="small-caps">Syndicate</span> back into the fact space model. Finally, since certain aspects of causal soundness (definition <a class="cross-reference" href="#def:relevance">4.31</a>) are helpful but not essential, we are free to consider alternative “subnet”-based implementation strategies, such as making actors build copies of the whole routing table themselves, leaving the dataspace “empty” and stateless, and using Bloom filters or similar to narrowly overapproximate the interests of an actor or group of actors.</p></p><p id="x_A_0_0_0_20">
<h3 id="x_A_0_0_0_1"><a name="toc_A"></a><span class="counter appendix"><span>A</span></span><span class="heading-text appendix"><a class="label-anchor" href="#APPENDIX:PLJS-SYNTAX"></a><a name="APPENDIX:PLJS-SYNTAX"></a><span class="small-caps">Syndicate/js</span> Syntax</span></h3><p id="x_A_0_0_0_2">Figure <a class="cross-reference" href="#fig:Ohm-grammar-for-PLJS">92</a> presents an Ohm <span class="citation citep">(<a class="citation" id="cite-299" href="#bib-Warth2016">Warth, Dubroy and Garnock-Jones 2016</a>)</span> grammar that extends JavaScript with <span class="small-caps">Syndicate</span>'s new language features. Support is provided for spawning new actors (lines 1116), for creating (lines 1718) and configuring (lines 1930) facets, for managing fields (lines 3537), sending messages (line 38) and matching incoming events (lines 3948). The remainder of the compiler from the extended JavaScript dialect to the core language is placed alongside the grammar in a separate 460-line JavaScript file.</p><p id="x_A_0_0_0_3">In order to keep the compiler simple, some of the tasks performed by the <span class="small-caps">Syndicate/rkt</span> macro-based compiler are deferred to runtime in the <span class="small-caps">Syndicate/js</span> implementation. In addition, the Ohm system is, at heart, a parsing toolkit, and does not offer an analogue of the intricately interwoven multi-phase expansion process available in Racket's syntactic extension system; therefore, features such as <em>event expanders</em>, which allow the <span class="small-caps">Syndicate/rkt</span> programmer to define custom event pattern forms, are precluded. This limits the <span class="small-caps">Syndicate/js</span> programmer to those event pattern forms built-in to the compiler.</p><p id="x_A_0_0_0_4">Two entry points to the compiler are provided: a command-line tool, for ordinary batch compilation, and a browser-loadable package. The latter allows for rapid development of <span class="small-caps">Syndicate/js</span>-based web applications by on-the-fly translating HTML <tt>script</tt> tags with a <tt>type</tt> attribute of “<tt>text/syndicate-js</tt>” into plain JavaScript that the browser can understand.</p>
<figure id="x_A_0_0_0_6"><a name="fig:Ohm-grammar-for-PLJS"></a>
<pre class="listing" id="x_A_0_0_0_5"><code>Syndicate &lt;: ES5 {
Statement
+= ActorStatement
| DataspaceStatement
| ActorFacetStatement
| ActorEndpointStatement
| AssertionTypeDeclarationStatement
| FieldDeclarationStatement
| SendMessageStatement
FunctionBodyBlock = "{" FunctionBody "}"
ActorStatement
= spawnStar (named Expression&lt;withIn&gt;)? FunctionBodyBlock -- noReact
| spawn (named Expression&lt;withIn&gt;)? FunctionBodyBlock -- withReact
DataspaceStatement
= ground dataspace identifier? FunctionBodyBlock -- ground
| dataspace FunctionBodyBlock -- normal
ActorFacetStatement
= react FunctionBodyBlock
ActorEndpointStatement
= on start FunctionBodyBlock -- start
| on stop FunctionBodyBlock -- stop
| assert FacetPattern AssertWhenClause? #(sc) -- assert
| on FacetEventPattern FunctionBodyBlock -- event
| on event identifier FunctionBodyBlock -- onEvent
| stop on FacetTransitionEventPattern FunctionBodyBlock -- stopOnWithK
| stop on FacetTransitionEventPattern #(sc) -- stopOnNoK
| dataflow FunctionBodyBlock -- dataflow
| during FacetPattern FunctionBodyBlock -- during
| during FacetPattern spawn (named Expression&lt;withIn&gt;)?
FunctionBodyBlock -- duringSpawn
AssertWhenClause = when "(" Expression&lt;withIn&gt; ")"
AssertionTypeDeclarationStatement
= (assertion | message) type identifier "(" FormalParameterList ")"
("=" stringLiteral)? #(sc)
FieldDeclarationStatement = field MemberExpression ("=" AssignmentExpression&lt;withIn&gt;)? #(sc)
MemberExpression += field MemberExpression -- fieldRefExp
UnaryExpression += delete field MemberExpression -- fieldDelExp
SendMessageStatement = "::" Expression&lt;withIn&gt; #(sc)
FacetEventPattern
= message FacetPattern -- messageEvent
| asserted FacetPattern -- assertedEvent
| retracted FacetPattern -- retractedEvent
FacetTransitionEventPattern
= FacetEventPattern -- facetEvent
| "(" Expression&lt;withIn&gt; ")" -- risingEdge
FacetPattern
= LeftHandSideExpression metalevel decimalIntegerLiteral -- withMetalevel
| LeftHandSideExpression -- noMetalevel
// (Keyword definitions elided)
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>92</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Ohm-grammar-for-PLJS"></a>Ohm grammar for the <span class="small-caps">Syndicate/js</span> extension to JavaScript<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<h4 class="unnumbered" id="x_A_0_0_0_7"><a name="toc_A.0"></a><span class="heading-text section">Example</span></h4>
<figure id="x_A_0_0_0_12"><a name="fig:PLJS-HTML-Example"></a>
<figure id="x_A_0_0_0_9"><a name="fig:PLJS:html"></a>&nbsp;<figcaption><span class="counter figure"><span>93(a)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLJS:html"></a><tt>index.html</tt>, HTML page hosting the program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<pre class="listing" id="x_A_0_0_0_8"><code>&lt;!doctype html&gt;
&lt;html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="http://syndicate-lang.org/dist/syndicatecompiler.js"&gt;&lt;/script&gt;
&lt;script src="http://syndicate-lang.org/dist/syndicate.js"&gt;&lt;/script&gt;
&lt;script type="text/syndicate-js" src="index.js"&gt;&lt;/script&gt;
&lt;h1&gt;Button Example&lt;/h1&gt;
&lt;button id="counter"&gt;&lt;span id="button-label"&gt;&lt;/span&gt;&lt;/button&gt;
&lt;/html&gt;
</code></pre><span class="plain-layout-boundary"></span>
<figure id="x_A_0_0_0_11"><a name="fig:PLJS:code"></a>&nbsp;<figcaption><span class="counter figure"><span>93(b)</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLJS:code"></a><tt>index.js</tt>, <span class="small-caps">Syndicate/js</span> source code, automatically translated to plain JavaScript<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<pre class="listing" id="x_A_0_0_0_10"><code>ground dataspace {
Syndicate.UI.spawnUIDriver();
spawn {
var ui = new Syndicate.UI.Anchor();
field this.counter = 0;
assert ui.html('#button-label', '' + this.counter);
on message Syndicate.UI.globalEvent('#counter', 'click', _) {
this.counter++;
}
}
}
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>93</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLJS-HTML-Example"></a>Example <span class="small-caps">Syndicate/js</span> in-browser program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_A_0_0_0_13">Figure <a class="cross-reference" href="#fig:PLJS-HTML-Example">93</a> shows a complete example browser-based <span class="small-caps">Syndicate/js</span> program. Figure <a class="cross-reference" href="#fig:PLJS:html">93(a)</a> specifies the HTML structure of the page loaded into the browser; figure <a class="cross-reference" href="#fig:PLJS:code">93(b)</a> specifies <span class="small-caps">Syndicate/js</span> code giving the program its behavior. Lines 4 and 5 of the HTML load the latest versions of the <span class="small-caps">Syndicate/js</span> compiler and runtime, respectively, from the <tt>syndicate-lang.org</tt> domain. Line 6 connects the HTML to the <span class="small-caps">Syndicate/js</span> program, making sure to correctly label the <tt>type</tt> of the linked code as <tt>text/syndicate-js</tt> in order to arrange for it to be compiled to plain JavaScript on the fly. Lines 7 and 8 are the user-visible interface; in particular, two elements are given identifiers in order for them to be accessible from the script. The clickable button is named <tt>counter</tt>, and the span of text forming its label is named <tt>button-label</tt>.</p><p id="x_A_0_0_0_14">Line 1 of the script in figure <a class="cross-reference" href="#fig:PLJS:code">93(b)</a> opens a block declaring the boot script for the ground dataspace to be run. Line 2 activates the <span class="small-caps">Syndicate/js</span> “user interface” driver, responsible for mapping assertions describing HTML fragments into the page as well as responding to interest in DOM events by establishing subscriptions and relaying events from the page into the dataspace. Lines 310 comprise the lone actor in this program. Line 4 constructs a JavaScript object offering convenience methods for constructing assertions and event patterns. On line 6, we see one of its uses. The actor asserts a record whose interpretation is, loosely, “please add the literal string representation of the value of <tt>this.counter</tt> to the collection of DOM nodes inside the element with ID <tt>button-label</tt>.” The assertion make reference to the field <tt>this.counter</tt> declared on line 4. The dataflow mechanism ensures that as <tt>this.counter</tt> is updated, assertions and subscriptions depending on it are automatically updated to match. Lines 79 comprise the sole event handler endpoint in the program, soliciting notifications about mouse-clicks on the DOM element with ID <tt>counter</tt>. In response, the actor increments its <tt>this.counter</tt> field.</p><p id="x_A_0_0_0_18">
<figure class="marginfigure" id="x_A_0_0_0_17"><a name="fig:PLJS:screenshot"></a>
<p class="align-center" id="x_A_0_0_0_16"><img id="x_A_0_0_0_15" src="js-example/screenshot.png"/></p><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>94</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:PLJS:screenshot"></a>The running program<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure></p><p id="x_A_0_0_0_19">The net effect of all of this is shown in figure <a class="cross-reference" href="#fig:PLJS:screenshot">94</a>. Each time the user clicks the button, the number on the button's label is incremented.</p></p><p id="x_B_0_0_0_20">
<h3 id="x_B_0_0_0_1"><a name="toc_B"></a><span class="counter appendix"><span>B</span></span><span class="heading-text appendix"><a class="label-anchor" href="#APPENDIX:IRC-CASE-STUDY"></a><a name="APPENDIX:IRC-CASE-STUDY"></a>Case study: IRC server</span></h3>
<div class="footnote" id="fn_2_130"><span class="counter footnote-counter"><span>130</span></span>For example, the internal architecture of RabbitMQ had to be revised several times to avoid RPC-like interactions in favor of unidirectional streaming in order to avoid time-of-check-to-time-of-use problems stemming from the fact that messages between independent pairs of actors may legitimately be delivered in any order in Erlang (and the actor model). If multiple paths from a stateful component to some sink exist, then it is perfectly possible for updates involving the stateful component to arrive out-of-order.<span class="plain-layout-boundary"></span></div><p id="x_B_0_0_0_2"><span class="small-caps">Syndicate</span> encourages programmers to design protocols that use assertion signaling, rather than messages, to exchange information. In many cases, this results in a “logical” characterization of protocol progress that is robust in the face of unexpected processing latency and partial failure. Use of messages within a conversational frame established by assertions is also, in many cases, perfectly sensible. However, in some cases—predominantly integration with non-<span class="small-caps">Syndicate</span> protocols, where messages alone transfer changes in application state—the <span class="small-caps">Syndicate</span> programmer must still carefully reason about order of events and latency. The reasoning involved is in some ways similar to that used to design away races in languages with other approaches to concurrency, but is focused on epistemic questions rather than questions of state; programmers think about which components know certain facts, rather than which locks are in certain states. Solutions include tracking causality in exchanged messages, or explicitly serializing communications through a single actor performing the role of single-point-of-truth. <span class="small-caps">Syndicate</span> is no different to the actor model in this regard; programming in Erlang, for example, involves exactly the same kinds of considerations.<label class="footnote-number" for="fn_2_130">130</label></p>
<figure id="x_B_0_0_0_4"><a name="fig:ircd-membership-tracking"></a>
<pre class="listing" id="x_B_0_0_0_3"><code>(during (ircd-channel-member $Ch this-conn)
(field [initial-names-sent? #f]
[initial-member-nicks (set)])
(on-start (flush!)
(flush!) ;; two round-trips to dataspace: gather current peers
(define nicks (initial-member-nicks))
(initial-names-sent? #t)
(initial-member-nicks 'no-longer-valid)
(send-initial-name-list! Ch nicks))
(during (ircd-channel-member Ch $other-conn)
(field [current-other-name #f])
(define/query-value next-other-name #f
(ircd-connection-info other-conn $N)
N)
(on (retracted (ircd-channel-member Ch other-conn))
(when (current-other-name)
(send-PART (current-other-name) Ch)))
(begin/dataflow
(when (not (equal? (current-other-name) (next-other-name)))
(cond
[(not (next-other-name)) ;; other-conn is disconnecting
(send-QUIT (current-other-name))]
[(not (initial-names-sent?)) ;; still gathering initial list
(initial-member-nicks (set-add (initial-member-nicks)
(next-other-name)))]
[(not (current-other-name)) ;; other-conn is joining
(send-JOIN (next-other-name) Ch)]
[else ;; it's a nick change
(send-NICK (current-other-name) (next-other-name))])
(current-other-name (next-other-name))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>95</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:ircd-membership-tracking"></a>Heart of the IRC server channel-membership-tracking code.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<div class="footnote" id="fn_2_131"><span class="counter footnote-counter"><span>131</span></span><span>Source code file <a href="https://github.com/tonyg/syndicate/blob/master/examples/ircd/session.rkt"><tt>examples/ircd/session.rkt</tt></a> in the <span class="small-caps">Syndicate</span> repository.</span><span class="plain-layout-boundary"></span></div><p id="x_B_0_0_0_5">A challenging example is found in the IRC protocol <span class="citation citep">(<a class="citation" id="cite-300" href="#bib-rfc1459">Oikarinen and Reed 1993</a>; <a class="citation" id="cite-301" href="#bib-rfc2812">Kalt 2000</a>)</span>. Upon joining a channel, the server sends the client first an aggregate of all users previously present in the channel. Then, updates to that set are delivered via incremental <tt>JOIN</tt> and <tt>PART</tt> notifications; if a peer disconnects, <tt>QUIT</tt> replaces <tt>PART</tt>. However, if a channel member decides to change its nickname, this is to be reported by the server not as a <tt>PART</tt> of the old nickname followed by a <tt>JOIN</tt> of the new, but by a special <tt>NICK</tt> message. In the <span class="small-caps">Syndicate</span> IRC server case study,<label class="footnote-number" for="fn_2_131">131</label> the requirements thus far can be met with only modest contortions (figure <a class="cross-reference" href="#fig:ircd-membership-tracking">95</a>). The challenge appears when we notice the requirement that if our connection is in two channels, and some peer <tt>X</tt> is in those same channels, and <tt>X</tt> renames itself to <tt>Y</tt>, the server should send only <em>one</em> <tt>NICK</tt> message; likewise, if <tt>X</tt> disconnects, only <em>one</em> <tt>QUIT</tt> message should be sent. That is, <tt>NICK</tt> and <tt>QUIT</tt> messages relate to connected users, not channels, but are only delivered to a client when they are relevant, namely when the client has one or more channel in common with the name-changing or disconnecting user. The code shown in figure <a class="cross-reference" href="#fig:ircd-membership-tracking">95</a> delivers redundant <tt>NICK</tt> and <tt>QUIT</tt> messages in these situations. A different approach is called for.</p>
<div class="footnote" id="fn_2_132"><span class="counter footnote-counter"><span>132</span></span><a href="https://github.com/jrosdahl/miniircd">https://github.com/jrosdahl/miniircd</a><span class="plain-layout-boundary"></span></div><p id="x_B_0_0_0_6">Traditional IRC server implementations such as the original <tt>ircd</tt> (as of version <tt>irc2.11.2p3</tt>) and newer implementations such as <tt>miniircd</tt><label class="footnote-number" for="fn_2_132">132</label> are able to avoid these concerns. Two differences in design interact to make this possible. First, they are single-threaded, event-driven programs. In effect, all state in the system is local to the active thread. Second, notification transmission is performed by the component responsible for the user being renamed or disconnecting, giving a convenient place to store a transient “checklist” of users to whom a particular <tt>NICK</tt> or <tt>QUIT</tt> notification has already been delivered. When preparing such notifications, these programs simply loop over all members of all the changing user's channels, making a note of peers to whom they have sent notifications as they go, in effect <em>deduplicating</em> the notifications.</p><p id="x_B_0_0_0_7">Nothing prevents us from writing a <span class="small-caps">Syndicate</span> IRC server in this style: a single “server” actor could hold all relevant state, with a facet for each connected user; in its event handlers, it would be able to interrogate the instantaneous state of the server as a whole without having to make allowance for the temporal decoupling that arises every time a <span class="small-caps">Syndicate</span> actor accesses its dataspace. However, taking this approach forfeits the advantages offered by idiomatic <span class="small-caps">Syndicate</span> design. In the <span class="small-caps">Syndicate</span> IRC implementation, authoritative aggregate system state lives in the dataspace, not in individual actors, and notification transmission is the responsibility of the component representing the party to be notified; deduplication must happen there.</p>
<figure id="x_B_0_0_0_9"><a name="fig:ircd-membership-tracking-fields"></a>
<pre class="listing" id="x_B_0_0_0_8"><code>(field [peer-common-channels (hash)]
[peer-names (hash)])
(define (add-peer-common-channel! other-conn Ch)
(peer-common-channels
(hashset-add (peer-common-channels) other-conn Ch)))
(define (remove-peer-common-channel! other-conn Ch)
(peer-common-channels
(hashset-remove (peer-common-channels) other-conn Ch)))
(define (no-common-channel-with-peer? other-conn)
(not (hash-has-key? (peer-common-channels) other-conn)))
(define (forget-peer-name! other-conn)
(peer-names (hash-remove (peer-names) other-conn)))
(define (most-recent-known-name other-conn)
(hash-ref (peer-names) other-conn #f))
(define (remember-peer-name! other-conn name)
(peer-names (hash-set (peer-names) other-conn name)))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>96</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:ircd-membership-tracking-fields"></a>Additional per-connection IRC server fields for <tt>NICK</tt>/<tt>QUIT</tt> deduplication.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure>
<figure id="x_B_0_0_0_11"><a name="fig:ircd-membership-tracking-dedup"></a>
<pre class="listing" id="x_B_0_0_0_10"><code>(during (ircd-channel-member $Ch this-conn)
(field [initial-names-sent? #f]
[initial-member-nicks (set)])
(on-start (flush!)
(flush!) ;; two round-trips to dataspace: gather current peers
(define nicks (initial-member-nicks))
(initial-names-sent? #t)
(initial-member-nicks 'no-longer-valid)
(send-initial-name-list! Ch nicks))
(during (ircd-channel-member Ch $other-conn)
* (on-start (add-peer-common-channel! other-conn Ch))
* (on-stop (remove-peer-common-channel! other-conn Ch)
* (when (no-common-channel-with-peer? other-conn)
* (forget-peer-name! other-conn)))
(field [current-other-name #f])
(define/query-value next-other-name #f
(ircd-connection-info other-conn $N)
N)
(on (retracted (ircd-channel-member Ch other-conn))
(when (current-other-name)
(send-PART (current-other-name) Ch)))
(begin/dataflow
(when (not (equal? (current-other-name) (next-other-name)))
(cond
[(not (next-other-name)) ;; other-conn is disconnecting
* (when (most-recent-known-name other-conn)
* (send-QUIT (current-other-name))
* (forget-peer-name! other-conn))]
[(not (initial-names-sent?)) ;; still gathering initial list
(initial-member-nicks (set-add (initial-member-nicks)
(next-other-name)))
* (remember-peer-name! other-conn (next-other-name))]
[(not (current-other-name)) ;; other-conn is joining
(send-JOIN (next-other-name) Ch)
* (remember-peer-name! other-conn (next-other-name))]
[else ;; it's a nick change
* (when (not (equal? (next-other-name)
* (most-recent-known-name other-conn)))
* (send-NICK (current-other-name) (next-other-name))
* (remember-peer-name! other-conn (next-other-name)))])
(current-other-name (next-other-name))))))
</code></pre><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>97</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:ircd-membership-tracking-dedup"></a>IRC server channel-membership-tracking with <tt>NICK</tt>/<tt>QUIT</tt> deduplication.<span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_B_0_0_0_12">To perform this deduplication, the actor must track exactly the names of peers with whom we share a channel. The simplest approach I could come up with uses two new connection-scoped fields to do this. Figure <a class="cross-reference" href="#fig:ircd-membership-tracking-fields">96</a> shows the new fields and their use. The changes to the code of figure <a class="cross-reference" href="#fig:ircd-membership-tracking">95</a> are the lines marked with <tt>*</tt> in figure <a class="cross-reference" href="#fig:ircd-membership-tracking-dedup">97</a>. Lines 1011 manage the connection's view of which other connections have a channel in common with this connection. The actual deduplication, the purpose of the exercise, occurs on lines 2527 and 3639.</p><p id="x_B_0_0_0_13">One noteworthy feature of the code in figure <a class="cross-reference" href="#fig:ircd-membership-tracking-fields">96</a> is its similarity to a special-purpose representation of a local dataspace containing “virtual assertions” of the form</p>
<div class="verbatim" id="x_B_0_0_0_15">
<pre class="verbatim" id="x_B_0_0_0_14"><code>(ircd-common-channel this-conn other-conn)
(ircd-connection-info other-conn name)
</code></pre></div><p id="x_B_0_0_0_16">The fact that the program already relies on <tt>ircd-connection-info</tt> assertions in the dataspace raises the question of why we do not simply assert</p>
<div class="verbatim" id="x_B_0_0_0_18">
<pre class="verbatim" id="x_B_0_0_0_17"><code>(ircd-common-channel this-conn other-conn)
</code></pre></div><p id="x_B_0_0_0_19">within the <tt>during</tt> clause starting on line 9 of figure <a class="cross-reference" href="#fig:ircd-membership-tracking-dedup">97</a>, and add a new facet to the connection actor reacting to <tt>ircd-common-channel</tt>, tracking <tt>ircd-connection-info</tt> and issuing <tt>NICK</tt> and <tt>QUIT</tt> messages when required. The answer is that building an initial summary of names is a stateful procedure that is part of joining an individual channel, while tracking <tt>NICK</tt> changes and <tt>QUIT</tt> events is done on a per-connection basis. It would be possible for the summary-construction process to add a nickname <tt>X</tt> to its set, for <tt>X</tt> to rename itself <tt>Y</tt>, and for the corresponding “<tt>:X NICK Y</tt>” message to be transmitted <em>before</em> the summary list, containing the already-obsolete <tt>X</tt>. Absent the requirement to summarize channel members in a manner syntactically distinct from subsequent changes to channel membership, this assertion-based approach of “following the logic” would work well.</p></p><p id="x_D_0_0_0_9">
<h3 id="x_C_0_0_0_1"><a name="toc_C"></a><span class="counter appendix"><span>C</span></span><span class="heading-text appendix"><a class="label-anchor" href="#APPENDIX:POLYGLOT"></a><a name="APPENDIX:POLYGLOT"></a>Polyglot <span class="small-caps">Syndicate</span></span></h3>
<div class="lyx-mathjax mathjax-definitions" id="x_C_0_0_0_2">\(\newcommand{\jsonEnc}[1]{\mathit{enc}(#1)}
\)</div><p id="x_C_0_0_0_5">Many of the programs developed in <span class="small-caps">Syndicate</span> have involved multiple separate processes, some running <span class="small-caps">Syndicate/rkt</span> and others <span class="small-caps">Syndicate/js</span> code, communicating via a simple JSON-based encoding of <span class="small-caps">Syndicate</span> events carried over WebSockets. Informally, imagine a function <span class="lyx-mathjax mathjax-inline">$\jsonEnc{\cdot}$</span> which maps <span class="small-caps">Syndicate</span> objects to JSON terms. We might encode tries like this:
<div class="lyx-mathjax mathjax-display" id="x_C_0_0_0_3">\begin{align*}
\jsonEnc{\MT} &amp; =[]\\
\jsonEnc{\OK{\alpha}} &amp; =[\jsonEnc{\alpha}]\\
\jsonEnc{\BR{T'}{s\mapsto T,\dots}} &amp; =[\jsonEnc{T'},[[\jsonEnc s,\jsonEnc T],\dots]]
\end{align*}
</div> and might encode <span class="small-caps">Syndicate</span> events like this:
<div class="lyx-mathjax mathjax-display" id="x_C_0_0_0_4">\begin{align*}
\jsonEnc{\left\langle c\right\rangle } &amp; =[\mathtt{"message"},\jsonEnc c]\\
\jsonEnc{\frac{\ROUTES_{i}}{\ROUTES_{o}}} &amp; =[\mathtt{"patch"},[\jsonEnc{\ROUTES_{i}},\jsonEnc{\ROUTES_{o}}]]
\end{align*}
</div></p><p id="x_C_0_0_0_6">Interoperation between Racket and JavaScript requires some agreement on the atoms and structure-types exchanged. I have chosen a conservative approach of identifying corresponding strings, numbers and booleans in each of Racket, JavaScript and JSON. Racket lists map to JSON and JavaScript arrays. Racket “prefab” structs map to JSON objects with special <tt>@type</tt> and <tt>fields</tt> members, which in turn map to the “structs” used extensively in the JavaScript dataspace implementation. JSON's objects—key/value dictionaries—are not otherwise supported, consonant with the restrictions on <span class="small-caps">Syndicate/js</span> assertions discussed in section <a class="cross-reference" href="#subsec:Assertions">7.2.1</a>.</p>
<figure class="fullwidth" id="x_C_0_0_0_8"><a name="fig:Schematic-distributed-PL"></a><img id="x_C_0_0_0_7" src="Figures/dist-syndicate-arrangement.svg"/><span class="plain-layout-boundary"></span><figcaption><span class="counter figure"><span>98</span></span><span class="figcaption-text"><a class="label-anchor" href="#fig:Schematic-distributed-PL"></a>Physical (left) and logical (right) arrangement of connected <span class="small-caps">Syndicate</span> processes.<span class="lyx-argument">Physical and logical arrangement of connected <span class="small-caps">Syndicate</span> processes.<span class="plain-layout-boundary"></span></span><span class="plain-layout-boundary"></span></span></figcaption><span class="plain-layout-boundary"></span></figure><p id="x_C_0_0_0_9">At each end of a connected WebSocket, a <span class="small-caps">Syndicate</span> actor maps between events arriving from its dataspace and JSON-encoded packets arriving from the socket. Depending on the details of the transformation between events and packets, a number of different effects can be obtained.</p>
<div class="footnote" id="fn_3_133"><span class="counter footnote-counter"><span>133</span></span><span>Source code file <a href="https://github.com/tonyg/syndicate/blob/master/racket/syndicate/broker/server.rkt"><tt>racket/syndicate/broker/server.rkt</tt></a> in the <span class="small-caps">Syndicate</span> repository.</span><span class="plain-layout-boundary"></span></div><p id="x_C_0_0_0_10">Figure <a class="cross-reference" href="#fig:Schematic-distributed-PL">98</a> shows two separate <span class="small-caps">Syndicate</span> processes communicating via WebSockets. The left-hand portion of the figure illustrates the “physical” arrangement: two processes, connected via the Internet, with <span class="small-caps">Syndicate</span> actors contained in each; in particular, with one actor (“wsock”) on each side dedicated to managing a WebSocket connection, and one actor (“broker”) dedicated to relaying between local dataspace events and transmitted WebSocket JSON messages.<label class="footnote-number" for="fn_3_133">133</label> The right-hand portion of the figure shows one possible logical arrangement that can be achieved.</p>
<div class="footnote" id="fn_3_134"><span class="counter footnote-counter"><span>134</span></span>Note the strong similarity to the <span class="lyx-mathjax mathjax-inline">$\FOUTName$</span> metafunction (definition <a class="cross-reference" href="#def:mf:out-monolithic">4.14</a>), used to translate between assertions in adjacent dataspaces within a <span class="small-caps">Syndicate</span> program.<span class="plain-layout-boundary"></span></div><p id="x_C_0_0_0_11">The illustrated configuration is asymmetric, despite the seeming symmetry of the “physical” arrangement; the key is in the transformations applied in the “broker” actors at each end of the link. If the Racket-side “broker” wraps received assertions in a <tt>shared()</tt> constructor, and the JavaScript-side “broker” relays <em>out</em> assertions labeled with a <tt>toServer()</tt> constructor, and labels assertions with a <tt>fromServer()</tt> constructor when relaying them <em>in</em>, the resulting logical arrangement has the shape depicted. Imagine that D in the diagram has expressed interest in some assertion <span class="lyx-mathjax mathjax-inline">$\mathtt{shared}(x)$</span>, and that A wishes to assert <span class="lyx-mathjax mathjax-inline">$x$</span> such that D can see it. D simply asserts <span class="lyx-mathjax mathjax-inline">$?\mathtt{shared}(x)$</span> as usual, and A asserts <span class="lyx-mathjax mathjax-inline">$\mathtt{toServer}(x)$</span>. The “broker” on A's side has previously asserted <span class="lyx-mathjax mathjax-inline">$\{?\mathtt{toServer}(\star),??\mathtt{fromServer}(\star)\}$</span>, thereby expressing interest in <em>outbound</em> assertions as well as interest in <em>interest in inbound</em> assertions.<label class="footnote-number" for="fn_3_134">134</label> After A's action, the broker thus learns that <span class="lyx-mathjax mathjax-inline">$\mathtt{toServer}(x)$</span> has been asserted, and accordingly sends <span class="lyx-mathjax mathjax-inline">$\jsonEnc{\frac{\{x\}}{\emptyset}}$</span> along the WebSocket. The broker on the Racket side receives and decodes this event, and then transforms the assertions carried within it by wrapping them with the <tt>shared()</tt> constructor. It then sends the resulting event, <span class="lyx-mathjax mathjax-inline">$\frac{\{\mathtt{shared}(x)\}}{\emptyset}$</span>, to its dataspace as if the event were endogenous. D then learns of the assertion as usual. Assertions may also flow in the reverse direction: if B asserts <span class="lyx-mathjax mathjax-inline">$?\mathtt{fromServer}(y)$</span>, then the JavaScript-side broker sends <span class="lyx-mathjax mathjax-inline">$\jsonEnc{\frac{\{?y\}}{\emptyset}}$</span> through the WebSocket, and the Racket-side broker asserts <span class="lyx-mathjax mathjax-inline">$\{\mathtt{shared}(?y),?\mathtt{shared}(y)\}$</span>. Note that the Racket-side broker has now expressed interest in <span class="lyx-mathjax mathjax-inline">$\mathtt{shared}(y)$</span> assertions as if it were interested in such assertions itself. If C then asserts <span class="lyx-mathjax mathjax-inline">$\mathtt{shared}(y)$</span>, the Racket-side broker receives an event <span class="lyx-mathjax mathjax-inline">$\frac{\{\mathtt{shared}(y)\}}{\emptyset}$</span>, transforms it to <span class="lyx-mathjax mathjax-inline">$\frac{\{y\}}{\emptyset}$</span>, and relays it to the JavaScript-side broker, which transforms it to <span class="lyx-mathjax mathjax-inline">$\frac{\{\mathtt{fromServer}(y)\}}{\emptyset}$</span> before delivering it to the JavaScript-side dataspace, again as if it were endogenous. B then learns of the assertion as usual.</p><p id="x_C_0_0_0_12">Using transformations similar to these allows us to effectively embed labeled portions of a dataspace within other dataspaces in a virtual hierarchy. If more than one JavaScript client is connected at the same time, it appears alongside the other connected (and local) actors in the Racket-side dataspace. Naturally, when the client disconnects, be it cleanly or as the result of a crash or networking problem, this manifests to the Racket-side broker as a WebSocket disconnection; the broker terminates itself in response, thereby automatically retracting the assertions from the remote dataspace.</p><p id="x_C_0_0_0_13">The specific transformation scheme sketched above wraps assertions received from <em>all</em> clients with the <em>same</em> constructor; in practice, we often wish to be able to securely distinguish between assertions made by individual connected clients: the implemented broker therefore allows customization of the wrappers on a per-connection basis.</p><p id="x_C_0_0_0_14">By labeling assertions received from connected clients, the broker enforces a kind of <em>spatial separation </em>between the remote party and local actors. This can be used for <em>sandboxing, </em>among other things. The “web chat” case study takes advantage of this sandboxing, carefully checking labeled, untrusted assertions from each connected client before relaying them to peers in the server-side dataspace. This is a core element in the enforcement of the application's security policy, closely related to the “firewalls” described in section <a class="cross-reference" href="#par:Firewalls">11.3</a>.</p><p id="x_C_0_0_0_15">Labeling of received assertions has a second benefit: it eliminates any ambiguity between assertions pertaining to the operation of the broker itself and its websocket connection (which, recall, is just another actor, communicating with the broker via assertions and messages) and assertions pertaining to the dataspace on the other end of the websocket link. In particular, events bearing assertions describing local websocket activity are clearly separated from events describing remote assertions. The per-connection constructor used to label received assertions acts as a form of quotation.</p>
<h3 id="x_D_0_0_0_1"><a name="toc_D"></a><span class="counter appendix"><span>D</span></span><span class="heading-text appendix"><a class="label-anchor" href="#APPENDIX:DATAFLOW"></a><a name="APPENDIX:DATAFLOW"></a>Racket Dataflow Library</span></h3><p id="x_D_0_0_0_2">This appendix presents a listing of the Racket dataflow library discussed in section <a class="cross-reference" href="#subsec:Dataflow">7.3.3</a>.</p><p id="x_D_0_0_0_3">The <tt>dataflow.rkt</tt> source file implements the dataflow mechanism proper.</p><p id="x_D_0_0_0_5">
<pre class="listing" id="x_D_0_0_0_4"><code>#lang racket/base
(provide dataflow-graph?
make-dataflow-graph
dataflow-graph-edges-forward
current-dataflow-subject-id
dataflow-record-observation!
dataflow-record-damage!
dataflow-forget-subject!
dataflow-repair-damage!)
(require racket/set)
(require "support/hash.rkt")
(struct dataflow-graph (edges-forward ;; object-id -&gt; (Setof subject-id)
edges-reverse ;; subject-id -&gt; (Setof object-id)
damaged-nodes) ;; Setof object-id
#:mutable)
(define current-dataflow-subject-id (make-parameter #f))
(define (make-dataflow-graph)
(dataflow-graph (hash)
(hash)
(set)))
(define (dataflow-record-observation! g object-id)
(define subject-id (current-dataflow-subject-id))
(when subject-id
(define fwd (dataflow-graph-edges-forward g))
(set-dataflow-graph-edges-forward! g (hashset-add fwd object-id subject-id))
(define rev (dataflow-graph-edges-reverse g))
(set-dataflow-graph-edges-reverse! g (hashset-add rev subject-id object-id))))
(define (dataflow-record-damage! g object-id)
(set-dataflow-graph-damaged-nodes! g
(set-add (dataflow-graph-damaged-nodes g) object-id)))
(define (dataflow-forget-subject! g subject-id)
(define rev (dataflow-graph-edges-reverse g))
(define subject-objects (hash-ref rev subject-id set))
(set-dataflow-graph-edges-reverse! g (hash-remove rev subject-id))
(for [(object-id (in-set subject-objects))]
(define fwd (dataflow-graph-edges-forward g))
(set-dataflow-graph-edges-forward! g (hashset-remove fwd object-id subject-id))))
(define (dataflow-repair-damage! g repair-node!)
(define repaired-this-round (set))
(let loop ()
(define workset (dataflow-graph-damaged-nodes g))
(set-dataflow-graph-damaged-nodes! g (set))
(let ((already-damaged (set-intersect workset repaired-this-round)))
(when (not (set-empty? already-damaged))
(log-warning "Cyclic dependencies involving ids ~v\n" already-damaged)))
(set! workset (set-subtract workset repaired-this-round))
(set! repaired-this-round (set-union repaired-this-round workset))
(when (not (set-empty? workset))
(for [(object-id (in-set workset))]
(define subjects (hash-ref (dataflow-graph-edges-forward g) object-id set))
(for [(subject-id (in-set subjects))]
(dataflow-forget-subject! g subject-id)
(parameterize ((current-dataflow-subject-id subject-id))
(repair-node! subject-id))))
(loop))))
</code></pre></p><p id="x_D_0_0_0_6">The <tt>support/hash.rkt</tt> source file implements support routines for maintaining hash-tables mapping keys to sets of values.</p><p id="x_D_0_0_0_8">
<pre class="listing" id="x_D_0_0_0_7"><code>#lang racket/base
(provide hash-set/remove
hashset-member?
hashset-add
hashset-remove)
(require racket/set)
(define (hash-set/remove ht key val [default-val #f] #:compare [compare equal?])
(if (compare val default-val)
(hash-remove ht key)
(hash-set ht key val)))
(define (hashset-member? ht key val)
(define s (hash-ref ht key #f))
(and s (set-member? s val)))
(define (hashset-add ht key val #:set [set set])
(hash-set ht key (set-add (hash-ref ht key set) val)))
(define (hashset-remove ht k v)
(define old (hash-ref ht k #f))
(if old
(let ((new (set-remove old v)))
(if (set-empty? new)
(hash-remove ht k)
(hash-set ht k new)))
ht))
</code></pre></p></p><p id="x_D_0_0_0_10"><h3 class="bibliography">Bibliography</h3>
<div class="bibliography" id="x_D_0_0_0_11"><div id="bib-Agha1986" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-location has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Agha, Gul</span><span class="bibfield year">1986</span><span class="bibfield title">Actors: a model of concurrent computation in distributed systems</span><span class="bibfield location">Cambridge, Massachusetts</span><span class="bibfield publisher">MIT Press</span><span class="anchors">[<a class="link-to-citation" href="#cite-21">21</a>, <a class="link-to-citation" href="#cite-50">50</a>, <a class="link-to-citation" href="#cite-61">61</a>]</span></div></div><div id="bib-Agha1997" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Agha, Gul A., Ian A. Mason, Scott F. Smith and Carolyn L. Talcott</span><span class="bibfield year">1997</span><span class="bibfield title">A Foundation for Actor Computation</span><span class="bibfield journaltitle">Journal of Functional Programming</span><span class="bibfield volume">7</span><span class="bibfield number">1</span><span class="bibfield pages">172</span><span class="anchors">[<a class="link-to-citation" href="#cite-22">22</a>, <a class="link-to-citation" href="#cite-51">51</a>, <a class="link-to-citation" href="#cite-94">94</a>, <a class="link-to-citation" href="#cite-282">282</a>, <a class="link-to-citation" href="#cite-284">284</a>]</span></div></div><div id="bib-Joule1995" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-institution has-number no-note no-howpublished no-date no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Agorics, Inc.</span><span class="bibfield year">1995</span><span class="bibfield title">Joule: Distributed Application Foundations</span><span class="bibfield institution dotted">Agorics, Inc.</span><span class="bibfield number">ADd.003.4P</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-30">30</a>]</span><a class="bibfield url" href="http://www.erights.org/history/joule/">link</a></div></div><div id="bib-Alexander1977" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-location has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Alexander, Christopher, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King and Shlomo Angel</span><span class="bibfield year">1977</span><span class="bibfield title">A Pattern Language: Towns, Buildings, Construction</span><span class="bibfield location">New York</span><span class="bibfield publisher">Oxford University Press</span><span class="anchors">[<a class="link-to-citation" href="#cite-211">211</a>]</span></div></div><div id="bib-Alur2007" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Alur, Rajeev</span><span class="bibfield year">2007</span><span class="bibfield title">Marrying Words and Trees</span><span class="bibfield booktitle">Symp. on Principles of Database Systems</span><span class="bibfield location">Beijing, China</span><span class="bibfield pages">233242</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-155">155</a>]</span></div></div><div id="bib-Alur2009" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Alur, Rajeev and P. Madhusudan</span><span class="bibfield year">2009</span><span class="bibfield title">Adding nesting structure to words</span><span class="bibfield journaltitle">Journal of the ACM</span><span class="bibfield volume">56</span><span class="bibfield number">3</span><span class="bibfield pages">16:116:43</span><span class="bibfield date">May</span><span class="anchors">[<a class="link-to-citation" href="#cite-133">133</a>, <a class="link-to-citation" href="#cite-154">154</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1516512.1516518">doi</a></div></div><div id="bib-Alvaro2011" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Alvaro, Peter, Neil Conway, Joseph M. Hellerstein and William R. Marczak</span><span class="bibfield year">2011</span><span class="bibfield title">Consistency Analysis in Bloom: a CALM and Collected Approach</span><span class="bibfield booktitle">5th Biennial Conference on Innovative Data Systems Research (CIDR '11)</span><span class="anchors">[<a class="link-to-citation" href="#cite-32">32</a>, <a class="link-to-citation" href="#cite-182">182</a>, <a class="link-to-citation" href="#cite-184">184</a>]</span></div></div><div id="bib-Andersson1995" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Andersson, Arne and Thomas Ottmann</span><span class="bibfield year">1995</span><span class="bibfield title">New Tight Bounds on Uniquely Represented Dictionaries</span><span class="bibfield journaltitle">SIAM Journal on Computing</span><span class="bibfield volume">24</span><span class="bibfield number">5</span><span class="bibfield pages">10911103</span><span class="anchors">[<a class="link-to-citation" href="#cite-146">146</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1137/S0097539792241102">doi</a></div></div><div id="bib-Armstrong2003" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-number has-date no-note no-howpublished no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Armstrong, Joe</span><span class="bibfield year">2003</span><span class="bibfield title">Making reliable distributed systems in the presence of software errors</span><span class="bibfield institution">Royal Institute of Technology, Stockholm</span><span class="bibfield number">December</span><span class="bibfield date">December</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-14">14</a>, <a class="link-to-citation" href="#cite-33">33</a>, <a class="link-to-citation" href="#cite-56">56</a>, <a class="link-to-citation" href="#cite-98">98</a>, <a class="link-to-citation" href="#cite-248">248</a>]</span><a class="bibfield url" href="http://erlang.org/download/armstrong_thesis_2003.pdf">link</a></div></div><div id="bib-Bach2005" class="bibliography-entry"><div class="entrytype-incollection editor-count-2 no-dayofmonth has-author has-title has-booktitle has-editor no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle"><span class="bibfield author">Bach, Kent</span><span class="bibfield year">2005</span><span class="bibfield title">The Top 10 Misconceptions About Implicature</span><span class="bibfield booktitle">Festschrift for Larry Horn</span><span class="bibfield editor">Betty Birner and Gregory Ward</span><span class="anchors">[<a class="link-to-citation" href="#cite-6">6</a>]</span></div></div><div id="bib-Bainomugisha2013" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Bainomugisha, Engineer, Andoni Lombide Carreton, Tom Van Cutsem, Stijn Mostinckx and Wolfgang De Meuter</span><span class="bibfield year">2013</span><span class="bibfield title">A Survey on Reactive Programming</span><span class="bibfield journaltitle">ACM Computing Surveys</span><span class="bibfield volume">45</span><span class="bibfield number">4</span><span class="bibfield pages">134</span><span class="anchors">[<a class="link-to-citation" href="#cite-86">86</a>, <a class="link-to-citation" href="#cite-168">168</a>, <a class="link-to-citation" href="#cite-197">197</a>, <a class="link-to-citation" href="#cite-200">200</a>, <a class="link-to-citation" href="#cite-203">203</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2501654.2501666">doi</a></div></div><div id="bib-Baker1992a" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Baker, Henry G.</span><span class="bibfield year">1992</span><span class="bibfield title">Lively linear Lisp: "look ma, no garbage!"</span><span class="bibfield journaltitle">ACM SIGPLAN Notices</span><span class="bibfield volume">27</span><span class="bibfield number">8</span><span class="bibfield pages">8998</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-138">138</a>]</span><a class="bibfield url" href="http://www.pipeline.com/~hbaker1/LinearLisp.html">link</a></div></div><div id="bib-Baker1993" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Baker, Henry G.</span><span class="bibfield year">1993</span><span class="bibfield title">Equal rights for functional objects or, the more things change, the more they are the same</span><span class="bibfield journaltitle">ACM SIGPLAN OOPS Messenger</span><span class="bibfield volume">4</span><span class="bibfield number">4</span><span class="bibfield pages">227</span><span class="anchors">[<a class="link-to-citation" href="#cite-162">162</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/165593.165596">doi</a></div></div><div id="bib-Bakken1995" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Bakken, David E. and Richard D. Schlichting</span><span class="bibfield year">1995</span><span class="bibfield title">Supporting Fault-Tolerant Parallel Programming in Linda</span><span class="bibfield journaltitle">IEEE Transactions on Parallel and Distributed Systems</span><span class="bibfield volume">6</span><span class="bibfield number">3</span><span class="bibfield pages">287302</span><span class="anchors">[<a class="link-to-citation" href="#cite-77">77</a>, <a class="link-to-citation" href="#cite-79">79</a>, <a class="link-to-citation" href="#cite-295">295</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/71.372777">doi</a></div></div><div id="bib-Baldoni2005" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-institution no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Baldoni, Roberto, Leonardo Querzoni and Antonino Virgillito</span><span class="bibfield year">2005</span><span class="bibfield title">Distributed Event Routing in Publish/Subscribe Communication Systems: a Survey</span><span class="bibfield institution">Dipartimento di Informatica e Sistemistica, Università di Roma "La Sapienzia"</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-153">153</a>]</span><a class="bibfield url" href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.106.1108">link</a></div></div><div id="bib-Barendregt1984" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-edition has-location has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-institution no-organization no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Barendregt, H. P.</span><span class="bibfield year">1984</span><span class="bibfield title">The Lambda Calculus: Its Syntax and Semantics</span><span class="bibfield edition dotted">rev.</span><span class="bibfield location">Amsterdam, The Netherlands</span><span class="bibfield publisher">North-Holland</span><span class="anchors">[<a class="link-to-citation" href="#cite-106">106</a>]</span></div></div><div id="bib-Bass1998" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Bass, Len, Paul Clements and Rick Kazman</span><span class="bibfield year">1998</span><span class="bibfield title">Software Architecture in Practice</span><span class="bibfield publisher">Addison-Wesley</span><span class="anchors">[<a class="link-to-citation" href="#cite-224">224</a>]</span></div></div><div id="bib-Beck1987" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Beck, Kent and Ward Cunningham</span><span class="bibfield year">1987</span><span class="bibfield title">Using pattern languages for object-oriented programs</span><span class="bibfield booktitle">OOPSLA Workshop on Specification and Design for Object-Oriented Programming</span><span class="bibfield date">September</span><span class="anchors">[<a class="link-to-citation" href="#cite-209">209</a>, <a class="link-to-citation" href="#cite-212">212</a>]</span><a class="bibfield url" href="http://c2.com/doc/oopsla87.html">link</a></div></div><div id="bib-Bernstein2004" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Bernstein, Daniel J.</span><span class="bibfield year">2004</span><span class="bibfield title">Crit-bit trees</span><span class="anchors">[<a class="link-to-citation" href="#cite-141">141</a>]</span><a class="bibfield url" href="http://cr.yp.to/critbit.html">link</a></div></div><div id="bib-Berry1992" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Berry, Gérard and Georges Gonthier</span><span class="bibfield year">1992</span><span class="bibfield title">The Esterel synchronous programming language: design, semantics, implementation</span><span class="bibfield journaltitle">Science of Computer Programming</span><span class="bibfield volume">19</span><span class="bibfield number">2</span><span class="bibfield pages">87152</span><span class="anchors">[<a class="link-to-citation" href="#cite-110">110</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/0167-6423(92)90005-V">doi</a></div></div><div id="bib-Bloom1970" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Bloom, Burton H.</span><span class="bibfield year">1970</span><span class="bibfield title">Space/time trade-offs in hash coding with allowable errors</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield volume">13</span><span class="bibfield number">7</span><span class="bibfield pages">422426</span><span class="bibfield date">July</span><span class="anchors">[<a class="link-to-citation" href="#cite-105">105</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/362686.362692">doi</a></div></div><div id="bib-BrinchHansen1993" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Brinch Hansen, Per</span><span class="bibfield year">1993</span><span class="bibfield title">Monitors and Concurrent Pascal: A Personal History</span><span class="bibfield journaltitle">ACM SIGPLAN Notices</span><span class="bibfield volume">28</span><span class="bibfield number">3</span><span class="bibfield pages">135</span><span class="anchors">[<a class="link-to-citation" href="#cite-44">44</a>, <a class="link-to-citation" href="#cite-219">219</a>, <a class="link-to-citation" href="#cite-223">223</a>]</span></div></div><div id="bib-Busi2001" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Busi, Nadia and Gianluigi Zavattaro</span><span class="bibfield year">2001</span><span class="bibfield title dotted">Publish/subscribe vs. shared dataspace coordination infrastructures: Is it just a matter of taste?</span><span class="bibfield booktitle">Proceedings Tenth IEEE International Workshop on Enabling Technologies: Infrastructure for Collaborative Enterprises. WET ICE 2001</span><span class="bibfield location">Cambridge, Massachusetts</span><span class="anchors">[<a class="link-to-citation" href="#cite-74">74</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/ENABL.2001.953438">doi</a></div></div><div id="bib-Caires2010" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Caires, Luís and Hugo Torres Vieira</span><span class="bibfield year">2010</span><span class="bibfield title">Analysis of Service Oriented Software Systems with the Conversation Calculus</span><span class="bibfield booktitle">Proceedings of the 7th International Conference on Formal Aspects of Component Software</span><span class="bibfield pages">633</span><span class="anchors">[<a class="link-to-citation" href="#cite-278">278</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-642-27269-1_2">doi</a></div></div><div id="bib-Caldwell2017" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-howpublished no-note no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Caldwell, Sam, Tony Garnock-Jones and Matthias Felleisen</span><span class="bibfield year">2017</span><span class="bibfield title">Coordinating Concurrent Conversations</span><span class="bibfield howpublished">Unpublished draft</span><span class="anchors">[<a class="link-to-citation" href="#cite-101">101</a>, <a class="link-to-citation" href="#cite-107">107</a>, <a class="link-to-citation" href="#cite-109">109</a>, <a class="link-to-citation" href="#cite-293">293</a>]</span></div></div><div id="bib-Callsen1994" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Callsen, Christian J. and Gul Agha</span><span class="bibfield year">1994</span><span class="bibfield title">Open Heterogeneous Computing in ActorSpace</span><span class="bibfield journaltitle">J. Parallel and Distributed Computing</span><span class="bibfield volume">21</span><span class="bibfield number">3</span><span class="bibfield pages">300289</span><span class="anchors">[<a class="link-to-citation" href="#cite-40">40</a>, <a class="link-to-citation" href="#cite-285">285</a>, <a class="link-to-citation" href="#cite-288">288</a>]</span></div></div><div id="bib-Cardelli2000a" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Cardelli, Luca and Andrew D. Gordon</span><span class="bibfield year">2000</span><span class="bibfield title">Mobile ambients</span><span class="bibfield journaltitle">Theoretical Computer Science</span><span class="bibfield volume">240</span><span class="bibfield number">1</span><span class="bibfield pages">177213</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-280">280</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/S0304-3975(99)00231-5">doi</a></div></div><div id="bib-Carriero1994" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Carriero, Nicholas J., David Gelernter, Timothy G. Mattson and Andrew H. Sherman</span><span class="bibfield year">1994</span><span class="bibfield title">The Linda alternative to message-passing systems</span><span class="bibfield journaltitle">Parallel Computing</span><span class="bibfield volume">20</span><span class="bibfield number">4</span><span class="bibfield pages">633655</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-17">17</a>, <a class="link-to-citation" href="#cite-66">66</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/0167-8191(94)90032-9">doi</a></div></div><div id="bib-Carzaniga2000" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Carzaniga, Antonio, David S. Rosenblum and Alexander L. Wolf</span><span class="bibfield year">2000</span><span class="bibfield title">Achieving scalability and expressiveness in an Internet-scale event notification service</span><span class="bibfield booktitle">Proceedings of the nineteenth annual ACM symposium on Principles of distributed computing - PODC '00</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield pages">219227</span><span class="bibfield date">July</span><span class="anchors">[<a class="link-to-citation" href="#cite-188">188</a>, <a class="link-to-citation" href="#cite-274">274</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/343477.343622">doi</a></div></div><div id="bib-Chambers1992" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Chambers, Craig</span><span class="bibfield year">1992</span><span class="bibfield title">The Design and Implementation of the Self Compiler, an Optimizing Compiler for Object-Oriented Programming Languages</span><span class="bibfield institution">Stanford</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-252">252</a>]</span></div></div><div id="bib-Clark1988" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Clark, David D.</span><span class="bibfield year">1988</span><span class="bibfield title">The design philosophy of the DARPA internet protocols</span><span class="bibfield journaltitle">ACM SIGCOMM Computer Communication Review</span><span class="bibfield volume">18</span><span class="bibfield number">4</span><span class="bibfield pages">106114</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-97">97</a>, <a class="link-to-citation" href="#cite-255">255</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/52325.52336">doi</a></div></div><div id="bib-Clark2001" class="bibliography-entry"><div class="entrytype-book editor-count-2 no-dayofmonth has-editor has-title has-publisher has-date no-note no-howpublished no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-author"><span class="bibfield editor">Clark, James and Makoto Murata</span><span class="bibfield year">2001</span><span class="bibfield title">RELAX NG Specification</span><span class="bibfield publisher">OASIS</span><span class="bibfield date">December</span><span class="anchors">[<a class="link-to-citation" href="#cite-149">149</a>]</span><a class="bibfield url" href="http://relaxng.org/spec-20011203.html">link</a></div></div><div id="bib-Clements2001" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Clements, Paul, Rick Kazman and Mark Klein</span><span class="bibfield year">2001</span><span class="bibfield title">Evaluating Software Architectures: Methods and Case Studies</span><span class="bibfield publisher">Addison-Wesley</span><span class="anchors">[<a class="link-to-citation" href="#cite-225">225</a>]</span></div></div><div id="bib-Clinger1981" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Clinger, William Douglas</span><span class="bibfield year">1981</span><span class="bibfield title">Foundations of Actor Semantics</span><span class="bibfield institution">Massachusetts Institute of Technology</span><span class="bibfield type-PhD dissertation"></span><span class="anchors">[<a class="link-to-citation" href="#cite-100">100</a>]</span></div></div><div id="bib-Conway2012" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-publisher has-date no-note no-howpublished no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Conway, Neil, William Marczak, Peter Alvaro, Joseph M. Hellerstein and David Maier</span><span class="bibfield year">2012</span><span class="bibfield title">Logic and lattices for distributed programming</span><span class="bibfield publisher">University of California at Berkeley</span><span class="bibfield date">June</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-180">180</a>, <a class="link-to-citation" href="#cite-181">181</a>, <a class="link-to-citation" href="#cite-183">183</a>]</span><a class="bibfield url" href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-167.html">link</a></div></div><div id="bib-Cooper2006" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-1 no-dayofmonth has-author has-title has-booktitle has-editor has-location has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle"><span class="bibfield author">Cooper, Gregory H. and Shriram Krishnamurthi</span><span class="bibfield year">2006</span><span class="bibfield title">Embedding dynamic dataflow in a call-by-value language</span><span class="bibfield booktitle">European Symposium on Programming (ESOP 2006)</span><span class="bibfield editor">Peter Sestoft</span><span class="bibfield location">Vienna, Austria</span><span class="bibfield publisher">Springer-Verlag</span><span class="bibfield pages">294308</span><span class="bibfield date">March</span><span class="anchors">[<a class="link-to-citation" href="#cite-167">167</a>, <a class="link-to-citation" href="#cite-204">204</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/11693024_20">doi</a></div></div><div id="bib-Coq:manual" class="bibliography-entry"><div class="entrytype-manual editor-count-0 no-dayofmonth has-author has-title has-organization has-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Coq development team</span><span class="bibfield year">2004</span><span class="bibfield title">The Coq proof assistant reference manual</span><span class="bibfield organization">LogiCal Project</span><span class="bibfield note">Ver. 8.0</span><span class="anchors">[<a class="link-to-citation" href="#cite-103">103</a>]</span><a class="bibfield url" href="http://coq.inria.fr">link</a></div></div><div id="bib-Cormen2009" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-edition has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-journaltitle no-booktitle no-editor"><span class="bibfield author">Cormen, Thomas H., Charles E. Leiserson, Ronald L. Rivest and Clifford Stein</span><span class="bibfield year">2009</span><span class="bibfield title">Introduction to Algorithms</span><span class="bibfield edition">3</span><span class="bibfield publisher">MIT Press</span><span class="bibfield pages">1312</span><span class="anchors">[<a class="link-to-citation" href="#cite-132">132</a>, <a class="link-to-citation" href="#cite-144">144</a>]</span></div></div><div id="bib-Culpepper2010" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Culpepper, Ryan and Matthias Felleisen</span><span class="bibfield year">2010</span><span class="bibfield title">Fortifying macros</span><span class="bibfield booktitle">Proceedings of the 15th ACM SIGPLAN International Conference on Functional Programming</span><span class="bibfield publisher">ACM</span><span class="bibfield pages">235246</span><span class="anchors">[<a class="link-to-citation" href="#cite-117">117</a>, <a class="link-to-citation" href="#cite-165">165</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1863543.1863577">doi</a></div></div><div id="bib-Day2008" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Day, John</span><span class="bibfield year">2008</span><span class="bibfield title">Patterns in Network Architecture: A Return to Fundamentals</span><span class="bibfield publisher">Prentice Hall</span><span class="anchors">[<a class="link-to-citation" href="#cite-1">1</a>]</span></div></div><div id="bib-DeKoster2016" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">De Koster, Joeri, Stefan Marr, Tom Van Cutsem and Theo D'Hondt</span><span class="bibfield year">2016</span><span class="bibfield title">Domains: Sharing state in the communicating event-loop actor model</span><span class="bibfield journaltitle">Computer Languages, Systems &amp; Structures</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-23">23</a>, <a class="link-to-citation" href="#cite-52">52</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/j.cl.2016.01.003">doi</a></div></div><div id="bib-DeKoster2016b" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">De Koster, Joeri, Tom Van Cutsem and Wolfgang De Meuter</span><span class="bibfield year">2016</span><span class="bibfield title">43 Years of Actors: a Taxonomy of Actor Models and Their Key Properties</span><span class="bibfield booktitle">Proc. AGERE</span><span class="bibfield location">Amsterdam, The Netherlands</span><span class="bibfield pages">3140</span><span class="bibfield date">October</span><span class="anchors">[<a class="link-to-citation" href="#cite-63">63</a>, <a class="link-to-citation" href="#cite-283">283</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/3001886.3001890">doi</a></div></div><div id="bib-DelaBriandais1959" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">de la Briandais, Rene</span><span class="bibfield year">1959</span><span class="bibfield title">File Searching Using Variable Length Keys</span><span class="bibfield booktitle">Papers Presented at the the March 3-5, 1959, Western Joint Computer Conference</span><span class="bibfield location">San Francisco, California</span><span class="bibfield pages">295298</span><span class="bibfield date">March</span><span class="anchors">[<a class="link-to-citation" href="#cite-128">128</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1457838.1457895">doi</a></div></div><div id="bib-Denicola2016" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Denicola, Domenic</span><span class="bibfield year">2016</span><span class="bibfield title">Cancelable Promises</span><span class="anchors">[<a class="link-to-citation" href="#cite-239">239</a>, <a class="link-to-citation" href="#cite-240">240</a>]</span><a class="bibfield url" title="Accessed: 12 October 2017" href="https://github.com/tc39/proposal-cancelable-promises/tree/0e769fda8e16bff0feffe964fddc43dcd86668ba">link</a></div></div><div id="bib-Diao2003" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Diao, Yanlei, Mehmet Altinel, Michael J. Franklin, Hao Zhang and Peter Fischer</span><span class="bibfield year">2003</span><span class="bibfield title">Path sharing and predicate evaluation for high-performance XML filtering</span><span class="bibfield journaltitle">ACM Transactions on Database Systems</span><span class="bibfield volume">28</span><span class="bibfield number">4</span><span class="bibfield pages">467516</span><span class="anchors">[<a class="link-to-citation" href="#cite-157">157</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/958942.958947">doi</a></div></div><div id="bib-Dimoulas2016" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Dimoulas, Christos, Max S. New, Robert Bruce Findler and Matthias Felleisen</span><span class="bibfield year">2016</span><span class="bibfield title">Oh Lord, Please Don't Let Contracts Be Misunderstood</span><span class="bibfield journaltitle">Proceedings of the 21st ACM SIGPLAN International Conference on Functional Programming - ICFP 2016</span><span class="anchors">[<a class="link-to-citation" href="#cite-296">296</a>]</span><a class="bibfield doi" href="https://dx.doi.org/http://dx.doi.org/10.1145">doi</a></div></div><div id="bib-Donnelly2008" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Donnelly, Kevin and Matthew Fluet</span><span class="bibfield year">2008</span><span class="bibfield title">Transactional events</span><span class="bibfield journaltitle">Journal of Functional Programming</span><span class="bibfield volume">18</span><span class="bibfield number">5-6</span><span class="bibfield pages">649706</span><span class="anchors">[<a class="link-to-citation" href="#cite-53">53</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1017/S0956796808006916">doi</a></div></div><div id="bib-rfc2131" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-organization has-publisher has-number has-date has-howpublished no-note no-pages no-issue no-volume no-location no-institution no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Droms, R.</span><span class="bibfield year">1997</span><span class="bibfield title">Dynamic Host Configuration Protocol</span><span class="bibfield organization">Internet Engineering Task Force</span><span class="bibfield publisher">IETF</span><span class="bibfield number">2131</span><span class="bibfield date">March</span><span class="bibfield howpublished">RFC 2131 (Draft Standard)</span><span class="anchors">[<a class="link-to-citation" href="#cite-244">244</a>]</span><a class="bibfield url" href="http://www.ietf.org/rfc/rfc2131.txt">link</a></div></div><div id="bib-Dunn" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Dunn, Jeffrey</span><span class="bibfield year">2017</span><span class="bibfield title">Epistemic Consequentialism</span><span class="bibfield journaltitle">Internet Encyclopedia of Philosophy</span><span class="anchors">[<a class="link-to-citation" href="#cite-10">10</a>]</span><a class="bibfield url" href="http://www.iep.utm.edu/epis-con/">link</a></div></div><div id="bib-Eastlund2009" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Eastlund, Carl and Matthias Felleisen</span><span class="bibfield year">2009</span><span class="bibfield title">Automatic verification for interactive graphical programs</span><span class="bibfield booktitle">Proceedings of the 8th International Workshop on the ACL2 Theorem Prover and its Applications</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield pages">3341</span><span class="bibfield date">May</span><span class="anchors">[<a class="link-to-citation" href="#cite-272">272</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1637837.1637843">doi</a></div></div><div id="bib-ECMA-262" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-edition has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-journaltitle no-booktitle no-editor"><span class="bibfield author">ECMA</span><span class="bibfield year">2015</span><span class="bibfield title">ECMA-262: ECMAScript 2015 language specification</span><span class="bibfield edition">6th</span><span class="bibfield publisher">Ecma International</span><span class="anchors">[<a class="link-to-citation" href="#cite-46">46</a>, <a class="link-to-citation" href="#cite-241">241</a>]</span></div></div><div id="bib-Elliott1997" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-location has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Elliott, Conal and Paul Hudak</span><span class="bibfield year">1997</span><span class="bibfield title">Functional reactive animation</span><span class="bibfield journaltitle">Proceedings of the second ACM SIGPLAN international conference on Functional programming - ICFP '97</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield pages">263273</span><span class="anchors">[<a class="link-to-citation" href="#cite-85">85</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/258948.258973">doi</a></div></div><div id="bib-rfc2693" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-organization has-publisher has-number has-date has-howpublished no-note no-pages no-issue no-volume no-location no-institution no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Ellison, C., B. Frantz, B. Lampson, R. Rivest, B. Thomas and T. Ylonen</span><span class="bibfield year">1999</span><span class="bibfield title">SPKI Certificate Theory</span><span class="bibfield organization">Internet Engineering Task Force</span><span class="bibfield publisher">IETF</span><span class="bibfield number">2693</span><span class="bibfield date">September</span><span class="bibfield howpublished">RFC 2693 (Experimental)</span><span class="anchors">[<a class="link-to-citation" href="#cite-297">297</a>]</span><a class="bibfield url" href="http://www.ietf.org/rfc/rfc2693.txt">link</a></div></div><div id="bib-Elphinstone2013" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Elphinstone, Kevin and Gernot Heiser</span><span class="bibfield year">2013</span><span class="bibfield title dotted">From L3 to seL4 -- What Have We Learnt in 20 Years of L4 Microkernels?</span><span class="bibfield journaltitle">ACM SIGOPS Symposium on Operating Systems Principles (SOSP)</span><span class="bibfield pages">133150</span><span class="anchors">[<a class="link-to-citation" href="#cite-82">82</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2517349.2522720">doi</a></div></div><div id="bib-Ene2001" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Ene, Cristian and Traian Muntean</span><span class="bibfield year">2001</span><span class="bibfield title">A Broadcast-based Calculus for Communicating Systems</span><span class="bibfield booktitle">Workshop on Formal Methods for Parallel Programming</span><span class="bibfield location">San Francisco, California</span><span class="anchors">[<a class="link-to-citation" href="#cite-290">290</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/IPDPS.2001.925136">doi</a><a class="bibfield url" href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.2165">link</a></div></div><div id="bib-EricssonAB2017" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Ericsson AB</span><span class="bibfield year">2017</span><span class="bibfield title">Erlang Run-Time System Application (ERTS) Reference Manual, version 9.0</span><span class="anchors">[<a class="link-to-citation" href="#cite-250">250</a>]</span><a class="bibfield url" href="http://erlang.org/doc/apps/erts/">link</a></div></div><div id="bib-OtpDesignPrinciples" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor no-author"><span class="bibfield title">Erlang/OTP Design Principles</span><span class="bibfield year">2012</span><span class="anchors">[<a class="link-to-citation" href="#cite-116">116</a>]</span><a class="bibfield url" href="http://www.erlang.org/doc/design_principles/des_princ.html">link</a></div></div><div id="bib-Ershov1958" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Ershov, A. P.</span><span class="bibfield year">1958</span><span class="bibfield title">On Programming of Arithmetic Operations</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield volume">1</span><span class="bibfield number">8</span><span class="bibfield pages">36</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-135">135</a>, <a class="link-to-citation" href="#cite-139">139</a>]</span><a class="bibfield url" href="http://www.pipeline.com/~hbaker1/othergc/Ershov-Hash.txt">link</a></div></div><div id="bib-Eugster2003" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Eugster, Patrick Th., Pascal A. Felber, Rachid Guerraoui and Anne-Marie Kermarrec</span><span class="bibfield year">2003</span><span class="bibfield title">The many faces of publish/subscribe</span><span class="bibfield journaltitle">ACM Computing Surveys</span><span class="bibfield volume">35</span><span class="bibfield number">2</span><span class="bibfield pages">114131</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-76">76</a>, <a class="link-to-citation" href="#cite-152">152</a>, <a class="link-to-citation" href="#cite-192">192</a>, <a class="link-to-citation" href="#cite-292">292</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/857076.857078">doi</a></div></div><div id="bib-Eugster2001" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Eugster, Patrick Th., Rachid Guerraoui and Christian Heide Damm</span><span class="bibfield year">2001</span><span class="bibfield title">On objects and events</span><span class="bibfield booktitle">Proceedings of the 16th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications</span><span class="bibfield location">Tampa Bay, Florida</span><span class="bibfield pages">254269</span><span class="bibfield date">October</span><span class="anchors">[<a class="link-to-citation" href="#cite-231">231</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/504311.504301">doi</a></div></div><div id="bib-Fagin2004" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Fagin, Ronald, Joseph Y. Halpern, Yoram Moses and Moshe Vardi</span><span class="bibfield year">2004</span><span class="bibfield title">Reasoning About Knowledge</span><span class="bibfield publisher">MIT Press</span><span class="bibfield pages">536</span><span class="anchors">[<a class="link-to-citation" href="#cite-11">11</a>, <a class="link-to-citation" href="#cite-28">28</a>, <a class="link-to-citation" href="#cite-257">257</a>]</span></div></div><div id="bib-Felleisen1988" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Felleisen, Matthias</span><span class="bibfield year">1988</span><span class="bibfield title">The Theory and Practice of First-Class Prompts</span><span class="bibfield booktitle">Proc. Principles of Programming Languages</span><span class="bibfield location">San Diego, California</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-120">120</a>]</span></div></div><div id="bib-Felleisen1991" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Felleisen, Matthias</span><span class="bibfield year">1991</span><span class="bibfield title">On the expressive power of programming languages</span><span class="bibfield journaltitle">Science of Computer Programming</span><span class="bibfield volume">17</span><span class="bibfield number">1--3</span><span class="bibfield pages">3575</span><span class="anchors">[<a class="link-to-citation" href="#cite-75">75</a>, <a class="link-to-citation" href="#cite-208">208</a>, <a class="link-to-citation" href="#cite-218">218</a>]</span></div></div><div id="bib-Felleisen1988a" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Felleisen, Matthias, Mitchell Wand, Daniel P. Friedman and Bruce F. Duba</span><span class="bibfield year">1988</span><span class="bibfield title">Abstract Continuations: A Mathematical Semantics for Handling Full Functional Jumps</span><span class="bibfield booktitle">ACM Conf. on LISP and Functional Programming</span><span class="bibfield location">Snowbird, Utah</span><span class="bibfield pages">5262</span><span class="bibfield date">July</span><span class="anchors">[<a class="link-to-citation" href="#cite-119">119</a>, <a class="link-to-citation" href="#cite-259">259</a>]</span></div></div><div id="bib-Felleisen2009a" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-location has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Felleisen, Matthias, Robert Bruce Findler and Matthew Flatt</span><span class="bibfield year">2009</span><span class="bibfield title">Semantics Engineering with PLT Redex</span><span class="bibfield location">Cambridge, Massachusetts</span><span class="bibfield publisher">MIT Press</span><span class="bibfield pages">502</span><span class="anchors">[<a class="link-to-citation" href="#cite-99">99</a>, <a class="link-to-citation" href="#cite-102">102</a>]</span></div></div><div id="bib-Felleisen2009" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Felleisen, Matthias, Robert Bruce Findler, Matthew Flatt and Shriram Krishnamurthi</span><span class="bibfield year">2009</span><span class="bibfield title">A Functional I/O System</span><span class="bibfield booktitle">ICFP</span><span class="anchors">[<a class="link-to-citation" href="#cite-163">163</a>, <a class="link-to-citation" href="#cite-261">261</a>, <a class="link-to-citation" href="#cite-262">262</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1596550.1596561">doi</a><a class="bibfield url" href="http://www.ccis.northeastern.edu/scheme/pubs/icfp09-fffk.pdf">link</a></div></div><div id="bib-Fiege2002" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Fiege, Ludger, Mira Mezini, Gero Mühl and Alejandro P. Buchmann</span><span class="bibfield year">2002</span><span class="bibfield title">Engineering Event-Based Systems with Scopes</span><span class="bibfield booktitle">Proc. of the European Conference on Object-Oriented Programming</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-291">291</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/3-540-47993-7_14">doi</a></div></div><div id="bib-Filliatre2006" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Filliâtre, Jean-Christophe and Sylvain Conchon</span><span class="bibfield year">2006</span><span class="bibfield title">Type-Safe Modular Hash-Consing</span><span class="bibfield booktitle">Proceedings of the 2006 workshop on ML</span><span class="bibfield location">Portland, Oregon</span><span class="bibfield publisher">ACM</span><span class="bibfield pages">1219</span><span class="bibfield date">September</span><span class="anchors">[<a class="link-to-citation" href="#cite-137">137</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1159876.1159880">doi</a></div></div><div id="bib-Finch2016" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume no-note no-howpublished no-date no-pages no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Finch, Tony</span><span class="bibfield year">2016</span><span class="bibfield title">QP tries are smaller and faster than crit-bit trees</span><span class="bibfield journaltitle">Tiny Transactions on Computer Science</span><span class="bibfield volume">4</span><span class="anchors">[<a class="link-to-citation" href="#cite-142">142</a>]</span></div></div><div id="bib-plt-tr1" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-institution has-number no-note no-howpublished no-date no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Flatt, Matthew and PLT</span><span class="bibfield year">2010</span><span class="bibfield title">Reference: Racket</span><span class="bibfield institution dotted">PLT Inc.</span><span class="bibfield number">PLT-TR-2010-1</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-115">115</a>, <a class="link-to-citation" href="#cite-175">175</a>, <a class="link-to-citation" href="#cite-268">268</a>]</span><a class="bibfield url" href="http://racket-lang.org/tr1/">link</a></div></div><div id="bib-Flatt2007" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Flatt, Matthew, Gang Yu, Robert Bruce Findler and Matthias Felleisen</span><span class="bibfield year">2007</span><span class="bibfield title">Adding delimited and composable control to a production programming environment</span><span class="bibfield booktitle">Proc. Int. Conf. on Functional Programming</span><span class="bibfield location">Freiburg, Germany</span><span class="bibfield date">October</span><span class="anchors">[<a class="link-to-citation" href="#cite-121">121</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1291220.1291178">doi</a></div></div><div id="bib-Flatt2006" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Flatt, Matthew, Robert Bruce Findler and Matthias Felleisen</span><span class="bibfield year">2006</span><span class="bibfield title">Scheme with Classes, Mixins, and Traits</span><span class="bibfield booktitle">Programming Languages and Systems</span><span class="bibfield location">Sydney, Australia</span><span class="bibfield pages">270289</span><span class="bibfield date">November</span><span class="anchors">[<a class="link-to-citation" href="#cite-161">161</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/11924661_17">doi</a></div></div><div id="bib-Forgy1982" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Forgy, Charles L.</span><span class="bibfield year">1982</span><span class="bibfield title">Rete: A Fast Algorithm for the Many Patterns/Many Objects Match Problem</span><span class="bibfield journaltitle">Artificial Intelligence</span><span class="bibfield volume">19</span><span class="bibfield pages">1737</span><span class="anchors">[<a class="link-to-citation" href="#cite-84">84</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/0004-3702(82)90020-0">doi</a></div></div><div id="bib-Gonthier" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-number has-pages no-note no-howpublished no-date no-issue no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Fournet, Cédric and Georges Gonthier</span><span class="bibfield year">2000</span><span class="bibfield title">The Join Calculus: a Language for Distributed Mobile Programming</span><span class="bibfield booktitle">Applied Semantics Summer School</span><span class="bibfield location">Caminha, Portugal</span><span class="bibfield number">September 2000</span><span class="bibfield pages">166</span><span class="anchors">[<a class="link-to-citation" href="#cite-55">55</a>]</span></div></div><div id="bib-Fowler2016" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Fowler, Simon, Sam Lindley and Philip Wadler</span><span class="bibfield year">2016</span><span class="bibfield title">Mixing Metaphors Actors as Channels and Channels as Actors</span><span class="anchors">[<a class="link-to-citation" href="#cite-60">60</a>]</span></div></div><div id="bib-Fredkin1960" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Fredkin, Edward</span><span class="bibfield year">1960</span><span class="bibfield title">Trie Memory</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield volume">3</span><span class="bibfield number">9</span><span class="bibfield pages">490499</span><span class="anchors">[<a class="link-to-citation" href="#cite-129">129</a>]</span></div></div><div id="bib-Frolund1994" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Frølund, Svend and Gul Agha</span><span class="bibfield year">1994</span><span class="bibfield title">Abstracting interactions based on message sets</span><span class="bibfield booktitle">ECOOP</span><span class="anchors">[<a class="link-to-citation" href="#cite-249">249</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/3-540-59450-7_7">doi</a></div></div><div id="bib-Gamma1994" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Gamma, Erich, Richard Helm, Ralph Johnson and John Vlissides</span><span class="bibfield year">1994</span><span class="bibfield title">Design Patterns: Elements of Reusable Object-Oriented Software</span><span class="bibfield publisher">Addison-Wesley</span><span class="anchors">[<a class="link-to-citation" href="#cite-31">31</a>, <a class="link-to-citation" href="#cite-210">210</a>, <a class="link-to-citation" href="#cite-215">215</a>, <a class="link-to-citation" href="#cite-216">216</a>, <a class="link-to-citation" href="#cite-228">228</a>, <a class="link-to-citation" href="#cite-232">232</a>, <a class="link-to-citation" href="#cite-234">234</a>, <a class="link-to-citation" href="#cite-242">242</a>, <a class="link-to-citation" href="#cite-246">246</a>, <a class="link-to-citation" href="#cite-247">247</a>]</span></div></div><div id="bib-Garnock-Jones2016a" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Garnock-Jones, Tony and Matthias Felleisen</span><span class="bibfield year">2016</span><span class="bibfield title">Coordinated Concurrent Programming in Syndicate</span><span class="bibfield booktitle">Proc. ESOP</span><span class="bibfield location">Eindhoven, The Netherlands</span><span class="bibfield pages">310336</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-93">93</a>, <a class="link-to-citation" href="#cite-160">160</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-662-49498-1_13">doi</a><a class="bibfield url" href="http://www.ccs.neu.edu/racket/pubs/esop16-gjf.pdf">link</a></div></div><div id="bib-Garnock-Jones2014" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Garnock-Jones, Tony, Sam Tobin-Hochstadt and Matthias Felleisen</span><span class="bibfield year">2014</span><span class="bibfield title">The Network as a Language Construct</span><span class="bibfield booktitle">European Symposium on Programming</span><span class="bibfield location">Grenoble, France</span><span class="bibfield pages">473492</span><span class="anchors">[<a class="link-to-citation" href="#cite-92">92</a>, <a class="link-to-citation" href="#cite-185">185</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-642-54833-8_25">doi</a><a class="bibfield url" href="http://www.ccs.neu.edu/racket/pubs/esop14-gjthf.pdf">link</a></div></div><div id="bib-Gelernter1985" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Gelernter, David</span><span class="bibfield year">1985</span><span class="bibfield title">Generative communication in Linda</span><span class="bibfield journaltitle">ACM Transactions on Programming Languages and Systems</span><span class="bibfield publisher">ACM</span><span class="bibfield volume">7</span><span class="bibfield number">1</span><span class="bibfield pages">80112</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-15">15</a>, <a class="link-to-citation" href="#cite-65">65</a>, <a class="link-to-citation" href="#cite-294">294</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2363.2433">doi</a></div></div><div id="bib-Gelernter1992" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Gelernter, David and Nicholas Carriero</span><span class="bibfield year">1992</span><span class="bibfield title">Coordination languages and their significance</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield publisher">ACM</span><span class="bibfield volume">35</span><span class="bibfield number">2</span><span class="bibfield pages">97107</span><span class="bibfield date">February</span><span class="anchors">[<a class="link-to-citation" href="#cite-16">16</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/129630.129635">doi</a></div></div><div id="bib-Golovin2010" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Golovin, Daniel</span><span class="bibfield year">2010</span><span class="bibfield title">The B-Skip-List: A Simpler Uniquely Represented Alternative to B-Trees</span><span class="bibfield journaltitle">arXiv preprint arXiv:1005.0662</span><span class="bibfield date">May</span><span class="anchors">[<a class="link-to-citation" href="#cite-148">148</a>]</span><a class="bibfield url" href="http://arxiv.org/abs/1005.0662">link</a></div></div><div id="bib-GonzalezBoix2012" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-number has-date no-note no-howpublished no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">González Boix, Elisa</span><span class="bibfield year">2012</span><span class="bibfield title">Handling Partial Failures in Mobile Ad hoc Network Applications: From Programming Language Design to Tool Support</span><span class="bibfield institution">Vrije Universiteit Brussel</span><span class="bibfield number">October</span><span class="bibfield date">October</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-70">70</a>]</span><a class="bibfield url" href="http://soft.vub.ac.be/Publications/2012/vub-soft-phd-12-03.pdf">link</a></div></div><div id="bib-GonzalezBoix2014" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">González Boix, Elisa, Christophe Scholliers, Wolfgang De Meuter and Theo D'Hondt</span><span class="bibfield year">2014</span><span class="bibfield title">Programming mobile context-aware applications with TOTAM</span><span class="bibfield journaltitle">Journal of Systems and Software</span><span class="bibfield volume">92</span><span class="bibfield number">1</span><span class="bibfield pages">319</span><span class="anchors">[<a class="link-to-citation" href="#cite-71">71</a>, <a class="link-to-citation" href="#cite-81">81</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/j.jss.2013.07.031">doi</a></div></div><div id="bib-Gosling2014" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Gosling, James, Bill Joy, Guy L. Steele, Gilad Bracha and Alex Buckley</span><span class="bibfield year">2014</span><span class="bibfield title">The Java Language Specification, Java SE 8 Edition</span><span class="bibfield publisher">Addison-Wesley Professional</span><span class="bibfield pages">792</span><span class="anchors">[<a class="link-to-citation" href="#cite-41">41</a>]</span></div></div><div id="bib-Goto1976" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Goto, Eiichi and Yasumasa Kanada</span><span class="bibfield year">1976</span><span class="bibfield title">Hashing Lemmas on Time Complexities with Applications to Formula Manipulation</span><span class="bibfield booktitle">Proc. ACM Symp. on Symbolic and Algebraic Computation</span><span class="bibfield location">Yorktown Heights, New York</span><span class="bibfield pages">154158</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-140">140</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/800205.806334">doi</a></div></div><div id="bib-Goubault1994" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-institution no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Goubault, Jean</span><span class="bibfield year">1994</span><span class="bibfield title">Implementing Functional Languages with Fast Equality, Sets and Maps: an Exercise in Hash Consing</span><span class="bibfield institution">Bull S.A. Research Center, rue Jean-Jaurès, 78340 Les Clayes sous Boise</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-136">136</a>]</span></div></div><div id="bib-Graunke2001" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Graunke, Paul, Shriram Krishnamurthi, Steve Van Der Hoeven and Matthias Felleisen</span><span class="bibfield year">2001</span><span class="bibfield title">Programming the Web with High-Level Programming Languages</span><span class="bibfield booktitle">European Symposium on Programming</span><span class="anchors">[<a class="link-to-citation" href="#cite-123">123</a>]</span></div></div><div id="bib-Grice1975" class="bibliography-entry"><div class="entrytype-incollection editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Grice, H. Paul</span><span class="bibfield year">1975</span><span class="bibfield title">Logic and Conversation</span><span class="bibfield booktitle">Syntax and Semantics 3: Speech Acts</span><span class="bibfield location">New York</span><span class="bibfield publisher">Academic Press</span><span class="bibfield pages">4158</span><span class="anchors">[<a class="link-to-citation" href="#cite-3">3</a>, <a class="link-to-citation" href="#cite-4">4</a>, <a class="link-to-citation" href="#cite-5">5</a>, <a class="link-to-citation" href="#cite-7">7</a>, <a class="link-to-citation" href="#cite-8">8</a>, <a class="link-to-citation" href="#cite-27">27</a>]</span></div></div><div id="bib-Haller2009" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Haller, Philipp and Martin Odersky</span><span class="bibfield year">2009</span><span class="bibfield title">Scala Actors: Unifying thread-based and event-based programming</span><span class="bibfield journaltitle">Theoretical Computer Science</span><span class="bibfield publisher dotted">Elsevier B.V.</span><span class="bibfield volume">410</span><span class="bibfield number">2-3</span><span class="bibfield pages">202220</span><span class="bibfield date">February</span><span class="anchors">[<a class="link-to-citation" href="#cite-57">57</a>, <a class="link-to-citation" href="#cite-173">173</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/j.tcs.2008.09.019">doi</a></div></div><div id="bib-Hancock2003" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Hancock, Christopher Michael</span><span class="bibfield year">2003</span><span class="bibfield title">Real-time programming and the big ideas of computational literacy</span><span class="bibfield institution">Massachusetts Institute of Technology</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-118">118</a>]</span><a class="bibfield doi" href="https://dx.doi.org/1721.1/61549">doi</a></div></div><div id="bib-Harris2005" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Harris, Tim, Simon Marlow, Simon Peyton Jones and Maurice Herlihy</span><span class="bibfield year">2005</span><span class="bibfield title">Composable memory transactions</span><span class="bibfield booktitle">Proc. Principles and Practice of Parallel Programming (PPOPP)</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-45">45</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1065944.1065952">doi</a></div></div><div id="bib-Henderson1982" class="bibliography-entry"><div class="entrytype-incollection editor-count-3 no-dayofmonth has-author has-title has-booktitle has-editor has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle"><span class="bibfield author">Henderson, Peter</span><span class="bibfield year">1982</span><span class="bibfield title">Purely Functional Operating Systems</span><span class="bibfield booktitle">Functional Programming and its Applications</span><span class="bibfield editor">J. Darlington, P. Henderson and D. Turner</span><span class="bibfield publisher">Cambridge University Press</span><span class="bibfield pages">177192</span><span class="anchors">[<a class="link-to-citation" href="#cite-269">269</a>]</span></div></div><div id="bib-sep-logic-epistemic" class="bibliography-entry"><div class="entrytype-incollection editor-count-1 no-dayofmonth has-author has-title has-booktitle has-editor has-edition has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-journaltitle"><span class="bibfield author">Hendricks, Vincent and John Symons</span><span class="bibfield year">2015</span><span class="bibfield title">Epistemic Logic</span><span class="bibfield booktitle">The Stanford Encyclopedia of Philosophy</span><span class="bibfield editor">Edward N. Zalta</span><span class="bibfield edition">Fall 2015</span><span class="bibfield publisher">Metaphysics Research Lab, Stanford University</span><span class="anchors">[<a class="link-to-citation" href="#cite-12">12</a>]</span><a class="bibfield url" href="https://plato.stanford.edu/archives/fall2015/entries/logic-epistemic/">link</a></div></div><div id="bib-Hewitt1971" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Hewitt, Carl</span><span class="bibfield year">1971</span><span class="bibfield title">Procedural Embedding of Knowledge in Planner</span><span class="bibfield booktitle">Proc. IJCAI</span><span class="bibfield pages">167182</span><span class="anchors">[<a class="link-to-citation" href="#cite-176">176</a>]</span></div></div><div id="bib-Hewitt1973" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Hewitt, Carl, Peter Bishop and Richard Steiger</span><span class="bibfield year">1973</span><span class="bibfield title">A universal modular ACTOR formalism for artificial intelligence</span><span class="bibfield booktitle">Proc. International Joint Conference on Artificial Intelligence</span><span class="bibfield publisher dotted">Morgan Kaufmann Publishers Inc.</span><span class="bibfield pages">235245</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-20">20</a>, <a class="link-to-citation" href="#cite-49">49</a>, <a class="link-to-citation" href="#cite-64">64</a>, <a class="link-to-citation" href="#cite-233">233</a>, <a class="link-to-citation" href="#cite-281">281</a>]</span></div></div><div id="bib-Hinze2000" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Hinze, Ralf</span><span class="bibfield year">2000</span><span class="bibfield title">Generalizing generalized tries</span><span class="bibfield journaltitle">Journal of Functional Programming</span><span class="bibfield volume">10</span><span class="bibfield number">4</span><span class="bibfield pages">327351</span><span class="anchors">[<a class="link-to-citation" href="#cite-158">158</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1017/S0956796800003713">doi</a></div></div><div id="bib-Hoare1974" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-1 no-dayofmonth has-author has-title has-booktitle has-editor has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-journaltitle"><span class="bibfield author dotted">Hoare, C. A. R.</span><span class="bibfield year">1974</span><span class="bibfield title">Hints on Programming Language Design</span><span class="bibfield booktitle">Computer Systems Reliability</span><span class="bibfield editor">C. Bunyan</span><span class="bibfield volume">20</span><span class="bibfield pages">505534</span><span class="anchors">[<a class="link-to-citation" href="#cite-220">220</a>, <a class="link-to-citation" href="#cite-221">221</a>, <a class="link-to-citation" href="#cite-222">222</a>]</span></div></div><div id="bib-Hoare1983" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Hoare, C. A. R.</span><span class="bibfield year">1985</span><span class="bibfield title">Communicating sequential processes</span><span class="bibfield publisher">Prentice Hall</span><span class="anchors">[<a class="link-to-citation" href="#cite-47">47</a>]</span></div></div><div id="bib-Hohpe2017" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Hohpe, Gregor</span><span class="bibfield year">2017</span><span class="bibfield title">Conversation Patterns</span><span class="anchors">[<a class="link-to-citation" href="#cite-214">214</a>, <a class="link-to-citation" href="#cite-229">229</a>, <a class="link-to-citation" href="#cite-243">243</a>]</span><a class="bibfield url" title="Accessed: 26 July 2017" href="http://www.enterpriseintegrationpatterns.com/patterns/conversation/">link</a></div></div><div id="bib-Hohpe2004" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-edition has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-journaltitle no-booktitle no-editor"><span class="bibfield author">Hohpe, Gregor and Bobby Woolf</span><span class="bibfield year">2004</span><span class="bibfield title">Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions</span><span class="bibfield edition">1</span><span class="bibfield publisher">Addison-Wesley Professional</span><span class="anchors">[<a class="link-to-citation" href="#cite-179">179</a>, <a class="link-to-citation" href="#cite-213">213</a>, <a class="link-to-citation" href="#cite-230">230</a>]</span></div></div><div id="bib-Hudak1988" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-booktitle has-publisher has-date no-note no-howpublished no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Hudak, Paul and Raman S. Sundaresh</span><span class="bibfield year">1988</span><span class="bibfield title">On the Expressiveness of Purely Functional I/O Systems</span><span class="bibfield booktitle">YALE/DCS/TR665</span><span class="bibfield publisher">Department of Computer Science, Yale University</span><span class="bibfield date">December</span><span class="anchors">[<a class="link-to-citation" href="#cite-263">263</a>, <a class="link-to-citation" href="#cite-271">271</a>, <a class="link-to-citation" href="#cite-276">276</a>]</span></div></div><div id="bib-Holzle1994" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-publisher has-number no-note no-howpublished no-date no-pages no-issue no-volume no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Hölzle, Urs</span><span class="bibfield year">1994</span><span class="bibfield title">Adaptive optimization for Self: Reconciling high performance with exploratory programming</span><span class="bibfield institution">Stanford University</span><span class="bibfield publisher">Stanford University</span><span class="bibfield number">August</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-253">253</a>]</span><a class="bibfield url" href="http://i.stanford.edu/TR/CS-TR-94-1520.html">link</a></div></div><div id="bib-Holzle1995" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Hölzle, Urs and David Ungar</span><span class="bibfield year">1995</span><span class="bibfield title dotted">Do Object-Oriented Languages Need Special Hardware Support?</span><span class="bibfield booktitle">Proceedings of the 9th European Conference on Object-Oriented Programming (ECOOP '95)</span><span class="bibfield pages">253282</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-254">254</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/3-540-49538-X_14">doi</a></div></div><div id="bib-IEEE-9945-2009" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">IEEE</span><span class="bibfield year">2009</span><span class="bibfield title">International Standard - Information technology Portable Operating System Interface (POSIX) Base Specifications, Issue 7</span><span class="bibfield journaltitle">ISO/IEC/IEEE 9945:2009(E)</span><span class="bibfield pages">13880</span><span class="anchors">[<a class="link-to-citation" href="#cite-42">42</a>, <a class="link-to-citation" href="#cite-124">124</a>, <a class="link-to-citation" href="#cite-177">177</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/IEEESTD.2009.5393893">doi</a></div></div><div id="bib-T13:1699D" class="bibliography-entry"><div class="entrytype-misc editor-count-1 no-dayofmonth has-author has-title has-editor has-edition has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-journaltitle no-booktitle"><span class="bibfield author">INCITS T13 Committee</span><span class="bibfield year">2006</span><span class="bibfield title">ANS T13/1699-D: AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)</span><span class="bibfield editor">Curtis Stevens</span><span class="bibfield edition">3f</span><span class="bibfield date">December</span><span class="anchors">[<a class="link-to-citation" href="#cite-125">125</a>]</span></div></div><div id="bib-Ingalls1988" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Ingalls, Dan, Scott Wallace, Yu-ying Chow, Frank Ludolph and Ken Doyle</span><span class="bibfield year">1988</span><span class="bibfield title">Fabrik - A Visual Programming Environment</span><span class="bibfield booktitle">Proc. OOPSLA</span><span class="bibfield date">November</span><span class="anchors">[<a class="link-to-citation" href="#cite-199">199</a>, <a class="link-to-citation" href="#cite-201">201</a>]</span></div></div><div id="bib-Ionescu2010" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Ionescu, Vlad Alexandru</span><span class="bibfield year">2010</span><span class="bibfield title">Very fast and scalable topic routing part 1</span><span class="bibfield booktitle">RabbitMQ Blog</span><span class="anchors">[<a class="link-to-citation" href="#cite-130">130</a>, <a class="link-to-citation" href="#cite-159">159</a>]</span><a class="bibfield url" title="Accessed: 16 January 2017" href="http://www.rabbitmq.com/blog/2010/09/14/very-fast-and-scalable-topic-routing-part-1/">link</a></div></div><div id="bib-Ionescu2011" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Ionescu, Vlad Alexandru</span><span class="bibfield year">2011</span><span class="bibfield title">Very fast and scalable topic routing part 2</span><span class="bibfield booktitle">RabbitMQ Blog</span><span class="anchors">[<a class="link-to-citation" href="#cite-131">131</a>]</span><a class="bibfield url" title="Accessed: 16 January 2017" href="https://www.rabbitmq.com/blog/2011/03/28/very-fast-and-scalable-topic-routing-part-2/">link</a></div></div><div id="bib-ISO-14882-2014" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">ISO</span><span class="bibfield year">2014</span><span class="bibfield title">International Standard - Information technology - Programming Languages - C++</span><span class="bibfield journaltitle">ISO/IEC 14882:2014</span><span class="bibfield pages">11358</span><span class="anchors">[<a class="link-to-citation" href="#cite-43">43</a>]</span></div></div><div id="bib-Jayaram2011" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Jayaram, K. R. and Patrick Eugster</span><span class="bibfield year">2011</span><span class="bibfield title">Split and Subsume: Subscription Normalization for Effective Content-Based Messaging</span><span class="bibfield booktitle">International Conference on Distributed Computing Systems</span><span class="bibfield pages">824835</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-190">190</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/ICDCS.2011.85">doi</a></div></div><div id="bib-rfc2812" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-organization has-publisher has-number has-date has-howpublished no-note no-pages no-issue no-volume no-location no-institution no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Kalt, C.</span><span class="bibfield year">2000</span><span class="bibfield title">Internet Relay Chat: Client Protocol</span><span class="bibfield organization">Internet Engineering Task Force</span><span class="bibfield publisher">IETF</span><span class="bibfield number">2812</span><span class="bibfield date">April</span><span class="bibfield howpublished">RFC 2812 (Informational)</span><span class="anchors">[<a class="link-to-citation" href="#cite-195">195</a>, <a class="link-to-citation" href="#cite-301">301</a>]</span><a class="bibfield url" href="http://www.ietf.org/rfc/rfc2812.txt">link</a></div></div><div id="bib-Kay1993" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number no-note no-howpublished no-date no-pages no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Kay, Alan C.</span><span class="bibfield year">1993</span><span class="bibfield title">The Early History of Smalltalk</span><span class="bibfield journaltitle">ACM SIGPLAN Notices</span><span class="bibfield publisher">ACM</span><span class="bibfield volume">28</span><span class="bibfield number">3</span><span class="anchors">[<a class="link-to-citation" href="#cite-251">251</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/155360.155364">doi</a></div></div><div id="bib-Kitcher1990" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Kitcher, Philip</span><span class="bibfield year">1990</span><span class="bibfield title">The Division of Cognitive Labor</span><span class="bibfield journaltitle">The Journal of Philosophy</span><span class="bibfield volume">87</span><span class="bibfield number">1</span><span class="bibfield pages">522</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-9">9</a>]</span></div></div><div id="bib-Konieczny2009" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Konieczny, Eric, Ryan Ashcraft, David Cunningham and Sandeep Maripuri</span><span class="bibfield year">2009</span><span class="bibfield title">Establishing Presence within the Service-Oriented Environment</span><span class="bibfield booktitle">IEEE Aerospace Conference</span><span class="bibfield location">Big Sky, Montana</span><span class="bibfield date">March</span><span class="anchors">[<a class="link-to-citation" href="#cite-34">34</a>, <a class="link-to-citation" href="#cite-193">193</a>, <a class="link-to-citation" href="#cite-258">258</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/AERO.2009.4839647">doi</a></div></div><div id="bib-sep-pragmatics" class="bibliography-entry"><div class="entrytype-incollection editor-count-1 no-dayofmonth has-author has-title has-booktitle has-editor has-edition has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-journaltitle"><span class="bibfield author">Korta, Kepa and John Perry</span><span class="bibfield year">2015</span><span class="bibfield title">Pragmatics</span><span class="bibfield booktitle">The Stanford Encyclopedia of Philosophy</span><span class="bibfield editor">Edward N. Zalta</span><span class="bibfield edition">Winter 2015</span><span class="bibfield publisher">Metaphysics Research Lab, Stanford University</span><span class="anchors">[<a class="link-to-citation" href="#cite-24">24</a>]</span><a class="bibfield url" href="https://plato.stanford.edu/archives/win2015/entries/pragmatics/">link</a></div></div><div id="bib-Lamport1984" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Lamport, Leslie</span><span class="bibfield year">1984</span><span class="bibfield title dotted">Using Time Instead of Timeout for Fault-Tolerant Distributed Systems.</span><span class="bibfield journaltitle">ACM Transactions on Programming Languages and Systems</span><span class="bibfield volume">6</span><span class="bibfield number">2</span><span class="bibfield pages">254280</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-298">298</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2993.2994">doi</a></div></div><div id="bib-Landin1966" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Landin, P. J.</span><span class="bibfield year">1966</span><span class="bibfield title">The Next 700 Programming Languages</span><span class="bibfield journaltitle">Commun. ACM</span><span class="bibfield volume">9</span><span class="bibfield number">3</span><span class="bibfield pages">157166</span><span class="anchors">[<a class="link-to-citation" href="#cite-95">95</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/365230.365257">doi</a></div></div><div id="bib-Lee1987" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Lee, Edward A. and David G. Messerschmitt</span><span class="bibfield year">1987</span><span class="bibfield title">Synchronous data flow</span><span class="bibfield journaltitle">Proceedings of the IEEE</span><span class="bibfield volume">75</span><span class="bibfield number">9</span><span class="bibfield pages">12351245</span><span class="anchors">[<a class="link-to-citation" href="#cite-198">198</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/PROC.1987.13876">doi</a></div></div><div id="bib-Leroy2009" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Leroy, Xavier</span><span class="bibfield year">2009</span><span class="bibfield title">Formal verification of a realistic compiler</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield volume">52</span><span class="bibfield number">7</span><span class="bibfield pages">107115</span><span class="anchors">[<a class="link-to-citation" href="#cite-127">127</a>]</span></div></div><div id="bib-Li2007" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Li, Peng and Steve Zdancewic</span><span class="bibfield year">2007</span><span class="bibfield title">Combining Events and Threads for Scalable Network Services</span><span class="bibfield booktitle">Proceedings of the 2007 ACM SIGPLAN conference on Programming language design and implementation</span><span class="bibfield pages">189199</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-172">172</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1250734.1250756">doi</a></div></div><div id="bib-Love2005" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-issue has-date no-note no-howpublished no-pages no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Love, Robert</span><span class="bibfield year">2005</span><span class="bibfield title">Kernel Korner: Intro to Inotify</span><span class="bibfield journaltitle">Linux Journal</span><span class="bibfield issue">139</span><span class="bibfield date">November</span><span class="anchors">[<a class="link-to-citation" href="#cite-96">96</a>]</span><a class="bibfield url" href="http://www.linuxjournal.com/article/8478">link</a></div></div><div id="bib-Manna1991" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Manna, Zohar and Amir Pnueli</span><span class="bibfield year">1991</span><span class="bibfield title">The Temporal Logic of Reactive and Concurrent Systems: Specification</span><span class="bibfield publisher">Springer Verlag</span><span class="anchors">[<a class="link-to-citation" href="#cite-186">186</a>, <a class="link-to-citation" href="#cite-196">196</a>]</span></div></div><div id="bib-Martins2010" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Martins, J. Legatheaux and Sérgio Duarte</span><span class="bibfield year">2010</span><span class="bibfield title">Routing Algorithms for Content-Based Publish/Subscribe Systems</span><span class="bibfield journaltitle">IEEE Communications Surveys and Tutorials</span><span class="bibfield volume">12</span><span class="bibfield number">1</span><span class="bibfield pages">3958</span><span class="anchors">[<a class="link-to-citation" href="#cite-191">191</a>]</span></div></div><div id="bib-McCarthy1998" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">McCarthy, John</span><span class="bibfield year">1998</span><span class="bibfield title">Elaboration Tolerance</span><span class="bibfield booktitle">Proc. Fourth Symp. on Logical Formalizations of Commonsense Reasoning</span><span class="bibfield location">London, England</span><span class="anchors">[<a class="link-to-citation" href="#cite-178">178</a>]</span><a class="bibfield url" href="http://jmc.stanford.edu/articles/elaboration.html">link</a></div></div><div id="bib-Mey2001" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-edition has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Mey, Jacob L.</span><span class="bibfield year">2001</span><span class="bibfield title">Pragmatics: An Introduction</span><span class="bibfield edition">2</span><span class="bibfield publisher">Wiley-Blackwell</span><span class="anchors">[<a class="link-to-citation" href="#cite-25">25</a>, <a class="link-to-citation" href="#cite-26">26</a>]</span></div></div><div id="bib-Miller2014" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Miller, Heather, Philipp Haller and Martin Odersky</span><span class="bibfield year">2014</span><span class="bibfield title">Spores: A type-based foundation for closures in the age of concurrency and distribution</span><span class="bibfield booktitle">ECOOP</span><span class="bibfield location">Uppsala, Sweden</span><span class="bibfield date">July</span><span class="anchors">[<a class="link-to-citation" href="#cite-37">37</a>]</span></div></div><div id="bib-Miller2016" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Miller, Heather, Philipp Haller, Normen Müller and Jocelyn Boullier</span><span class="bibfield year">2016</span><span class="bibfield title">Function passing: a model for typed, distributed functional programming</span><span class="bibfield booktitle">Proceedings of the 2016 ACM International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software - Onward! 2016</span><span class="bibfield location">Amsterdam, The Netherlands</span><span class="bibfield date">November</span><span class="anchors">[<a class="link-to-citation" href="#cite-38">38</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2986012.2986014">doi</a></div></div><div id="bib-Miller2006" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-volume has-number no-note no-howpublished no-date no-pages no-issue no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Miller, Mark S.</span><span class="bibfield year">2006</span><span class="bibfield title">Robust composition: Towards a unified approach to access control and concurrency control</span><span class="bibfield institution">Johns Hopkins University</span><span class="bibfield volume">67</span><span class="bibfield number">12</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-29">29</a>, <a class="link-to-citation" href="#cite-62">62</a>]</span></div></div><div id="bib-Miller2005" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Miller, Mark S., E. Dean Tribble and Jonathan Shapiro</span><span class="bibfield year">2005</span><span class="bibfield title">Concurrency Among Strangers</span><span class="bibfield booktitle">Proc. Int. Symp. on Trustworthy Global Computing</span><span class="bibfield location">Edinburgh, Scotland</span><span class="bibfield pages">195229</span><span class="anchors">[<a class="link-to-citation" href="#cite-59">59</a>]</span></div></div><div id="bib-Miller2013" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Miller, Mark S., Tom Van Cutsem and Bill Tulloh</span><span class="bibfield year">2013</span><span class="bibfield title">Distributed electronic rights in JavaScript</span><span class="bibfield booktitle">Proc. ESOP</span><span class="anchors">[<a class="link-to-citation" href="#cite-91">91</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-642-37036-6_1">doi</a></div></div><div id="bib-Milner1999" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Milner, Robin</span><span class="bibfield year">1999</span><span class="bibfield title">Communicating and Mobile Systems: The Pi Calculus</span><span class="bibfield publisher">Cambridge University Press</span><span class="bibfield pages">161</span><span class="anchors">[<a class="link-to-citation" href="#cite-48">48</a>]</span></div></div><div id="bib-Milner1992" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Milner, Robin, Joachim Parrow and David Walker</span><span class="bibfield year">1992</span><span class="bibfield title">A calculus of mobile processes, I</span><span class="bibfield journaltitle">Information and Computation</span><span class="bibfield volume">100</span><span class="bibfield number">1</span><span class="bibfield pages">140</span><span class="bibfield date">September</span><span class="anchors">[<a class="link-to-citation" href="#cite-277">277</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/0890-5401(92)90008-4">doi</a></div></div><div id="bib-Mostinckx2008a" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Mostinckx, Stijn, Andoni Lombide Carreton and Wolfgang De Meuter</span><span class="bibfield year">2008</span><span class="bibfield title">Reactive Context-Aware Programming</span><span class="bibfield booktitle">Proc. 1st Int. DisCoTec Workshop on Context-aware Adaptation Mechanisms for Pervasive and Ubiquitous Services (CAMPUS)</span><span class="bibfield location">Oslo, Norway</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-19">19</a>, <a class="link-to-citation" href="#cite-88">88</a>, <a class="link-to-citation" href="#cite-89">89</a>, <a class="link-to-citation" href="#cite-114">114</a>]</span></div></div><div id="bib-Mostinckx2007" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-2 no-dayofmonth has-author has-title has-booktitle has-editor has-location has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle"><span class="bibfield author">Mostinckx, Stijn, Christophe Scholliers, Eline Philips, Charlotte Herzeel and Wolfgang De Meuter</span><span class="bibfield year">2007</span><span class="bibfield title">Fact spaces: Coordination in the face of disconnection</span><span class="bibfield booktitle">Proc. Int. Conf. on Coordination Models and Languages</span><span class="bibfield editor">Amy L. Murphy and Jan Vitek</span><span class="bibfield location">Paphos, Cyprus</span><span class="bibfield pages">268285</span><span class="anchors">[<a class="link-to-citation" href="#cite-18">18</a>, <a class="link-to-citation" href="#cite-83">83</a>, <a class="link-to-citation" href="#cite-113">113</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-540-72794-1_15">doi</a></div></div><div id="bib-Mozafari2012" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Mozafari, Barzan, Kai Zeng and Carlo Zaniolo</span><span class="bibfield year">2012</span><span class="bibfield title">High-performance complex event processing over XML streams</span><span class="bibfield booktitle">Proceedings of the 2012 international conference on Management of Data - SIGMOD '12</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield pages">253264</span><span class="anchors">[<a class="link-to-citation" href="#cite-156">156</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2213836.2213866">doi</a></div></div><div id="bib-Murphy2006" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Murphy, Amy L., Gian Pietro Picco and Gruia-Catalin Roman</span><span class="bibfield year">2006</span><span class="bibfield title">LIME: A Coordination Model and Middleware Supporting Mobility of Hosts and Agents</span><span class="bibfield journaltitle">ACM Transactions on Software Engineering and Methodology</span><span class="bibfield volume">15</span><span class="bibfield number">3</span><span class="bibfield pages">279328</span><span class="anchors">[<a class="link-to-citation" href="#cite-67">67</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1151695.1151698">doi</a></div></div><div id="bib-Norvig1996" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Norvig, Peter</span><span class="bibfield year">1996</span><span class="bibfield title">Design patterns in dynamic programming</span><span class="bibfield booktitle">Object World</span><span class="bibfield date">May</span><span class="anchors">[<a class="link-to-citation" href="#cite-217">217</a>, <a class="link-to-citation" href="#cite-226">226</a>]</span><a class="bibfield url" href="http://www.norvig.com/design-patterns/design-patterns.pdf">link</a></div></div><div id="bib-Nystrom2014" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Nystrom, Robert</span><span class="bibfield year">2014</span><span class="bibfield title">Game Programming Patterns</span><span class="bibfield publisher">Genever Benning</span><span class="anchors">[<a class="link-to-citation" href="#cite-236">236</a>]</span></div></div><div id="bib-rfc1459" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-organization has-publisher has-number has-date has-howpublished has-note no-pages no-issue no-volume no-location no-institution no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Oikarinen, J. and D. Reed</span><span class="bibfield year">1993</span><span class="bibfield title">Internet Relay Chat Protocol</span><span class="bibfield organization">Internet Engineering Task Force</span><span class="bibfield publisher">IETF</span><span class="bibfield number">1459</span><span class="bibfield date">May</span><span class="bibfield howpublished">RFC 1459 (Experimental)</span><span class="bibfield note">Updated by RFCs 2810, 2811, 2812, 2813</span><span class="anchors">[<a class="link-to-citation" href="#cite-194">194</a>, <a class="link-to-citation" href="#cite-300">300</a>]</span><a class="bibfield url" href="http://www.ietf.org/rfc/rfc1459.txt">link</a></div></div><div id="bib-Oliva1995" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Oliva, Dino P., John D. Ramsdell and Mitchell Wand</span><span class="bibfield year">1995</span><span class="bibfield title">The VLISP Verified PreScheme Compiler</span><span class="bibfield journaltitle">Lisp and Symbolic Computation</span><span class="bibfield volume">8</span><span class="bibfield pages">111182</span><span class="anchors">[<a class="link-to-citation" href="#cite-126">126</a>]</span></div></div><div id="bib-Papadopoulos1998" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Papadopoulos, George A. and Farhad Arbab</span><span class="bibfield year">1998</span><span class="bibfield title">Coordination Models and Languages</span><span class="bibfield journaltitle">Advances in Computers</span><span class="bibfield volume">46</span><span class="bibfield pages">329400</span><span class="anchors">[<a class="link-to-citation" href="#cite-78">78</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/S0065-2458(08)60208-9">doi</a></div></div><div id="bib-Perlis1982" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Perlis, Alan J.</span><span class="bibfield year">1982</span><span class="bibfield title">Special Feature: Epigrams on programming</span><span class="bibfield journaltitle">ACM SIGPLAN Notices</span><span class="bibfield volume">17</span><span class="bibfield number">9</span><span class="bibfield pages">713</span><span class="bibfield date">September</span><span class="anchors">[<a class="link-to-citation" href="#cite-207">207</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/947955.1083808">doi</a></div></div><div id="bib-Peschanski2007" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Peschanski, Frédéric, Alexis Darrasse, Nataliya Guts and Jérémy Bobbio</span><span class="bibfield year">2007</span><span class="bibfield title">Coordinating mobile agents in interaction spaces</span><span class="bibfield journaltitle">Science of Computer Programming</span><span class="bibfield publisher dotted">Elsevier North-Holland, Inc.</span><span class="bibfield volume">66</span><span class="bibfield number">3</span><span class="bibfield pages">246265</span><span class="bibfield date">May</span><span class="anchors">[<a class="link-to-citation" href="#cite-289">289</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/j.scico.2007.01.011">doi</a></div></div><div id="bib-PeytonJones2010" class="bibliography-entry"><div class="entrytype-incollection editor-count-3 no-dayofmonth has-author has-title has-booktitle has-editor has-organization has-publisher has-pages has-date no-note no-howpublished no-issue no-number no-volume no-location no-institution no-edition no-journaltitle"><span class="bibfield author">Peyton Jones, Simon</span><span class="bibfield year">2001</span><span class="bibfield title">Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell</span><span class="bibfield booktitle">Engineering theories of software construction</span><span class="bibfield editor">C.A.R. Hoare, M. Broy and R. Steinbrueggen</span><span class="bibfield organization">Microsoft Research</span><span class="bibfield publisher">IOS Press</span><span class="bibfield pages">4796</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-260">260</a>, <a class="link-to-citation" href="#cite-265">265</a>]</span></div></div><div id="bib-PeytonJones1993" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Peyton Jones, Simon L. and Philip Wadler</span><span class="bibfield year">1993</span><span class="bibfield title">Imperative functional programming</span><span class="bibfield booktitle">ACM Symposium on Principles of Programming Languages (POPL)</span><span class="bibfield location">Charleston, South Carolina</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-264">264</a>]</span></div></div><div id="bib-Pierce2002" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Pierce, Benjamin C.</span><span class="bibfield year">2002</span><span class="bibfield title">Types and Programming Languages</span><span class="bibfield publisher">MIT Press</span><span class="anchors">[<a class="link-to-citation" href="#cite-108">108</a>]</span></div></div><div id="bib-Pietzuch2002" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Pietzuch, Peter Robert and Jean M. Bacon</span><span class="bibfield year">2002</span><span class="bibfield title">Hermes: a distributed event-based middleware architecture</span><span class="bibfield journaltitle">Proceedings 22nd International Conference on Distributed Computing Systems Workshops</span><span class="bibfield publisher">IEEE Comput. Soc</span><span class="bibfield pages">611618</span><span class="anchors">[<a class="link-to-citation" href="#cite-189">189</a>, <a class="link-to-citation" href="#cite-275">275</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/ICDCSW.2002.1030837">doi</a></div></div><div id="bib-Plotkin1977" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author dotted">Plotkin, G. D.</span><span class="bibfield year">1977</span><span class="bibfield title">LCF considered as a programming language</span><span class="bibfield journaltitle">Theoretical Computer Science</span><span class="bibfield volume">5</span><span class="bibfield number">3</span><span class="bibfield pages">223255</span><span class="anchors">[<a class="link-to-citation" href="#cite-164">164</a>, <a class="link-to-citation" href="#cite-238">238</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/0304-3975(77)90044-5">doi</a></div></div><div id="bib-Pugh1990" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Pugh, William</span><span class="bibfield year">1990</span><span class="bibfield title">Skip lists: a probabilistic alternative to balanced trees</span><span class="bibfield journaltitle">Communications of the ACM</span><span class="bibfield volume">33</span><span class="bibfield number">6</span><span class="bibfield pages">668676</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-147">147</a>]</span></div></div><div id="bib-Queinnec2000" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Queinnec, Christian</span><span class="bibfield year">2000</span><span class="bibfield title">The Influence of Browsers on Evaluators or, Continuations to Program Web Servers</span><span class="bibfield booktitle">ICFP</span><span class="anchors">[<a class="link-to-citation" href="#cite-122">122</a>]</span></div></div><div id="bib-Radul2009" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-number has-date no-note no-howpublished no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Radul, Alexey Andreyevich</span><span class="bibfield year">2009</span><span class="bibfield title">Propagation Networks: A Flexible and Expressive Substrate for Computation</span><span class="bibfield institution">Massachusetts Institute of Technology</span><span class="bibfield number">2003</span><span class="bibfield date">September</span><span class="bibfield type-PhD"></span><span class="anchors">[<a class="link-to-citation" href="#cite-202">202</a>, <a class="link-to-citation" href="#cite-205">205</a>]</span><a class="bibfield doi" href="https://dx.doi.org/1721.1/49525">doi</a></div></div><div id="bib-Reppy1991" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author dotted">Reppy, John H.</span><span class="bibfield year">1991</span><span class="bibfield title">CML: A Higher-order Concurrent Language</span><span class="bibfield booktitle">Proc. PLDI</span><span class="bibfield location">Toronto, Canada</span><span class="bibfield pages">293305</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-54">54</a>, <a class="link-to-citation" href="#cite-266">266</a>]</span></div></div><div id="bib-Reppy1999" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author dotted">Reppy, John H.</span><span class="bibfield year">1999</span><span class="bibfield title">Concurrent Programming in ML</span><span class="bibfield publisher">Cambridge University Press</span><span class="anchors">[<a class="link-to-citation" href="#cite-174">174</a>, <a class="link-to-citation" href="#cite-267">267</a>]</span></div></div><div id="bib-Reppy1992" class="bibliography-entry"><div class="entrytype-thesis editor-count-0 no-dayofmonth has-author has-title has-institution has-number no-note no-howpublished no-date no-pages no-issue no-volume no-publisher no-location no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Reppy, John Hamilton</span><span class="bibfield year">1992</span><span class="bibfield title">Higher-order Concurrency</span><span class="bibfield institution">Cornell University</span><span class="bibfield number">June</span><span class="bibfield type-PhD thesis"></span><span class="anchors">[<a class="link-to-citation" href="#cite-36">36</a>]</span></div></div><div id="bib-RotemGalOz2006" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-howpublished no-note no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Rotem-Gal-Oz, Arnon</span><span class="bibfield year">2006</span><span class="bibfield title">Fallacies of Distributed Computing Explained</span><span class="bibfield howpublished">White paper</span><span class="anchors">[<a class="link-to-citation" href="#cite-2">2</a>]</span><a class="bibfield url" href="http://www.rgoarchitects.com/Files/fallacies.pdf">link</a></div></div><div id="bib-Rowstron2000" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Rowstron, Antony</span><span class="bibfield year">2000</span><span class="bibfield title">Using Agent Wills to Provide Fault-tolerance in Distributed Shared Memory Systems</span><span class="bibfield booktitle">Parallel and Distributed Processing</span><span class="bibfield location">Rhodos, Greece</span><span class="bibfield pages">317324</span><span class="bibfield date">January</span><span class="anchors">[<a class="link-to-citation" href="#cite-80">80</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/EMPDP.2000.823426">doi</a></div></div><div id="bib-Rowstron1996a" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Rowstron, Antony and Alan Wood</span><span class="bibfield year">1996</span><span class="bibfield title">Solving the Linda multiple rd problem</span><span class="bibfield booktitle">Proc. 1st International Conference on Coordination Models and Languages (COORDINATION '96)</span><span class="bibfield location">Cesena, Italy</span><span class="bibfield pages">357367</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-73">73</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/3-540-61052-9_56">doi</a></div></div><div id="bib-Russell2016" class="bibliography-entry"><div class="entrytype-incollection editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher no-note no-howpublished no-date no-pages no-issue no-number no-volume no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Russell, Nick, Wil M. P. van der Aalst and Arthur H. M. ter Hofstede</span><span class="bibfield year">2016</span><span class="bibfield title">Control-flow Patterns</span><span class="bibfield booktitle">Workflow Patterns: The Definitive Guide</span><span class="bibfield location">Cambridge, Massachusetts</span><span class="bibfield publisher">MIT Press</span><span class="anchors">[<a class="link-to-citation" href="#cite-237">237</a>]</span></div></div><div id="bib-Salvaneschi2014" class="bibliography-entry"><div class="entrytype-incollection editor-count-5 no-dayofmonth has-author has-title has-booktitle has-editor has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle"><span class="bibfield author">Salvaneschi, Guido and Mira Mezini</span><span class="bibfield year">2014</span><span class="bibfield title">Towards Reactive Programming for Object-Oriented Applications</span><span class="bibfield booktitle">Transactions on Aspect-Oriented Software Development XI</span><span class="bibfield editor">Shigeru Chiba, Éric Tanter, Eric Bodden, Shahar Maoz and Jörg Kienzle</span><span class="bibfield publisher">Springer-Verlag Berlin Heidelberg</span><span class="bibfield pages">227261</span><span class="anchors">[<a class="link-to-citation" href="#cite-170">170</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-642-55099-7_7">doi</a></div></div><div id="bib-Sanderson2010" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Sanderson, Steven</span><span class="bibfield year">2010</span><span class="bibfield title">Introducing Knockout, a UI library for JavaScript</span><span class="anchors">[<a class="link-to-citation" href="#cite-171">171</a>]</span><a class="bibfield url" title="Accessed: 27 July 2017" href="http://blog.stevensanderson.com/2010/07/05/introducing-knockout-a-ui-library-for-javascript/">link</a></div></div><div id="bib-SantAnna2015" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Sant'Anna, Francisco, Roberto Ierusalimschy and Noemi Rodriguez</span><span class="bibfield year">2015</span><span class="bibfield title">Structured synchronous reactive programming with Céu</span><span class="bibfield journaltitle">Proceedings of the 14th International Conference on Modularity - MODULARITY 2015</span><span class="bibfield pages">2940</span><span class="anchors">[<a class="link-to-citation" href="#cite-111">111</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2724525.2724571">doi</a></div></div><div id="bib-Schlichting1983" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Schlichting, Richard D. and Fred B. Schneider</span><span class="bibfield year">1983</span><span class="bibfield title">Fail-stop processors: an approach to designing fault-tolerant computing systems</span><span class="bibfield journaltitle">ACM Transactions on Computer Systems</span><span class="bibfield volume">1</span><span class="bibfield number">3</span><span class="bibfield pages">222238</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-112">112</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/357369.357371">doi</a></div></div><div id="bib-Scholliers2009" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Scholliers, Christophe, Elisa González Boix and Wolfgang De Meuter</span><span class="bibfield year">2009</span><span class="bibfield title">TOTAM: Scoped Tuples for the Ambient</span><span class="bibfield booktitle">Proc. 2nd DisCoTec workshop on Context-aware Adaptation Mechanisms for Pervasive and Ubiquitous Services (CAMPUS)</span><span class="anchors">[<a class="link-to-citation" href="#cite-68">68</a>]</span></div></div><div id="bib-Scholliers2010" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Scholliers, Christophe, Elisa González Boix, Wolfgang De Meuter and Theo D'Hondt</span><span class="bibfield year">2010</span><span class="bibfield title">Context-Aware Tuples for the Ambient</span><span class="bibfield booktitle">Proc. On the Move to Meaningful Internet Systems (OTM)</span><span class="bibfield location">Crete, Greece</span><span class="anchors">[<a class="link-to-citation" href="#cite-69">69</a>]</span></div></div><div id="bib-Seidel1996" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Seidel, Raimund and Cecilia R. Aragon</span><span class="bibfield year">1996</span><span class="bibfield title">Randomized search trees</span><span class="bibfield journaltitle">Algorithmica</span><span class="bibfield volume">16</span><span class="bibfield number">4-5</span><span class="bibfield pages">464497</span><span class="anchors">[<a class="link-to-citation" href="#cite-143">143</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/BF01940876">doi</a></div></div><div id="bib-Shapiro2011" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Shapiro, Marc, Nuno Preguiça, Carlos Baquero and Marek Zawirski</span><span class="bibfield year">2011</span><span class="bibfield title">Conflict-free Replicated Data Types</span><span class="bibfield booktitle">Proc. 13th International Symposium on Stabilization, Safety, and Security of Distributed Systems (SSS 2011)</span><span class="bibfield location">Grenoble, France</span><span class="bibfield pages">386400</span><span class="bibfield date">October</span><span class="anchors">[<a class="link-to-citation" href="#cite-206">206</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-642-24550-3_29">doi</a></div></div><div id="bib-Sklower1991" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Sklower, Keith</span><span class="bibfield year">1991</span><span class="bibfield title">A Tree-Based Packet Routing Table for Berkeley Unix</span><span class="bibfield booktitle">USENIX Winter Conference</span><span class="anchors">[<a class="link-to-citation" href="#cite-151">151</a>]</span></div></div><div id="bib-Stoye1986" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Stoye, William</span><span class="bibfield year">1986</span><span class="bibfield title">Message-based Functional Operating Systems</span><span class="bibfield journaltitle">Science of Computer Programming</span><span class="bibfield volume">6</span><span class="bibfield pages">291311</span><span class="anchors">[<a class="link-to-citation" href="#cite-270">270</a>]</span></div></div><div id="bib-Sullivan1990" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Sullivan, Kevin and David Notkin</span><span class="bibfield year">1990</span><span class="bibfield title">Reconciling environment integration and component independence</span><span class="bibfield booktitle">Proceedings of the fourth ACM SIGSOFT symposium on Software development environments - SDE 4</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield volume">15</span><span class="bibfield number">6</span><span class="bibfield pages">2233</span><span class="bibfield date">October</span><span class="anchors">[<a class="link-to-citation" href="#cite-273">273</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/99277.99281">doi</a></div></div><div id="bib-Sundar1989" class="bibliography-entry"><div class="entrytype-report editor-count-0 no-dayofmonth has-author has-title has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Sundar, Rajamani and Robert E. Tarjan</span><span class="bibfield year">1989</span><span class="bibfield title">Unique Binary Search Tree Representations and Equality-Testing of Sets and Sequences</span><span class="bibfield date">November</span><span class="bibfield type-techreport"></span><span class="anchors">[<a class="link-to-citation" href="#cite-145">145</a>]</span></div></div><div id="bib-Tatroe2013" class="bibliography-entry"><div class="entrytype-book editor-count-0 no-dayofmonth has-author has-title has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">Tatroe, Kevin, Peter MacIntyre and Rasmus Lerdorf</span><span class="bibfield year">2013</span><span class="bibfield title">Programming PHP, 3rd edition</span><span class="bibfield publisher">O'Reilly Media</span><span class="bibfield pages">540</span><span class="anchors">[<a class="link-to-citation" href="#cite-72">72</a>]</span></div></div><div id="bib-Group2008" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title no-note no-howpublished no-date no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">The AMQP Working Group</span><span class="bibfield year">2008</span><span class="bibfield title">Advanced Message Queueing Protocol: Protocol Specification version 0-9-1</span><span class="anchors">[<a class="link-to-citation" href="#cite-35">35</a>]</span></div></div><div id="bib-Tobin-Hochstadt2008" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-location has-publisher has-pages no-note no-howpublished no-date no-issue no-number no-volume no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Tobin-Hochstadt, Sam and Matthias Felleisen</span><span class="bibfield year">2008</span><span class="bibfield title">The design and implementation of typed scheme</span><span class="bibfield journaltitle">Proceedings of the 35th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages - POPL '08</span><span class="bibfield location">New York, New York, USA</span><span class="bibfield publisher">ACM Press</span><span class="bibfield pages">395</span><span class="anchors">[<a class="link-to-citation" href="#cite-134">134</a>, <a class="link-to-citation" href="#cite-150">150</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/1328438.1328486">doi</a></div></div><div id="bib-Ungar1991" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages has-date no-note no-howpublished no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Ungar, David, Craig Chambers, Bay-Wei Chang and Urs Hölzle</span><span class="bibfield year">1991</span><span class="bibfield title">Organizing programs without classes</span><span class="bibfield journaltitle">Lisp and Symbolic Computation</span><span class="bibfield volume">4</span><span class="bibfield number">3</span><span class="bibfield pages">223242</span><span class="bibfield date">July</span><span class="anchors">[<a class="link-to-citation" href="#cite-235">235</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/BF01806107">doi</a></div></div><div id="bib-VanCutsem2014" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-publisher has-volume has-number has-pages has-date no-note no-howpublished no-issue no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Van Cutsem, Tom, Elisa González Boix, Christophe Scholliers, Andoni Lombide Carreton, Dries Harnie, Kevin Pinte and Wolfgang De Meuter</span><span class="bibfield year">2014</span><span class="bibfield title">AmbientTalk: programming responsive mobile peer-to-peer applications with actors</span><span class="bibfield journaltitle">Computer Languages, Systems &amp; Structures</span><span class="bibfield publisher">Elsevier</span><span class="bibfield volume">40</span><span class="bibfield number">3-4</span><span class="bibfield pages">112136</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-58">58</a>, <a class="link-to-citation" href="#cite-87">87</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1016/j.cl.2014.05.002">doi</a></div></div><div id="bib-VanDitmarsch" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">van Ditmarsch, Hans, Wiebe van der Hoek and Barteld Kooi</span><span class="bibfield year">2017</span><span class="bibfield title">Dynamic Epistemic Logic</span><span class="bibfield journaltitle">Internet Encyclopedia of Philosophy</span><span class="bibfield date">August</span><span class="anchors">[<a class="link-to-citation" href="#cite-13">13</a>, <a class="link-to-citation" href="#cite-187">187</a>]</span><a class="bibfield url" href="http://www.iep.utm.edu/de-logic/">link</a></div></div><div id="bib-Varela1999" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Varela, Carlos A. and Gul Agha</span><span class="bibfield year">1999</span><span class="bibfield title">A Hierarchical Model for Coordination of Concurrent Activities</span><span class="bibfield booktitle">Proc. Int. Conf. on Coordination Languages and Models</span><span class="bibfield pages">166182</span><span class="bibfield date">April</span><span class="anchors">[<a class="link-to-citation" href="#cite-39">39</a>, <a class="link-to-citation" href="#cite-286">286</a>, <a class="link-to-citation" href="#cite-287">287</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/3-540-48919-3_13">doi</a></div></div><div id="bib-Vieira2008" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-pages no-note no-howpublished no-date no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Vieira, Hugo T., Luís Caires and João C. Seco</span><span class="bibfield year">2008</span><span class="bibfield title">The Conversation Calculus: A Model of Service Oriented Computation</span><span class="bibfield booktitle">European Symposium on Programming</span><span class="bibfield pages">269283</span><span class="anchors">[<a class="link-to-citation" href="#cite-279">279</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1007/978-3-540-78739-6_21">doi</a></div></div><div id="bib-Viotti2016" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number no-note no-howpublished no-date no-pages no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Viotti, Paolo and Marko Vukolić</span><span class="bibfield year">2016</span><span class="bibfield title">Consistency in Non-Transactional Distributed Storage Systems</span><span class="bibfield journaltitle">ACM Computing Surveys (CSUR)</span><span class="bibfield volume">49</span><span class="bibfield number">1</span><span class="anchors">[<a class="link-to-citation" href="#cite-256">256</a>]</span></div></div><div id="bib-WebSub" class="bibliography-entry"><div class="entrytype-misc editor-count-0 has-dayofmonth has-author has-title has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">W3C</span><span class="bibfield year">2016</span><span class="bibfield title">WebSub, W3C working draft</span><span class="bibfield date">24 November</span><span class="anchors">[<a class="link-to-citation" href="#cite-245">245</a>]</span><a class="bibfield url" title="Accessed: 22 February 2017" href="https://www.w3.org/TR/websub/">link</a></div></div><div id="bib-Warth2016" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-pages has-date no-note no-howpublished no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Warth, Alessandro, Patrick Dubroy and Tony Garnock-Jones</span><span class="bibfield year">2016</span><span class="bibfield title">Modular Semantic Actions</span><span class="bibfield booktitle">Proc. Dynamic Languages Symposium</span><span class="bibfield location">Amsterdam, The Netherlands</span><span class="bibfield pages">108119</span><span class="bibfield date">November</span><span class="anchors">[<a class="link-to-citation" href="#cite-166">166</a>, <a class="link-to-citation" href="#cite-299">299</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1145/2989225.2989231">doi</a><a class="bibfield url" href="https://ohmlang.github.io/pubs/dls2016/modular-semantic-actions.pdf">link</a></div></div><div id="bib-Whiting1994" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-number has-pages no-note no-howpublished no-date no-issue no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Whiting, Paul G. and Robert S.V. Pascoe</span><span class="bibfield year">1994</span><span class="bibfield title">A History of Data-Flow Languages</span><span class="bibfield journaltitle">IEEE Annals of the History of Computing</span><span class="bibfield volume">16</span><span class="bibfield number">4</span><span class="bibfield pages">3859</span><span class="anchors">[<a class="link-to-citation" href="#cite-169">169</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1109/85.329757">doi</a></div></div><div id="bib-Wright1994" class="bibliography-entry"><div class="entrytype-article editor-count-0 no-dayofmonth has-author has-title has-journaltitle has-volume has-pages no-note no-howpublished no-date no-issue no-number no-publisher no-location no-institution no-organization no-edition no-booktitle no-editor"><span class="bibfield author">Wright, Andrew K. and Matthias Felleisen</span><span class="bibfield year">1994</span><span class="bibfield title">A Syntactic Approach to Type Soundness</span><span class="bibfield journaltitle">Information and Computation</span><span class="bibfield volume">115</span><span class="bibfield pages">3894</span><span class="anchors">[<a class="link-to-citation" href="#cite-104">104</a>]</span><a class="bibfield doi" href="https://dx.doi.org/10.1006/inco.1994.1093">doi</a></div></div><div id="bib-ANSI:Smalltalk:1997" class="bibliography-entry"><div class="entrytype-misc editor-count-0 no-dayofmonth has-author has-title has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-location no-institution no-organization no-edition no-journaltitle no-booktitle no-editor"><span class="bibfield author">X3J20 Committee for NCITS</span><span class="bibfield year">1997</span><span class="bibfield title">ANSI Smalltalk Standard v1.9 (draft)</span><span class="bibfield date">December</span><span class="anchors">[<a class="link-to-citation" href="#cite-227">227</a>]</span><a class="bibfield url" href="http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf">link</a></div></div><div id="bib-Yoo2012" class="bibliography-entry"><div class="entrytype-inproceedings editor-count-0 no-dayofmonth has-author has-title has-booktitle has-location has-date no-note no-howpublished no-pages no-issue no-number no-volume no-publisher no-institution no-organization no-edition no-journaltitle no-editor"><span class="bibfield author">Yoo, Sunghwan, Charles Killian, Terence Kelly, Hyoun Kyu Cho and Steven Plite</span><span class="bibfield year">2012</span><span class="bibfield title">Composable Reliability for Asynchronous Systems</span><span class="bibfield booktitle">Proceedings of the 2012 USENIX Annual Technical Conference</span><span class="bibfield location">Boston, Massachusetts</span><span class="bibfield date">June</span><span class="anchors">[<a class="link-to-citation" href="#cite-90">90</a>]</span><a class="bibfield url" href="https://www.usenix.org/system/files/conference/atc12/atc12-final206-7-20-12.pdf">link</a></div></div></div></p></div></body></html>