This document discusses using protocols and lazy sequences in Node. It introduces JavaScript concepts like lists and collections. It describes how lazy sequences only evaluate data when needed. Protocols provide an interface for checking sequence types and implementing methods like first, rest, and cons. Async sequences in Node can be represented with streams and promises to handle asynchronous code. Overall protocols allow mixing synchronous and asynchronous sequences and could enable new abstractions.
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. 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?
8. Using Lists
map = 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. 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. Lazy Sequences
● Only really care about the data in
the list when we call first()
● rest() can be lazily evaluated
11. Using Lazy Seqences
map = function(coll, fn) {
return lazySeq(function() {
var head = coll.first(list), tail = coll.rest(list);
return lazySeq.cons(map(tail, fn), fn(head));
});
};
12. The Interface Problem
● How do we check for the sequence
interface?
● How do we apply the interface
implementation if it's missing?
● What do we do if some object already
has a first, rest or cons which are
different from the ones we expect?
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. Observations
● Lazy Sequences are like promises
● Syncronous values can be
reresented as promises that
resolve immediately
● With protocols we can conjoin
sequences.
24. Potential Uses
● Higher level abstractions
● Mix and match sync & async
● Write once run anywhere
● Leverage new technologies e.g.
WebCL
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.