{"id":641,"date":"2014-08-23T21:45:36","date_gmt":"2014-08-24T04:45:36","guid":{"rendered":"http:\/\/pchristensen.com\/blog\/?p=641"},"modified":"2014-08-27T12:19:09","modified_gmt":"2014-08-27T19:19:09","slug":"core-async-webinar","status":"publish","type":"post","link":"http:\/\/pchristensen.com\/blog\/articles\/core-async-webinar\/","title":{"rendered":"Notes on Core.Async Webinar"},"content":{"rendered":"<p>Recently, <a href=\"https:\/\/twitter.com\/swannodette\">David Nolen<\/a> of <a href=\"http:\/\/cognitect.com\/\">Cognitect<\/a> held a webinar about &#8220;Designing Front End Applications Using core.async&#8221;. I&#8217;m a huge fan of David&#8217;s teaching style (see his tutorials on <a href=\"https:\/\/github.com\/swannodette\/enlive-tutorial\">Enlive<\/a>, <a href=\"https:\/\/github.com\/swannodette\/lt-cljs-tutorial\">LightTable+ClojureScript<\/a>, <a href=\"https:\/\/github.com\/swannodette\/om\/wiki\/Basic-Tutorial\">Om Basic<\/a> and <a href=\"https:\/\/github.com\/swannodette\/om\/wiki\/Intermediate-Tutorial\">Om Intermediate<\/a>) so I cleared my calendar. I&#8217;m very excited about Clojure&#8217;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.<\/p>\n<p><strong>UPDATE<\/strong>: The recording is now live:\u00a0<a href=\"http:\/\/go.cognitect.com\/core_async_webinar_recording\">http:\/\/go.cognitect.com\/core_async_webinar_recording<\/a><\/p>\n<p>Here are my notes<\/p>\n<ul>\n<li>EXAMPLES &#8211; <a href=\"https:\/\/github.com\/cognitect\/async-webinar\">https:\/\/github.com\/cognitect\/async-webinar<\/a><\/li>\n<li>Problems with Asynchronous programming\n<ul>\n<li>nesting callbacks is hard to maintain, read<\/li>\n<li>JS is single-threaded<\/li>\n<li>JS promises\n<ul>\n<li>better looking code, somewhat easier to read, but still a lot of callbacks. Chaining, not as nested<\/li>\n<\/ul>\n<\/li>\n<li>JS ES6 generators &#8211; extremely low level &#8211; core.async delivers the same benefits, but with a much higher level abstraction<\/li>\n<\/ul>\n<\/li>\n<li>ClojureScript\n<ul>\n<li>Cognitect &#8211; write the same types of apps, but simpler. Embrace and enhance the host<\/li>\n<li>Immutability<\/li>\n<li>ClojureScript &#8211; good interop with JS runtimes + libraries, with Clojure language platform<\/li>\n<\/ul>\n<\/li>\n<li>Why ClojureScript?\n<ul>\n<li>ClojureScript &#8211; good interop with JS runtimes + libraries, with Clojure language platform<\/li>\n<li>Leverage Google Closure Compiler\/Library\n<ul>\n<li>JS has many methods of packaging and delivery; Cljs only uses Closure<\/li>\n<li>Superior minification + compression\n<ul>\n<li>dead code elimintation &#8211; include whatever you want, with no code bloat<\/li>\n<\/ul>\n<\/li>\n<li>Battle-tested standard library &#8211; support back to IE6<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Core.Async\n<ul>\n<li>based on CSP (communicating sequential processes) &#8211; naturally captures one-off async tasks AND async streams\/queues (e.g. mouse movements, etc)<\/li>\n<li>Go blocks are a source transform that give the illusion of blocking, even in single-threaded context (i.e. JS hosts)<\/li>\n<\/ul>\n<\/li>\n<li>Terminology\n<ul>\n<li>Channels &#8211; conduit between different processes &#8211; put values in, take values out\n<ul>\n<li>Buffers &#8211; channels use them to configure backpressure, handle bursts of events; you can customize semantics<\/li>\n<li>Transducers (new!) &#8211; efficient way to control how values enter and exit channel, e.g. map\/filter<\/li>\n<\/ul>\n<\/li>\n<li>Go blocks &#8211; async blocks of execution with the illusion of blocking operations<\/li>\n<\/ul>\n<\/li>\n<li>Core Operations\n<ul>\n<li>putting values onto a channel<\/li>\n<li>taking values off a channel<\/li>\n<li>selecting over multiple channels (puts &amp; takes)<\/li>\n<\/ul>\n<\/li>\n<li>10 short examples\n<ul>\n<li>good enough first principles<\/li>\n<li>repo available &#8211; <a href=\"https:\/\/github.com\/cognitect\/async-webinar\">https:\/\/github.com\/cognitect\/async-webinar<\/a> &#8211; build, launch, follow along in browser<\/li>\n<li>helpers\n<ul>\n<li>includes examples of JS interop<\/li>\n<li>events\u2192chan &#8211; listen for events, put them into the channel\n<ul>\n<li>use core.async to deal with events, instead of callbacks<\/li>\n<\/ul>\n<\/li>\n<li>mouse-loc\u2192vec &#8211; turn events into vector<\/li>\n<\/ul>\n<\/li>\n<li>Example1\n<ul>\n<li>create a channel of clicks, block, and add a note<\/li>\n<li>&lt;! &#8211; blocking read inside of go blocks<\/li>\n<\/ul>\n<\/li>\n<li>Example 2 &#8211; same, but wait for 2 clicks<\/li>\n<li>Example 3 &#8211; 2 channels, wait for one from each channel<\/li>\n<li>Example 4 &#8211; shows how writing to a channel blocks that program until some other go block takes from the channel<\/li>\n<li>Example 5 &#8211; separate go block to consume the channel\n<ul>\n<li>go blocks are like forking a process<\/li>\n<li>looks like 2 separate processes running together and communicating over channels<\/li>\n<\/ul>\n<\/li>\n<li>Example 6 &#8211; stream processing\n<ul>\n<li>use transducer to convert events before they come into the channel<\/li>\n<li>looks like an infinite loop &#8211; but getting a message off the click channel ends it<\/li>\n<li>alts! &#8211; select over multiple channels &#8211; non-deterministically read from whichever channel has data first\n<ul>\n<li>line 140 &#8211; pattern matching on the channel<\/li>\n<\/ul>\n<\/li>\n<li>transducers let you work at a higher level of abstraction and data like you like it<\/li>\n<\/ul>\n<\/li>\n<li>Example 7 &#8211; more transducers\n<ul>\n<li>discard events unless the y is divisible by 5<\/li>\n<li>loops can use the loop var bindings to record state<\/li>\n<\/ul>\n<\/li>\n<li>Example 8 &#8211; use loop vars to store state<\/li>\n<li>Example 9 &#8211; more like real web\n<ul>\n<li>next\/prev buttons to loop through a list<\/li>\n<li>listen on prev\/next channels to change vals, enable\/disable prev\/next<\/li>\n<\/ul>\n<\/li>\n<li>Example 10 &#8211; bigger example, broken out into helpers\n<ul>\n<li>more transducers &#8211; take all key presses, map the keyCode, filter by the set #{37 39}, and map them to :prev\/:next\n<ul>\n<li>efficient because all those transformations happen in one function, inside the channel<\/li>\n<\/ul>\n<\/li>\n<li>click start, construct the keys channel\n<ul>\n<li>async\/merge &#8211; take any number of channels, merge them into one channel (e.g. prev, next, keys) \u2192 a single channel that spits out :prev\/:next<\/li>\n<li>you can add more channels (e.g. left\/right swipe on a tablet) and convert them to the same channels<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Code is easier to manage and reason about new sources of events<\/li>\n<li>Resources &amp; Next Steps\n<ul>\n<li>original announcement &#8211; <a href=\"http:\/\/clojure.com\/blog\/2013\/06\/28\/clojure-core-async-channels.html\">http:\/\/clojure.com\/blog\/2013\/06\/28\/clojure-core-async-channels.html<\/a><\/li>\n<li>Tim Baldrige Clojure\/conj 2013 core.async talk (40 min vid) &#8211; <a href=\"http:\/\/www.youtube.com\/watch?v=enwIIGzhahw\">http:\/\/www.youtube.com\/watch?v=enwIIGzhahw<\/a>\n<ul>\n<li>server-side work<\/li>\n<li>portability between Clojure and ClojureScript<\/li>\n<\/ul>\n<\/li>\n<li>Facebook React &#8211; <a href=\"http:\/\/facebook.github.io\/react\">http:\/\/facebook.github.io\/react<\/a>\n<ul>\n<li>Works well with immutable data structures for UI<\/li>\n<li>ClojureScript libs &#8211; Om, Reagent, Quiescent, Reacl<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Q&amp;A\n<ul>\n<li>How do you compose small pieces into a large front-end application?\n<ul>\n<li>Think about the abstract event types and handling, not concrete event sources<\/li>\n<li>Core.async lets you write little distributed elements inside your UI<\/li>\n<li>Components are independent and share a message language for coordination<\/li>\n<\/ul>\n<\/li>\n<li>Chan function &#8211; up to 3 args\n<ul>\n<li>int that sets buffer size or properties\n<ul>\n<li>more useful in server context than UI<\/li>\n<\/ul>\n<\/li>\n<li>on front end, best is to use size 1 and a transducer to transform the stream<\/li>\n<\/ul>\n<\/li>\n<li>Complex data?\n<ul>\n<li>All pre-built React components can work with any ClojureScript React library<\/li>\n<\/ul>\n<\/li>\n<li>Buffer size is 1 event &#8211; with data of arbitrary value<\/li>\n<li>If you&#8217;re already running JVM, it makes more sense to use Nashorn JS on JVM lib instead of Node<\/li>\n<li>You cannot monitor channels &#8211; they are purposely opaque<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Recently, David Nolen of Cognitect held a webinar about &#8220;Designing Front End Applications Using core.async&#8221;. I&#8217;m a huge fan of David&#8217;s teaching style (see his tutorials on Enlive, LightTable+ClojureScript, Om Basic and Om Intermediate) so I cleared my calendar. I&#8217;m very excited about Clojure&#8217;s front-end stack, with ClojureScript, core.async, and Transit, and after this webinar, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[14,10],"tags":[],"class_list":{"0":"post-641","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-clojure","7":"category-programming","8":"entry"},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pazgP-al","_links":{"self":[{"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/posts\/641","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/comments?post=641"}],"version-history":[{"count":0,"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/posts\/641\/revisions"}],"wp:attachment":[{"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/media?parent=641"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/categories?post=641"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/pchristensen.com\/blog\/wp-json\/wp\/v2\/tags?post=641"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}