FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O...
Transcript of FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O...
![Page 1: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/1.jpg)
freshfreshdietdietTHETHE
Fresh, Gourmet, Delivered DailyFresh, Gourmet, Delivered Daily
FRP in ClojureScript with JavelinFRP in ClojureScript with JavelinAlan DipertAlan Dipert@alandipert@alandipert
![Page 2: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/2.jpg)
![Page 3: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/3.jpg)
nginx
syslog-ng
jetty
postgresredis
![Page 4: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/4.jpg)
![Page 5: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/5.jpg)
fn
fn
val val val
![Page 6: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/6.jpg)
(+ 1 (* 2 3))
+
1
*
2 3
![Page 7: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/7.jpg)
Applicative EvaluationApplicative Evaluation
● Evaluate argumentsEvaluate arguments● Syntax specifies orderSyntax specifies order
● Apply arguments to functionsApply arguments to functions● No notion of timeNo notion of time
● Almost: in Clojure, CL args eval left to rightAlmost: in Clojure, CL args eval left to right
![Page 8: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/8.jpg)
(+ 1 (* 2 ?))
+
1
*
2 ?
![Page 9: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/9.jpg)
(+ 1 (* 2 ?))
+
1 2 ?
![Page 10: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/10.jpg)
(+ 1 (* 2 ?))
1 2 ?
![Page 11: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/11.jpg)
1 2 ?
ThreadThread
![Page 12: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/12.jpg)
Child ThreadChild Thread
Child ThreadChild Thread
Parent ThreadParent Thread
![Page 13: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/13.jpg)
+ time+ time==
![Page 14: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/14.jpg)
+ time+ time==FunctionalFunctionalReactive Reactive ProgrammingProgramming
![Page 15: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/15.jpg)
Reactive EvaluationReactive Evaluation
+
1
*
2 ?
![Page 16: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/16.jpg)
Reactive EvaluationReactive Evaluation
+
1
*
2 4
do something with result
![Page 17: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/17.jpg)
Reactive EvaluationReactive Evaluation
● Maintain dependency order of processesMaintain dependency order of processes● Evaluation triggered by availability of Evaluation triggered by availability of
argumentsarguments● Instead of by invocation of parentInstead of by invocation of parent
● Programs look/feel applicativePrograms look/feel applicative● We don't need threads (necessarily)We don't need threads (necessarily)
![Page 18: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/18.jpg)
Browsers: bells, whistles, gotchasBrowsers: bells, whistles, gotchas
● JavaScript event loopJavaScript event loop● Callbacks everywhereCallbacks everywhere
● DOM (Document Object Model)DOM (Document Object Model)● DOM elements contribute to application state, but DOM elements contribute to application state, but
are poor variables: they're mutable globalsare poor variables: they're mutable globals
see hlisp! https://github.com/tailrecursion/hlisp-starter
![Page 19: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/19.jpg)
FRP: Objects in PlayFRP: Objects in Play
● Event StreamsEvent Streams● Sources of zero or more values over timeSources of zero or more values over time● Incoming events trigger activity in whatever is Incoming events trigger activity in whatever is
listeninglistening
● Behaviors (a.k.a. Signals)Behaviors (a.k.a. Signals)● Always-valued boxes, Always-valued boxes, refref-like-like● Value can be derived from a function applied to 1 or Value can be derived from a function applied to 1 or
more “constituent” objectsmore “constituent” objects● Application of this function is triggered by activity in Application of this function is triggered by activity in
constituent objectsconstituent objects
![Page 20: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/20.jpg)
FRP: Fundamental OperationsFRP: Fundamental Operations
● Event StreamsEvent Streams● filterfilter, , mapmap, , mergemerge etc. etc.● startsWithstartsWith: return a new Behavior backed by the : return a new Behavior backed by the
stream, provided an initial valuestream, provided an initial value
● BehaviorsBehaviors● liftlift: return a new Behavior provided 1 or more : return a new Behavior provided 1 or more
other objects and a function other objects and a function ● changeschanges: return a new Event Stream carrying a : return a new Event Stream carrying a
Behavior's value over timeBehavior's value over time
![Page 21: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/21.jpg)
FRP with Flapjax: ExampleFRP with Flapjax: Example
HTML<body onload="demo.start()" <h3>Flapjax Demo</h3> <input type="text" id="n1" value="0"/> <input type="text" id="n2" value="0"/> <span id="sum">0</span></body>
Browser
![Page 22: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/22.jpg)
Browser
ClojureScript(defn extractFloatE [id] (F/mapE parse-float (F/extractValueE id)))
(defn start [] (let [n1 (extractFloatE "n1") n2 (extractFloatE "n2") sum (F/liftB + n1 n2)] (F/insertValueB sum "sum" "innerHTML")))
![Page 23: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/23.jpg)
Browser
ClojureScript(defn extractFloatE [id] (F/mapE parse-float (F/extractValueE id)))
(defn start [] (let [n1 (extractFloatE "n1") n2 (extractFloatE "n2") sum (F/liftB + n1 n2)] (F/insertValueB sum "sum" "innerHTML")))
![Page 24: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/24.jpg)
Browser
M-x ceremony-mode(defn extractFloatE [id] (F/mapE parse-float (F/extractValueE id)))
(defn start [] (let [n1 (extractFloatE "n1") n2 (extractFloatE "n2") sum (F/liftB + n1 n2)] (F/insertValueB sum "sum" "innerHTML")))
![Page 25: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/25.jpg)
Browser
ClojureScript(defn extractFloatE [id] (F/mapE parse-float (F/extractValueE id)))
(defn start [] (let [n1 (extractFloatE "n1") n2 (extractFloatE "n2") sum (F/liftB + n1 n2)] (F/insertValueB sum "sum" "innerHTML")))
![Page 26: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/26.jpg)
Browser
ClojureScript(defn extractFloatE [id] (F/mapE parse-float (F/extractValueE id)))
(defn start [] (let [n1 (extractFloatE "n1") n2 (extractFloatE "n2") sum (+ n1 n2)] (F/insertValueB sum "sum" "innerHTML")))
![Page 27: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/27.jpg)
omg
![Page 28: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/28.jpg)
SpreadsheetsSpreadsheets
● Input cellsInput cells● user inserts values, evaluation propagates when user inserts values, evaluation propagates when
new values are enterednew values are entered
● Formula cellsFormula cells● user defines, evaluated when constituent cells user defines, evaluated when constituent cells
change valuechange value
● If spreadsheets are so awesome, why do we If spreadsheets are so awesome, why do we care about FRP?care about FRP?
![Page 29: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/29.jpg)
Continuous vs. Discrete Continuous vs. Discrete PropagationPropagation
● Spreadsheet propagation is Spreadsheet propagation is continuouscontinuous● Evaluation only happens if new values are Evaluation only happens if new values are
introduced into the systemintroduced into the system● It's not possible to trigger evaluation without It's not possible to trigger evaluation without
providing a new valueproviding a new value
● FRP evaluation is continuous and/or FRP evaluation is continuous and/or discretediscrete● liftlift can take Event Stream arguments can take Event Stream arguments● Event Streams trigger evaluation in dependents Event Streams trigger evaluation in dependents
when any value is received, regardless of noveltywhen any value is received, regardless of novelty
![Page 30: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/30.jpg)
<opinion><opinion>● FRP might be good for modeling I/O flows that FRP might be good for modeling I/O flows that
are for side effects only (e.g. Rx Observables)are for side effects only (e.g. Rx Observables)● FRP not awesome in ClojureScriptFRP not awesome in ClojureScript
● Application state spreads across the graph as Application state spreads across the graph as intermediate, disparate Behaviorsintermediate, disparate Behaviors
● Requires special control structures (Requires special control structures (switchEswitchE))● Implying Event Streams Implying Event Streams of Event Streams of Event Streams of Event Streams …of Event Streams … ● Hard to debug without static type systemHard to debug without static type system
● Overlap between Behavior, Event Stream APIsOverlap between Behavior, Event Stream APIs● No integration point with Clojure state modelNo integration point with Clojure state model
</opinion></opinion>
![Page 31: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/31.jpg)
JavelinJavelin
Abstract spreadsheet library for reactive Abstract spreadsheet library for reactive programming with values in ClojureScript.programming with values in ClojureScript.
Proudly delivered as a single macro, Proudly delivered as a single macro, cellcell, that , that you write regular ClojureScript inside of.you write regular ClojureScript inside of.
![Page 32: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/32.jpg)
ClojureScript(defn start [] (let [a (cell 0) b (cell (inc a)) c (cell (+ 123 a b))] (cell (.log js/console c)) (swap! a inc) (js/alert @b)))
input cellformula cellformula cellanon. formula cellmutationdereference
![Page 33: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/33.jpg)
ClojureScript(let [a (cell 0) b (cell (inc a)) c (cell (+ 123 a b))] (cell (.log js/console c)) (swap! a inc))
a
b
c
(.log js/console c)
(swap! a inc)
Javelin guarantees Javelin guarantees that cell that cell cc sees only sees only consistentconsistent values of values of aa and and bb. This makes . This makes Javelin “glitch-free”Javelin “glitch-free”
![Page 34: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/34.jpg)
Javelin's OpinionsJavelin's Opinions
● At any point in time, a web application is in At any point in time, a web application is in exactly one stateexactly one state● ...and that state is stored as a value in an input cell ...and that state is stored as a value in an input cell
we call the “stem cell”we call the “stem cell”● The stem cell is the root node of the dependency The stem cell is the root node of the dependency
graph representing the application's behaviorgraph representing the application's behavior
● Everything the user sees or can do is governed Everything the user sees or can do is governed by data in the stem cellby data in the stem cell● ...or derived formula cells...or derived formula cells
![Page 35: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/35.jpg)
““Real” Javelin AppsReal” Javelin Apps
● We use 2 other things to build our applications:We use 2 other things to build our applications:● hlisp: compiles HTML to ClojureScripthlisp: compiles HTML to ClojureScript● wigwam: server, client RPC machinerywigwam: server, client RPC machinery
● Available at Available at https://github.com/tailrecursionhttps://github.com/tailrecursion
![Page 36: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/36.jpg)
Javelin/hlisp/wigwam architectureJavelin/hlisp/wigwam architecture
wigwamstem cell
cellDOM(hlisp)
clientclient serverserver
● DOM elements bound to cells (hlisp) DOM elements bound to cells (hlisp) ● RPC always return stem cell (wigwam)RPC always return stem cell (wigwam)
![Page 37: FRP in ClojureScript with Javelinalan/index.cgi/doc/tip/... · FRP might be good for modeling I/O flows that are for side effects only (e.g. Rx Observables) FRP not](https://reader033.fdocuments.in/reader033/viewer/2022050605/5fad060b3392a74d9321dae4/html5/thumbnails/37.jpg)
freshfreshdietdietTHETHE
Fresh, Gourmet, Delivered DailyFresh, Gourmet, Delivered Daily
Thank you!Thank you!