Your SlideShare is downloading. ×
ClojureScript  Anatomy
Targeting JavaScript
Why?Targeting JavaScript
Primacy                              of                          SemanticsI also regard syntactical problems as essentiall...
JavaScript has much in common with                              Scheme.                     It is a dynamic language.     ...
Power Points• Reach • browser, shell, mobile, databases• First-class functions• Prototypal inheritance• Closures• Literal ...
Pain Points
Pain Points• Everything else
JavaScript
JavaScript    • Safety through convention
JavaScript    • Safety through convention    • Rampant mutation
JavaScript    • Safety through convention    • Rampant mutation    • Globals
JavaScript    • Safety through convention    • Rampant mutation    • Globals    • this
JavaScript    • Safety through convention    • Rampant mutation    • Globals    • this    • Truthiness
JavaScript    • Safety through convention    • Rampant mutation    • Globals    • this    • Truthiness    • Objects make p...
JavaScript•   Safety through convention•   Rampant mutation•   Globals•   this•   Truthiness•   Objects make poor modules
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation•   Globals•   this•...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
JavaScript•   Safety through convention                                • Callbacks•   Rampant mutation                    ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = ...
Google Closure• Standard library• Dependency system• Compiler/minifier (GClosure)• Templating language• 1 kajillion man-hou...
Google Closure• Standard library• Dependency system• Compiler/minifier (GClosure)• Templating language• 1 beellion man-hour...
convention    convention  convention conventionconvention
Primacy                      of                    Syntax     one could say that all semantics is being represented as syn...
CoffeeScript
the web be
Namespaces
ECMAScript.NextJSModule                             nodules       modules.js            curl.js
Namespacesfogus.my.lib.frobnicate();
Namespacesfogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = fogus.my.lib || {};
Namespaces(ns fogus.my.lib)(defn frobnicate [] :frobbed!)    goog.provide(‘fogus.my.lib)    ;    fogus.my.lib = function()...
Compression Potential
Take your pick(ns fogus.my.lib)goog.provide(‘fogus.my.lib’);fogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = f...
Take your pick(ns fogus.my.lib)goog.provide(‘fogus.my.lib’);fogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = f...
Abstracti ns
Abstractions• Protocols at the bottom • ISeq, IMap, ILookup, IDeref, etc.• Realizing powerful immutable types • Map, List,...
JavaScript    the   Parts
Functional Inheritance       Pattern• Private data• Access to super methods• Missing new safe
Functional Inheritance                    Patternvar person = function(spec) {  var that = {};     that.getName = function...
Functional Inheritance  Pattern Dangers• Harder to minify• Larger memory footprint• Cannot update instances• Eliminates in...
Pseudo-classical               Inheritance PatternPerson = function(name) {   this._name = name;};                        ...
Pseudo-classical   Inheritance Pattern• Harder Easier to minify• Larger Smaller memory footprint• Cannot Can update instan...
Safe ExtensionString.prototype.cljs$core$first = ...Object.prototype.my$lib$first = ...
me._name//=> ‘Fogus’
Minification• Inlining• Renaming• Dead-code elimination
Inlining
Functional Inheritance               Inliningvar person = function(spec) {      var myName = me.getName();  var that = {};...
Functional Inheritance               Inliningvar person = function(spec) {          var myName = me.getName();  var that =...
Functional Inheritance               Inliningvar person = function(spec) {              var myName = me.getName();  var th...
Inlining
Pseudo-classical InliningPerson = function(name) {   this._name = name;                                              var m...
Pseudo-classical InliningPerson = function(name) {   this._name = name;                                            var myN...
Renaming
Functional Inheritance      Renaming   var person = function(spec) {     var that = {};        that.getName = function() {...
Functional Inheritance      Renaming   var person = function(spec) {     var that = {};        that.getName = function() {...
Renaming
Pseudo-classical   RenamingPerson = function(name) {   this._name = name;};Person.prototype.getName = function() {   retur...
Pseudo-classical   RenamingPerson = function(name) {   this._name = name;};Person.prototype.o = function() {   return this...
Dead Code
Dead-code Elimination       Intro(let [a 1      b 2      a b]  a);=> 2
Dead-code Elimination       Intro               (function (){(let [a 1        var a__847 = 1;      b 2        var b__848 =...
Dead-code Elimination       Intro                 (function (){(let [a 1          var a__847 = 1;      b 2          var b_...
Dead-code Elimination       Intro                 (function (){(let [a 1          var a__847 = 1;      b 2          var b_...
Dead-code Elimination       Intro               (function (){(let [a 1        var a__847 = 1;      b 2        var b__848 =...
Functional Inheritance     Dead-code   var person = function(spec) {     var that = {};     var hasBeard = false;        t...
Functional Inheritance     Dead-code   var person = function(spec) {     var that = {};     var hasBeard = false;        t...
Functional Inheritance     Dead-code   var person = function(spec) {     var that = {};     var hasBeard = false;        t...
Dead Code
Pseudo-classical  Dead-codePerson = function(name) {   this._name = name;   this._hasBeard = false;};Person.prototype.getN...
Pseudo-classical  Dead-codePerson = function(name) {   this._name = name;   this._hasBeard = false;};Person.prototype.getN...
Pseudo-classical  Dead-codePerson = function(name) {  this._name = name;};                              kthxbaiPerson.prot...
There’s more to life than     this
Memory Footprint• Crockford • Closure per-method, per-type • Leaky (holds a reference to all variables)• Pseudo-classical ...
Live
Instance Updating• Problem • How to update every instance in the    system with new behavior?
Functional Inheritance       Updating         var person = function(spec) {           var that = {};              that.get...
Functional Inheritance       Updating         var person = function(spec) {           var that = {};              that.get...
ClojureScript   Cares.
ClojureScript            Extending                 (defprotocol Catable                   (cat [this other]))             ...
ClojureScript  Extending       (extend-type string         Catable         (cat [this other]           (str this other))) ...
Pseudo-classical         Updating         Person = function(name) {            this._name = name;         };         Perso...
Pseudo-classical               Updating               Person = function(name) {                  this._name = name;       ...
apply
function
Var Args JavaScript          ClojureScriptarguments             & stuff
Var Args     JavaScript          ClojureScript   arguments              & stuffAn object that holds    arguments          ...
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply    (defn apply      [f arg-seq]      (.apply f (to-array arg-seq)))
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply                                   (defn add-first-two                                     [& args]    ...
ClojureScript apply                                   ∞                                   (defn add-first-two             ...
ClojureScript apply    (defn apply      [f arg-seq]      (.apply f (to-array arg-seq)))
ClojureScript           applyTo• A function stored on ClojureScript functions • Only if they have var args• Compiled to on...
ClojureScript apply    (defn apply      [f arg-seq]      (if (.applyTo f)       (if (<= bounded-count fixed-arity)        ...
ClojureScript apply    (defn apply      [f arg-seq]      (if (.applyTo f)       (if (<= bounded-count fixed-arity)        ...
ClojureScript apply    (defn apply      [f arg-seq]      (if (.applyTo f)       (if (<= bounded-count fixed-arity)        ...
ClojureScript apply    (defn apply      [f arg-seq]      (if (.applyTo f)       (if (<= bounded-count fixed-arity)        ...
CompilerAnatomy
Cl  oju        re           D   at                    a                        AS                          T
Analysis
Emission
C6     4         JA           VA              SC                 RIP                       T
Thank                           Youhttp://joyofclojure.com         @fogus
Learn More•   http://bit.ly/cljs-intro•   http://boss-level.com/?p=102•   http://blog.fogus.me/tag/clojurescript•   http:/...
Crockford Hates instanceof
Functional Inheritance   instanceof    var me   = person({name : Fogus});    me instanceof person;    //=> false
ClojureScript Loves  instanceof
Pseudo-classicalinstanceof var me   = new Person(Fogus); me instanceof Person; //=> true
ClojureScriptsatisfies? (defprotocol Catable   (cat [this other])) (deftype Cons [H T]   Catable   (cat [_ new-tail] nil))...
tread
Don’t Tread on Me Function.prototype.method = function(name, f) {    this.prototype[name] = f;    return this; }; Object.m...
ClojureScript Gently       CaressesObject & Function  as One Might Caress the finest Fabergé Egg
Look with your eyes,not with your hands  var inherits = function(child, parent) {    function tmp() {};    tmp.prototype =...
Var Args       JavaScript               ClojureScriptfunction stuffToArray() {       (defn stuff->seq  // create an array ...
Var Args       JavaScript               ClojureScriptfunction stuffToArray() {       (defn stuff->seq  // create an array ...
Var Args               JavaScript                         ClojureScriptfunction stuffToArray() {                         (...
Compiler Macros• Operate in the compiler only • Analysis phase• Written in Clojure• Allows shadowing of fns • Operates acc...
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
ClojureScript Anatomy
Upcoming SlideShare
Loading in...5
×

ClojureScript Anatomy

3,918

Published on

A deep dive into the inner workings of ClojureScript's analysis,
88 compilation, and runtime phases. The talk focused specifically on
89 the way that traditional JavaScript abstractions thwart code-size
90 and efficiency and how ClojureScript avoids such pitfalls. Finally,
91 I told a couple "war stories" about some of the specific challenges
92 met by the Clojure/core team during the development of the compiler
93 and runtime.

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,918
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
0
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • * One of the great stories in the history of hacking\n* Right up there with that guy who used autoconfig properly\n
  • \n
  • * If JavaScript is so cool, then why target it? Why not use it?\n
  • * The meaning is king. \n* Anything that can be done in CLJS can be done with JS\n * This is the root of all Turing completeness arguments\n\n
  • * For the purposes of writing Little Schemer only\n
  • Everyone implements classes. :-(\n
  • * first-class functions\n* prototypal\n* closures\n* literals\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • * Really this is the only snarky language joke I&amp;#x2019;ll say all day. \n
  • * This is Douglass Crockford\n* Seems like a nice guy\n* Wrote a book about using only the nice parts of JS\n
  • * But there is something sinister about this advice!\n
  • * How is JavaScript like a Russian novel?\n
  • \n
  • * Semicolons\n
  • * Namespacing\n
  • * Closure pattern\n
  • * LET pattern\n
  • * VAR\n
  • * privates\n
  • * publics\n
  • * And after all of that... you can add some functionality.\n
  • * You need to introduce thousands of characters before anything happens.\n
  • \n
  • \n
  • Anyone have experience with GClosure? It&amp;#x2019;s tough to follow the conventions. I wrote every function/form in js *before* I wrote the cljs impl.\n
  • \n
  • \n
  • \n
  • * conventions conventions conventions\n* It&amp;#x2019;s too much to think about sometimes, but people will get used to *anything*\n* But you&amp;#x2019;ve still not yet solved the problem at hand.\n* JS with a rabid adherence to conventions is 84% as safe as Haskell!\n
  • * All useful semantics become syntax.\n* In JS, its syntax betrays its semantics because intent is buried in idiom, verbosity, and safety checks.\n* CLJS (and LISP) leave syntax as an open set in order to allow one to build the syntax to match the semantics.\n\n| Isn&apos;t the semantics more important the syntax?\n\ngenerally speaking, if this were true, we would not see the syntax-fixation\nthat the whole industry is built on. syntax _distinguishes_ programming\nlanguages from each other; the semantics is only a question of how much of\nthe syntax you need to implement it. e.g., if CFRONT can produce C code\nfrom C++, so can a human. syntax can help automate the expression of the\nsemantics in very important ways, or serve to frustrate the same process.\nhowever, certain operations are possible (that is, sufficiently easy) on\ncertain syntaxes, which leads me to the more specific interpretation.\n
  • * Let&amp;#x2019;s talk a moment to talk about CoffeeScript\n* Enjoyed my time\n* JS the good parts -- eliminates much of the ceremony, many edge cases (while introducing some of its own)\n* But maybe we need something more...\n
  • Asynchronous - DOM - Constant serialization - Limited resources and slow pipes - Hostile environment\n
  • \n
  • \n
  • * Because you can!\n* Although there are many flavors, they tend to a common pattern...\n
  • * This is a namespaced JS function.\n* Nested objects\n
  • \n
  • * This leads me into a nice discussion about compression potential...\n
  • * What do I mean?\n* Not golfing!\n
  • * You can get fairly compressed in the second example, but this is indicative only of this problem, and not in the language itself.\n* CoffeeScript doesn&amp;#x2019;t fix this. It shaves characters, but that&amp;#x2019;s all.\n
  • \n
  • * Why so many class systems? \n* Because you can!\n* Many suffer from a lack of safety or composability\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • * Clojure ensures safety by...\n
  • * To Crockford&amp;#x2019;s credit, his is better encapsulated.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • * functions cause complication\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • * Simple as CLJ\n
  • * Compiler Macros\n
  • * AST\n
  • * AST\n
  • \n
  • * Well, this is what I&amp;#x2019;ve already talked about\n
  • \n
  • * People are already using the analyzer\n* typing, Marg, etc.\n
  • \n
  • \n
  • \n
  • * AWESOME Syntax Tree!!!\n
  • \n
  • \n
  • \n
  • * Get rid of everything but the emitter\n* Remember it takes an AST\n
  • * Parser generates an AST in CLJS format\n
  • * Parser generates an AST in CLJS format\n
  • Rock On!\n
  • Make something amazing\n
  • Possibilities are Limitless\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • * TODO: More talking points here --- example?\n
  • Transcript of "ClojureScript Anatomy"

    1. 1. ClojureScript Anatomy
    2. 2. Targeting JavaScript
    3. 3. Why?Targeting JavaScript
    4. 4. Primacy of SemanticsI also regard syntactical problems as essentially irrelevant to programming languages at their present stage ... the urgent task in programming languages is to explore the field of semantic possibilities. — Christopher Strachey - “Fundamental Concepts in Programming Languages”
    5. 5. JavaScript has much in common with Scheme. It is a dynamic language. It has a flexible datatype (arrays) that can easily simulate s-expressions. And most importantly, functions are lambdas.http://javascript.crockford.com/little.html
    6. 6. Power Points• Reach • browser, shell, mobile, databases• First-class functions• Prototypal inheritance• Closures• Literal syntax
    7. 7. Pain Points
    8. 8. Pain Points• Everything else
    9. 9. JavaScript
    10. 10. JavaScript • Safety through convention
    11. 11. JavaScript • Safety through convention • Rampant mutation
    12. 12. JavaScript • Safety through convention • Rampant mutation • Globals
    13. 13. JavaScript • Safety through convention • Rampant mutation • Globals • this
    14. 14. JavaScript • Safety through convention • Rampant mutation • Globals • this • Truthiness
    15. 15. JavaScript • Safety through convention • Rampant mutation • Globals • this • Truthiness • Objects make poor modules
    16. 16. JavaScript• Safety through convention• Rampant mutation• Globals• this• Truthiness• Objects make poor modules
    17. 17. JavaScript• Safety through convention • Callbacks• Rampant mutation• Globals• this• Truthiness• Objects make poor modules
    18. 18. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals• this• Truthiness• Objects make poor modules
    19. 19. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals • Limited data formats• this• Truthiness• Objects make poor modules
    20. 20. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals • Limited data formats• this • Limited abstractions• Truthiness• Objects make poor modules
    21. 21. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals • Limited data formats• this • Limited abstractions• Truthiness • ==• Objects make poor modules
    22. 22. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals • Limited data formats• this • Limited abstractions• Truthiness • ==• Objects make poor modules • Optional semicolons
    23. 23. JavaScript• Safety through convention • Callbacks• Rampant mutation • Low Compression Potential• Globals • Limited data formats• this • Limited abstractions• Truthiness • ==• Objects make poor modules • Optional semicolons • Missing `new`
    24. 24. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; function init(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    25. 25. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; function init(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    26. 26. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; function init(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    27. 27. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; function init(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    28. 28. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; var init = function(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    29. 29. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; var init = function(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    30. 30. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; var init = function(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    31. 31. my = my || {};my.awesome = my.awesome || {};my.awesome.lib = my.awesome.lib ||{};my.awesome.lib = (function(){ var that = {}; var init = function(){ /* do something */ }; that.foo = true; that.init = init; return that;}());my.awesome.lib.frob = (function($){ function privateFun(){ /* do something */ } return function() { /* do something with $ */ };
    32. 32. Google Closure• Standard library• Dependency system• Compiler/minifier (GClosure)• Templating language• 1 kajillion man-hours of effort
    33. 33. Google Closure• Standard library• Dependency system• Compiler/minifier (GClosure)• Templating language• 1 beellion man-hours of effort
    34. 34. convention convention convention conventionconvention
    35. 35. Primacy of Syntax one could say that all semantics is being represented as syntax... semantics has vanished entirely to be replaced with pure syntax. — John Shutt - “Primacy of Syntax”
    36. 36. CoffeeScript
    37. 37. the web be
    38. 38. Namespaces
    39. 39. ECMAScript.NextJSModule nodules modules.js curl.js
    40. 40. Namespacesfogus.my.lib.frobnicate();
    41. 41. Namespacesfogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = fogus.my.lib || {};
    42. 42. Namespaces(ns fogus.my.lib)(defn frobnicate [] :frobbed!) goog.provide(‘fogus.my.lib) ; fogus.my.lib = function() { return “□ :frobbed!” };
    43. 43. Compression Potential
    44. 44. Take your pick(ns fogus.my.lib)goog.provide(‘fogus.my.lib’);fogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = fogus.my.lib || {};
    45. 45. Take your pick(ns fogus.my.lib)goog.provide(‘fogus.my.lib’);fogus = fogus || {};fogus.my = fogus.my || {};fogus.my.lib = fogus.my.lib || {};
    46. 46. Abstracti ns
    47. 47. Abstractions• Protocols at the bottom • ISeq, IMap, ILookup, IDeref, etc.• Realizing powerful immutable types • Map, List, Vector, etc.• Extended to JavaScript • strings, null, arrays, etc.
    48. 48. JavaScript the Parts
    49. 49. Functional Inheritance Pattern• Private data• Access to super methods• Missing new safe
    50. 50. Functional Inheritance Patternvar person = function(spec) { var that = {}; that.getName = function() { var me = person({name : Fogus}); return spec.name; me.getName() }; //=> Fogus return that;};var man = function(spec) { var that = person(spec); var super_getName = that.superior(getName); var me = man({name : Fogus}); that.getName = function() { me.getName() return "Mr. " + super_getName(); //=> Mr. Fogus }; return that;};
    51. 51. Functional Inheritance Pattern Dangers• Harder to minify• Larger memory footprint• Cannot update instances• Eliminates instanceof• Mucks with Function.prototype and Object.prototype in an unsafe way
    52. 52. Pseudo-classical Inheritance PatternPerson = function(name) { this._name = name;}; var me = new Person(Fogus);Person.prototype.getName = function() { me.getName() return this._name; //=> Fogus};Man = function(name) { Person.call(this, name);};inherits(Man, Person); var me = new Man(Fogus); me.getName()Man.prototype.getName = function() { //=> Mr. Fogus return "Mr. " + Man._super.getName.call(this);};
    53. 53. Pseudo-classical Inheritance Pattern• Harder Easier to minify• Larger Smaller memory footprint• Cannot Can update instances• Eliminates instanceof• Mucks with Clean Function.prototype and Object.prototype
    54. 54. Safe ExtensionString.prototype.cljs$core$first = ...Object.prototype.my$lib$first = ...
    55. 55. me._name//=> ‘Fogus’
    56. 56. Minification• Inlining• Renaming• Dead-code elimination
    57. 57. Inlining
    58. 58. Functional Inheritance Inliningvar person = function(spec) { var myName = me.getName(); var that = {}; var sig = signature({‘name’ : myName}); sig.toString(); that.getName = function() { //=> ‘Sent from teh Fogus iPhone’ return spec.name; }; return that;};
    59. 59. Functional Inheritance Inliningvar person = function(spec) { var myName = me.getName(); var that = {}; var sig = signature({‘name’ : myName}); sig.toString(); that.getName = function() { //=> ‘Sent from teh Fogus iPhone’ return spec.name; }; return that;}; ?
    60. 60. Functional Inheritance Inliningvar person = function(spec) { var myName = me.getName(); var that = {}; var sig = signature({‘name’ : myName}); sig.toString(); that.getName = function() { //=> ‘Sent from teh Fogus iPhone’ return spec.name; }; return that;}; var sig = signature({‘name’ : me.getName()}); sig.toString(); //=> ‘Sent from teh Fogus iPhone’
    61. 61. Inlining
    62. 62. Pseudo-classical InliningPerson = function(name) { this._name = name; var myName = me.getName();}; var sig = new Signature(myName); sig.toString();Person.prototype.getName = function() { //=> ‘Sent from teh Fogus iPhone’ return this._name;}; ?
    63. 63. Pseudo-classical InliningPerson = function(name) { this._name = name; var myName = me.getName();}; var sig = new Signature(myName); sig.toString();Person.prototype.getName = function() { //=> ‘Sent from teh Fogus iPhone’ return this._name;}; var sig = new Signature(me._name); sig.toString(); //=> ‘Sent from teh Fogus iPhone’
    64. 64. Renaming
    65. 65. Functional Inheritance Renaming var person = function(spec) { var that = {}; that.getName = function() { return spec.name; }; return that; }; var man = function(spec) { var that = person(spec); var super_getName = that.superior(‘getName’); that.getName = function() { return "Mr. " + super_getName(); }; return that; };
    66. 66. Functional Inheritance Renaming var person = function(spec) { var that = {}; that.getName = function() { return spec.name; }; return that; }; var man = function(spec) { var that = person(spec); var super_getName = that.superior(‘getName’); that.getName = function() { return "Mr. " + super_getName(); }; return that; };
    67. 67. Renaming
    68. 68. Pseudo-classical RenamingPerson = function(name) { this._name = name;};Person.prototype.getName = function() { return this._name;};Man = function(name) { Person.call(this, name);};inherits(Man, Person);Man.prototype.getName = function() { return "Mr. " + Man._super.getName.call(this);};
    69. 69. Pseudo-classical RenamingPerson = function(name) { this._name = name;};Person.prototype.o = function() { return this._name;};Man = function(name) { Person.call(this, name);};inherits(Man, Person);Man.prototype.getName = function() { return "Mr. " + Man._super.o.call(this);};
    70. 70. Dead Code
    71. 71. Dead-code Elimination Intro(let [a 1 b 2 a b] a);=> 2
    72. 72. Dead-code Elimination Intro (function (){(let [a 1 var a__847 = 1; b 2 var b__848 = 2; a b] var a__849 = b__848; a) return a__849;;=> 2 })();
    73. 73. Dead-code Elimination Intro (function (){(let [a 1 var a__847 = 1; b 2 var b__848 = 2; a b] var a__849 = b__848; a) return a__849;;=> 2 })(); ?
    74. 74. Dead-code Elimination Intro (function (){(let [a 1 var a__847 = 1; b 2 var b__848 = 2; a b] var a__849 = b__848; a) return a__849;;=> 2 })(); 2
    75. 75. Dead-code Elimination Intro (function (){(let [a 1 var a__847 = 1; b 2 var b__848 = 2; a b] var a__849 = b__848; a) return a__849;;=> 2 })();
    76. 76. Functional Inheritance Dead-code var person = function(spec) { var that = {}; var hasBeard = false; that.getName = function() { return spec.name; }; return that; }; var man = function(spec) { var that = person(spec); var super_getName = that.superior(‘getName’); that.getName = function() { return "Mr. " + super_getName(); }; return that; };
    77. 77. Functional Inheritance Dead-code var person = function(spec) { var that = {}; var hasBeard = false; that.getName = function() { return spec.name; }; return that; }; var man = function(spec) { var that = person(spec); All good var super_getName = that.superior(‘getName’); Right? that.getName = function() { return "Mr. " + super_getName(); }; return that; };
    78. 78. Functional Inheritance Dead-code var person = function(spec) { var that = {}; var hasBeard = false; that.getName = function() { Cursed return spec.name; }; return that; Closures! }; var man = function(spec) { var that = person(spec); var super_getName = that.superior(‘getName’); that.getName = function() { return "Mr. " + super_getName(); }; return that; };
    79. 79. Dead Code
    80. 80. Pseudo-classical Dead-codePerson = function(name) { this._name = name; this._hasBeard = false;};Person.prototype.getName = function() { return this._name;};Man = function(name) { Person.call(this, name);};inherits(Man, Person);Man.prototype.getName = function() { return "Mr. " + Man._super.getName.call(this);};
    81. 81. Pseudo-classical Dead-codePerson = function(name) { this._name = name; this._hasBeard = false;};Person.prototype.getName = function() { return this._name;};Man = function(name) { Person.call(this, name);};inherits(Man, Person);Man.prototype.getName = function() { return "Mr. " + Man._super.getName.call(this);};
    82. 82. Pseudo-classical Dead-codePerson = function(name) { this._name = name;}; kthxbaiPerson.prototype.getName = function() { return this._name;};Man = function(name) { Person.call(this, name);};inherits(Man, Person);Man.prototype.getName = function() { return "Mr. " + Man._super.getName.call(this);};
    83. 83. There’s more to life than this
    84. 84. Memory Footprint• Crockford • Closure per-method, per-type • Leaky (holds a reference to all variables)• Pseudo-classical • No closures needed
    85. 85. Live
    86. 86. Instance Updating• Problem • How to update every instance in the system with new behavior?
    87. 87. Functional Inheritance Updating var person = function(spec) { var that = {}; that.getName = function() { return spec.name; }; return that; }; var me = person({name : Fogus}); var you = person({name : Cersei});How can we add hasBeard to every instance now and in the future?
    88. 88. Functional Inheritance Updating var person = function(spec) { var that = {}; that.getName = function() { return spec.name; }; return that; }; var me = person({name : Fogus}); var you = person({name : Cersei});How can we add hasBeard to every instance now and in the future? One at a time... every single time
    89. 89. ClojureScript Cares.
    90. 90. ClojureScript Extending (defprotocol Catable (cat [this other])) (def sound1 "Meow") (def sound2 "Mao") (cat sound1 sound2) ; ASPLODE!How can we allow cat to work with every instance now and in the future?
    91. 91. ClojureScript Extending (extend-type string Catable (cat [this other] (str this other))) (cat sound1 sound2) ;=> “MeowMao” (cat sound1 "ZZZZZ") ;=> "MeowZZZZZ"Pseudo-classical underpinnings FTW
    92. 92. Pseudo-classical Updating Person = function(name) { this._name = name; }; Person.prototype.getName = function() { return this._name; }; var me = new Person(‘Fogus’); var you = new Person(‘Cercei’);How can we add hasBeard to every instance now and in the future?
    93. 93. Pseudo-classical Updating Person = function(name) { this._name = name; }; Person.prototype.getName = function() { return this._name; }; var me = new Person(‘Fogus’); var you = new Person(‘Cercei’); How can we add hasBeard to every instance now and in the future?Person.prototype.hasBeard = function() { return false };
    94. 94. apply
    95. 95. function
    96. 96. Var Args JavaScript ClojureScriptarguments & stuff
    97. 97. Var Args JavaScript ClojureScript arguments & stuffAn object that holds arguments a seq
    98. 98. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);}
    99. 99. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (add-first-two 1 2 3) ;=> 3
    100. 100. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (apply add-first-two [1 2 3])
    101. 101. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (apply add-first-two [1 2 3])
    102. 102. ClojureScript apply (defn apply [f arg-seq] (.apply f (to-array arg-seq)))
    103. 103. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (apply add-first-two [1 2 3]) ;=> 3
    104. 104. ClojureScript apply (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (apply add-first-two (iterate inc 1)) ;=> ?
    105. 105. ClojureScript apply ∞ (defn add-first-two [& args] (+ (first args) (second args)))function addFirstTwo() { var args = // that slice thing return cljs.first(args) + cljs.second(args);} (apply add-first-two (iterate inc 1)) ;=> ?
    106. 106. ClojureScript apply (defn apply [f arg-seq] (.apply f (to-array arg-seq)))
    107. 107. ClojureScript applyTo• A function stored on ClojureScript functions • Only if they have var args• Compiled to only deal with the args seq at the maximum fixed arity • This ensures that an infinite seq is not realized
    108. 108. ClojureScript apply (defn apply [f arg-seq] (if (.applyTo f) (if (<= bounded-count fixed-arity) (.apply f (to-array arg-seq)) (.applyTo f args)) (.apply f (to-array arg-seq)))
    109. 109. ClojureScript apply (defn apply [f arg-seq] (if (.applyTo f) (if (<= bounded-count fixed-arity) (.apply f (to-array arg-seq)) (.applyTo f args)) (.apply f (to-array arg-seq)))
    110. 110. ClojureScript apply (defn apply [f arg-seq] (if (.applyTo f) (if (<= bounded-count fixed-arity) (.apply f (to-array arg-seq)) (.applyTo f args)) (.apply f (to-array arg-seq)))
    111. 111. ClojureScript apply (defn apply [f arg-seq] (if (.applyTo f) (if (<= bounded-count fixed-arity) (.apply f (to-array arg-seq)) (.applyTo f args)) (.apply f (to-array arg-seq)))
    112. 112. CompilerAnatomy
    113. 113. Cl oju re D at a AS T
    114. 114. Analysis
    115. 115. Emission
    116. 116. C6 4 JA VA SC RIP T
    117. 117. Thank Youhttp://joyofclojure.com @fogus
    118. 118. Learn More• http://bit.ly/cljs-intro• http://boss-level.com/?p=102• http://blog.fogus.me/tag/clojurescript• http://github.com/clojure/clojurescript
    119. 119. Crockford Hates instanceof
    120. 120. Functional Inheritance instanceof var me = person({name : Fogus}); me instanceof person; //=> false
    121. 121. ClojureScript Loves instanceof
    122. 122. Pseudo-classicalinstanceof var me = new Person(Fogus); me instanceof Person; //=> true
    123. 123. ClojureScriptsatisfies? (defprotocol Catable (cat [this other])) (deftype Cons [H T] Catable (cat [_ new-tail] nil)) (satisfies? Catable (Cons. 1 2)) ;=> true
    124. 124. tread
    125. 125. Don’t Tread on Me Function.prototype.method = function(name, f) { this.prototype[name] = f; return this; }; Object.method(superior, function(name) { var that = function; var method = that[name]; return function() { return method.apply(that, arguments); }; });
    126. 126. ClojureScript Gently CaressesObject & Function as One Might Caress the finest Fabergé Egg
    127. 127. Look with your eyes,not with your hands var inherits = function(child, parent) { function tmp() {}; tmp.prototype = parent.prototype; child._super = parent.prototype; child.prototype = new tmp(); child.prototype.constructor = child; };
    128. 128. Var Args JavaScript ClojureScriptfunction stuffToArray() { (defn stuff->seq // create an array of stuff [& stuff]} stuff)stuffToArray(1,2,3,4); (stuff->seq 1 2 3 4)//=> [1,2,3,4] ;=> (1 2 3 4)
    129. 129. Var Args JavaScript ClojureScriptfunction stuffToArray() { (defn stuff->seq // create an array of stuff [& stuff]} stuff)stuffToArray(1,2,3,4); (stuff->seq 1 2 3 4)//=> [1,2,3,4] ;=> (1 2 3 4)
    130. 130. Var Args JavaScript ClojureScriptfunction stuffToArray() { (defn stuff->seq return Array.prototype.slice.call(arguments); [& stuff]} stuff)stuffToArray(1,2,3,4); (stuff->seq 1 2 3 4)//=> [1,2,3,4] ;=> (1 2 3 4)
    131. 131. Compiler Macros• Operate in the compiler only • Analysis phase• Written in Clojure• Allows shadowing of fns • Operates according to a fix point

    ×