4. Complex languages
… are simply not
easy to understand
@jr0cket
Josh Smith - Tweet
Original Gif
5. The Complexity Iceberg
- @krisajenkins
● complexity is very
dangerous when hidden
● You can't know what a
function does for certain if it
has side effects
7. Pure Functions
The results of the function are purely determined by its initial output and its own code
- no external influence, a function only uses local values
- referential transparency (the function can be replaced by its value)
8. Impure Functions - side causes
The results of the function are purely determined by its initial output and its own code
- behaviour externally influenced and non-deterministic
9. Eliminating Side Effects
Functional programming is about eliminating side effects where you can,
controlling them where you can't - @krisajenkins
The features in Functional Programming come from a
desire to reduce side effects
21. Clojurescript Environments
Nashorn
- built into JVM, access Java classes
- Oracle Nashorn: A Next-Generation JavaScript Engine for the JVM
Browser-REPL
- built into modern browsers (Chrome, Firefox, etc)
- commonly used for client side web apps
Node.js
- great for command line utilities and microservices!
22. Common Clojurescript Tooling
Figwheel (leiningen plugin)
- defacto tool for client side web apps
- live reload and so much more...
Figwheel-sidecar
- connecting Emacs to figwheel
23. Full-stack projects: Chestnut
https://github.com/plexus/chestnut
- leiningen template for Clojure/ClojureScript apps based
- with Om, Reagent, or Rum
- instant reloading of Clojure, ClojureScript, and CSS
- browser-connected REPL included
lein new chestnut project-name
24. Self-hosted Clojurescript Environments
Instant startup times, great for command line tools
Lumo (cross-platform)
- https://github.com/anmonteiro/lumo
Plank (Mac & Linux)
- http://planck-repl.org/
28. What React Provides
React is only the view
You DO NOT GET any of the following:
An event system (other than vanilla DOM events)
Any AJAX capabilities whatsoever
Any form of a data layer
Promises
Any application framework at all
Any idea how implement the above
29. How React Works (Simplified)
Your view triggers an event
- a user types a name in a text field
That event updates a model
Then the model triggers an event
And the view responds to that model's event by
re-rendering with the latest data.
This one way data flow / decoupled observer
pattern is designed to guarantee that your source
of truth always stays in your stores / models
30. JSX
JSX is a preprocessor step that adds XML syntax to JavaScript.
You can definitely use React without JSX but JSX makes React a lot more elegant.
Just like XML, JSX tags have a tag name, attributes, and children.
If an attribute value is enclosed in quotes, the value is a string.
34. Reagent
Reagent provides a minimalistic interface between ClojureScript and React. It allows you to define efficient React components using
nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax.
The goal of Reagent is to make it possible to define arbitrarily complex UIs using just a couple of basic concepts, and to be fast
enough by default that you rarely have to care about performance.
35. Reagent Core functions
reagent.core/render
- Render a Reagent component into the DOM
- First argument is either a vector (Reagent Hiccup syntax) or a React element
reagent.core/atom
- Like clojure.core/atom, plus it tracks components that deref atom & re-renders them
36. Reagent Helper functions
clj->js
- convert values from clojurescript to javascript
js->clj
- transforms JavaScript arrays into ClojureScript vectors, and JavaScript objects
into ClojureScript maps
38. Reframe
re-frame is a pattern for writing SPAs in ClojureScript, using Reagent.
Being a functional framework, it is about data, and the (pure) functions which
transform that data.
It is a loop
Architecturally, re-frame implements "a perpetual loop".
To build an app, you hang pure functions on certain parts of this loop, and re-frame
looks after the conveyance of data around the loop, into and out of the transforming
functions you provide - hence a tag line of "Derived Values, Flowing".
40. Om / Om-next
Om allows users to represent their UIs simply as EDN. Because ClojureScript data is immutable data, Om can always rapidly
re-render the UI from the root. Thus Om UIs are out of the box snapshotable and undoable and these operations have no
implementation complexity and little overhead.
See for yourself.
Unique Features
Om supports features not currently present in React:
● Global state management facilities built in
● Components may have arbitrary data dependencies, not limited to props & state
● Component construction can be intercepted via :instrument. Simplifies debugging components and generic editors.
● Provides stream of all application state change deltas via :tx-listen. Simplifies synchronization online and offline.
● Customizable semantics. Fine grained control over how components store state, even for components outside of your control.
Simplifies using Om components outside the Om framework, debugging, and adding event hooks not anticipated by original
component designer.
41. Om core functions
om.core/IRender
- Render a Om component into the DOM
- uses reify to provide a specific implementation of the om/IRender interface
om.dom/div attributes content
- creates a <div> tag in react
- all react tags need to be wrapped in a div in order to be rendered
- om.dom/… has all the other tags too - h1, h2, p, a … (sablono can be used instead)
#js
- converts clojure maps into Javascript objects
- nest #js functions to to create JS objects - eg. for inline styles
42. Om Cursors
Cursors are a fundamental part of Om. They let components refer to pieces of
the app state without knowing where they are in the state tree. This makes
updating the app state simple, as the cursor is already pointing to the correct
part of the app state.
cursors are like maps, but cursors also let you write to them
A cursor is an atom & a path to a location in the atom
appstate :entries 0
44. Rum
Rum is a client/server library for HTML UI. In ClojureScript, it works as React wrapper, in Clojure, it is a static HTML
generator.
- Simple semantics: Rum is arguably smaller, simpler and more straightforward than React itself.
- Decomplected: Rum is a library, not a framework. Use only the parts you need, throw away or replace what you don’t
need, combine different approaches in a single app, or even combine Rum with other frameworks.
- No enforced state model: Unlike Om, Reagent or Quiescent, Rum does not dictate where to keep your state. Instead, it
works well with any storage: persistent data structures, atoms, DataScript, JavaScript objects, localStorage or any custom
solution you can think of.
- Extensible: the API is stable and explicitly defined, including the API between Rum internals. It lets you build custom
behaviours that change components in significant ways.
- Minimal codebase: You can become a Rum expert just by reading its source code (~900 lines).