To Infinity & Beyond!   Protocols & Lazy Sequences in Node                  Part 1Bahul Neel Upadhyaya (@bahulneel)BraveNe...
JavaScript●   Imperative●   Dynamic●   OOP    –   Prototypes    –   Constructors●   Functional    –   First Class Function...
List Comprehension●   Loops    –   for (init; while; step)●   Stack & Queue    –   push/pop/shift/unshift●   Iterators    ...
Collections    How do I know if collection x works with my function?●   Extends Array?●   Implements Array?●   Impements s...
Collections
LispJohn McCarthy                 Structure and                       Interpretation of Computer                          ...
Listsfirst   rest   first    rest   first   rest
Using Listsmap = function(list, fn) {                            reduce = function(list, fn) {         var head = first(li...
Sequences●   collection.first()    –   Returns the first item●   collection.rest()    –   Returns a sequence of the the ta...
Lazy Sequences●   Only really care about the data in    the list when we call first()●   rest() can be lazily evaluated
Using Lazy Seqencesmap = function(coll, fn) {     return lazySeq(function() {       var head = coll.first(list), tail = co...
The Interface Problem●   How do we check for the sequence    interface?●   How do we apply the interface    implementation...
Monkey PatchingMyColl.protoype.first = function(coll) {}MyColl.protoype.rest = function(coll) {}MyColl.protoype.cons = fun...
The Adapter PatternmySeq =mySeqAdapter(myColl);head = mySeq.first();tail = mySeq.rest();newSeq = myColl.cons(item);
Switchingfunction first(coll) {    if (coll === null)       return null;    else if (isArray(coll))       return coll[0]; ...
Protocolsvar Sequence = protocol.define(     Sequence,     [ first, [ coll ] ],     [ rest, [ coll ] ],     [ cons, [ coll...
Protocols vs. Interfaces Protocol          Interface      Object          Interface         Calls                         ...
Using Protocolsvar first = Sequence.first, rest = Sequence.rest,       cons = Sequence.cons;map = function(coll, fn) {    ...
What about Node?●   Sequences are synchronous●   Node is aynchronous             Pull vs. Push
Async in Node      Streams          Promises●   Evented      ●   Single shot●   Callbacks    ●   Callbacks●   Buffered    ...
Async Mapmap = function(stream, fn) {     var result = stream.Stream();     result.writable = true;     stream.on(“data”, ...
Async Sequences●   first(stream)    –   A promise to the first item in the first buffer in the        stream.●   rest(stre...
Observations●   Lazy Sequences are like promises●   Syncronous values can be    reresented as promises that    resolve imm...
Potential Uses●   Higher level abstractions●   Mix and match sync & async●   Write once run anywhere●   Leverage new techn...
Get cosy●   cosy.lang    –   Protocols    –   Lazy Sequences    –   Tail Recursionhttp://bnt.getcosy.org (v0)http://getcos...
To be continued...Part 2●   Async Sequences●   Tail Recursion●   Live Demos
Questions
Upcoming SlideShare
Loading in …5
×

To Infinity & Beyond: Protocols & sequences in Node - Part 1

556 views

Published on

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

  • Be the first to like this

No Downloads
Views
Total views
556
On SlideShare
0
From Embeds
0
Number of Embeds
187
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Designed by Brendan Eich in 1994 for Mozilla. Originally called Mocha it was based on Self and Scheme Brings in features from both languages Allows the developer to adopt any style or any combination of those styles.
  • One of the things we spend most of our time doing is manipulating lists of things (numbers, objects, etc). Currently, in the javascript world, we have a number of ways available to us. Classic for loop, push/pop, forEach, map, etc. Javascript has no standard way to deal with this.
  • Collections add a extra layer of complexity. Do they extend the Array prototype? If not do they implement the common array functions and/or patterns? If so which ones? Do I need to add these functions myself? When do I add them? Will they collide with someone elses functions? => Complexity & bloat
  • Is there a better way? Can we find a common set of methods that will let us write a universal function that should work with anyone's collection? I think there is and all we need to do is borrow a few ideas from the Lisp guys.
  • Designed by John McCarthy in 1958 Made popular in AI circles by scheme written by Guy Lewis Steele Jr. and Gerald Jay Sussman. Sussman went on to write Structure & Interpetation of Computer Programs with Harold Abelson (must read!) The name LISP was derrived from LISt Processing and had a very simple but powerful way to look at lists
  • In lisp a list is linked list that has a head and a tail. Where calling first on a list returns the data at the head of the list and calling rest returns a list of all the elements in the tail. It turns out that this representation gets us pretty far if we want a common way to deal with lists.
  • In Rich Hickey's Clojure dialect of LISP he added the concept of sequences which is any collection implementing the first, rest and cons methods I've shown it on the slide in JS form. Now that we depend on an interface we can now also make an interresting observation.
  • Until we actually ask for an element of the sequence we're not obliged to evaluate it. That means so long as we're able to evaluate the head at will we never need to bother with the rest until we need it. This means we can save on some unncecessary computation and also have potentially infinite sequences.
  • Is there some way to do this automatically? Yes: protocols
  • Think of the boxes as source files Meaning the responsibility is decoulpled.
  • To Infinity & Beyond: Protocols & sequences in Node - Part 1

    1. 1. To Infinity & Beyond! Protocols & Lazy Sequences in Node Part 1Bahul Neel Upadhyaya (@bahulneel)BraveNewTalenthttp://github.com/bahulneelhttp://www.bravenewtalent.com
    2. 2. JavaScript● Imperative● Dynamic● OOP – Prototypes – Constructors● Functional – First Class Functions Brendan Eich – Closures
    3. 3. List Comprehension● Loops – for (init; while; step)● Stack & Queue – push/pop/shift/unshift● Iterators – forEach, etc● Map/Reduce No standard way of doing these
    4. 4. Collections How do I know if collection x works with my function?● Extends Array?● Implements Array?● Impements some iterator?● Do I need to monkey patch?
    5. 5. Collections
    6. 6. LispJohn McCarthy Structure and Interpretation of Computer Programs
    7. 7. Listsfirst rest first rest first rest
    8. 8. Using Listsmap = function(list, fn) { reduce = function(list, fn) { var head = first(list), tail = rest(list); var head = first(list), tail = rest(list); if (!head) return []; if (!head) return null; result = map(tail, fn); result = reduce(tail, fn); return [fn(head)].append(result); return fn(head, result);}; };filter = function(list, fn) { forEach = function(list, fn) { var head = first(list), tail = rest(list); var head = first(list), tail = rest(list); if (!head) return []; if (!head) return null; result = map(tail, fn); fn(head); if (fn(head)) return [head].append(result); forEach(tail, fn); else return result; };};
    9. 9. Sequences● collection.first() – Returns the first item● collection.rest() – Returns a sequence of the the tail of the collection● collection.cons(item) – Returns a new collection with item at the head and the collection at the tail
    10. 10. Lazy Sequences● Only really care about the data in the list when we call first()● rest() can be lazily evaluated
    11. 11. Using Lazy Seqencesmap = function(coll, fn) { return lazySeq(function() { var head = coll.first(list), tail = coll.rest(list); return lazySeq.cons(map(tail, fn), fn(head)); });};
    12. 12. The Interface Problem● How do we check for the sequence interface?● How do we apply the interface implementation if its missing?● What do we do if some object already has a first, rest or cons which are different from the ones we expect?
    13. 13. Monkey PatchingMyColl.protoype.first = function(coll) {}MyColl.protoype.rest = function(coll) {}MyColl.protoype.cons = function(coll, item) {}
    14. 14. The Adapter PatternmySeq =mySeqAdapter(myColl);head = mySeq.first();tail = mySeq.rest();newSeq = myColl.cons(item);
    15. 15. Switchingfunction first(coll) { if (coll === null) return null; else if (isArray(coll)) return coll[0]; else if (function === typeof coll.first) return coll.first(); else throw new Error(not a sequence);}
    16. 16. Protocolsvar Sequence = protocol.define( Sequence, [ first, [ coll ] ], [ rest, [ coll ] ], [ cons, [ coll ] ]);protocol.extend( Sequence MyCollection, [ first, function (coll) { return coll.head(); } ], [ rest, function (coll) { return coll.tail(); } ], [ cons, function (coll, item) { return coll.cons(item); });
    17. 17. Protocols vs. Interfaces Protocol Interface Object Interface Calls Implements Implementation Calls Object Protocol Calls Calls someFunction someFunction
    18. 18. Using Protocolsvar first = Sequence.first, rest = Sequence.rest, cons = Sequence.cons;map = function(coll, fn) { return lazySeq(function() { var head = first(coll, list), tail = rest(coll, list); return cons(map(tail, fn), fn(head)); });};
    19. 19. What about Node?● Sequences are synchronous● Node is aynchronous Pull vs. Push
    20. 20. Async in Node Streams Promises● Evented ● Single shot● Callbacks ● Callbacks● Buffered ● Unbuffered● Composable ● Composable
    21. 21. Async Mapmap = function(stream, fn) { var result = stream.Stream(); result.writable = true; stream.on(“data”, function(data) { result.write(fn(data)); }); return result;};
    22. 22. Async Sequences● first(stream) – A promise to the first item in the first buffer in the stream.● rest(stream) – A sequence of the rest of the items in the first buffer with the original stream at the tail.● cons(stream, item) – A sequence with a promise to the item at the head and the stream as the tail.
    23. 23. Observations● Lazy Sequences are like promises● Syncronous values can be reresented as promises that resolve immediately● With protocols we can conjoin sequences.
    24. 24. Potential Uses● Higher level abstractions● Mix and match sync & async● Write once run anywhere● Leverage new technologies e.g. WebCL
    25. 25. Get cosy● cosy.lang – Protocols – Lazy Sequences – Tail Recursionhttp://bnt.getcosy.org (v0)http://getcosy.org (v1+)
    26. 26. To be continued...Part 2● Async Sequences● Tail Recursion● Live Demos
    27. 27. Questions

    ×