Peter Christensen

  • Presentations
  • Contact Me

Notes on Core.Async Webinar

August 23, 2014 by Peter Leave a Comment

Recently, David Nolen of Cognitect held a webinar about “Designing Front End Applications Using core.async”. I’m a huge fan of David’s teaching style (see his tutorials on Enlive, LightTable+ClojureScript, Om Basic and Om Intermediate) so I cleared my calendar. I’m very excited about Clojure’s front-end stack, with ClojureScript, core.async, and Transit, and after this webinar, I have a much clearer idea of how core.async fits in.

UPDATE: The recording is now live: http://go.cognitect.com/core_async_webinar_recording

Here are my notes

  • EXAMPLES – https://github.com/cognitect/async-webinar
  • Problems with Asynchronous programming
    • nesting callbacks is hard to maintain, read
    • JS is single-threaded
    • JS promises
      • better looking code, somewhat easier to read, but still a lot of callbacks. Chaining, not as nested
    • JS ES6 generators – extremely low level – core.async delivers the same benefits, but with a much higher level abstraction
  • ClojureScript
    • Cognitect – write the same types of apps, but simpler. Embrace and enhance the host
    • Immutability
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
  • Why ClojureScript?
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
    • Leverage Google Closure Compiler/Library
      • JS has many methods of packaging and delivery; Cljs only uses Closure
      • Superior minification + compression
        • dead code elimintation – include whatever you want, with no code bloat
      • Battle-tested standard library – support back to IE6
  • Core.Async
    • based on CSP (communicating sequential processes) – naturally captures one-off async tasks AND async streams/queues (e.g. mouse movements, etc)
    • Go blocks are a source transform that give the illusion of blocking, even in single-threaded context (i.e. JS hosts)
  • Terminology
    • Channels – conduit between different processes – put values in, take values out
      • Buffers – channels use them to configure backpressure, handle bursts of events; you can customize semantics
      • Transducers (new!) – efficient way to control how values enter and exit channel, e.g. map/filter
    • Go blocks – async blocks of execution with the illusion of blocking operations
  • Core Operations
    • putting values onto a channel
    • taking values off a channel
    • selecting over multiple channels (puts & takes)
  • 10 short examples
    • good enough first principles
    • repo available – https://github.com/cognitect/async-webinar – build, launch, follow along in browser
    • helpers
      • includes examples of JS interop
      • events→chan – listen for events, put them into the channel
        • use core.async to deal with events, instead of callbacks
      • mouse-loc→vec – turn events into vector
    • Example1
      • create a channel of clicks, block, and add a note
      • <! – blocking read inside of go blocks
    • Example 2 – same, but wait for 2 clicks
    • Example 3 – 2 channels, wait for one from each channel
    • Example 4 – shows how writing to a channel blocks that program until some other go block takes from the channel
    • Example 5 – separate go block to consume the channel
      • go blocks are like forking a process
      • looks like 2 separate processes running together and communicating over channels
    • Example 6 – stream processing
      • use transducer to convert events before they come into the channel
      • looks like an infinite loop – but getting a message off the click channel ends it
      • alts! – select over multiple channels – non-deterministically read from whichever channel has data first
        • line 140 – pattern matching on the channel
      • transducers let you work at a higher level of abstraction and data like you like it
    • Example 7 – more transducers
      • discard events unless the y is divisible by 5
      • loops can use the loop var bindings to record state
    • Example 8 – use loop vars to store state
    • Example 9 – more like real web
      • next/prev buttons to loop through a list
      • listen on prev/next channels to change vals, enable/disable prev/next
    • Example 10 – bigger example, broken out into helpers
      • more transducers – take all key presses, map the keyCode, filter by the set #{37 39}, and map them to :prev/:next
        • efficient because all those transformations happen in one function, inside the channel
      • click start, construct the keys channel
        • async/merge – take any number of channels, merge them into one channel (e.g. prev, next, keys) → a single channel that spits out :prev/:next
        • you can add more channels (e.g. left/right swipe on a tablet) and convert them to the same channels
  • Code is easier to manage and reason about new sources of events
  • Resources & Next Steps
    • original announcement – http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
    • Tim Baldrige Clojure/conj 2013 core.async talk (40 min vid) – http://www.youtube.com/watch?v=enwIIGzhahw
      • server-side work
      • portability between Clojure and ClojureScript
    • Facebook React – http://facebook.github.io/react
      • Works well with immutable data structures for UI
      • ClojureScript libs – Om, Reagent, Quiescent, Reacl
  • Q&A
    • How do you compose small pieces into a large front-end application?
      • Think about the abstract event types and handling, not concrete event sources
      • Core.async lets you write little distributed elements inside your UI
      • Components are independent and share a message language for coordination
    • Chan function – up to 3 args
      • int that sets buffer size or properties
        • more useful in server context than UI
      • on front end, best is to use size 1 and a transducer to transform the stream
    • Complex data?
      • All pre-built React components can work with any ClojureScript React library
    • Buffer size is 1 event – with data of arbitrary value
    • If you’re already running JVM, it makes more sense to use Nashorn JS on JVM lib instead of Node
    • You cannot monitor channels – they are purposely opaque

Filed Under: Clojure, Programming

Leave a Reply

You must be logged in to post a comment.

Categories

  • Blog
  • Book Review
  • Business
  • Clojure
  • Education
  • Emacs
  • Fun
  • iOS
  • Lisp
  • Personal Sprints
  • Pictures
  • Polyphasic
  • Presentations
  • Programming
  • Rails
  • Startups
  • Uncategorized

Copyright © 2025 · Minimum Pro Theme on Genesis Framework · WordPress · Log in