Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Monadify evented code

Monadify evented code

Monadify evented code OR: how to put synchronicity back in asynchronous code.
Here i describe how to use CoffeeScript in order to port the "synchronous" programming style to the evented, turn based Model used by node.js

Simon DotOrg

May 02, 2014
Tweet

More Decks by Simon DotOrg

Other Decks in Programming

Transcript

  1. In node.js code looks sometimes like this readRequest(conn,function(req){ readTemplateFile(fn,function(data){ parseTemplateFile(data,function(tepl){

    queryDataBase(„…..",function(resultset){ fetchNextResult(resultset,function(row){ sendResponse(conn,...); }); }); }); }); });
  2. Now lets look at Haskell (>>=) :: Maybe a ->

    (a -> Maybe b) -> Maybe b Nothing >>= _ = Nothing (Just x) >>= f = f x return :: a -> Maybe a return x = Just x add :: Maybe Int -> Maybe Int -> Maybe Int add mx my = mx >>= (\x -> my >>= (\y -> return (x + y)))
  3. Now, Haskell with syntactic sugar (>>=) :: Maybe a ->

    (a -> Maybe b) -> Maybe b Nothing >>= _ = Nothing (Just x) >>= f = f x return :: a -> Maybe a return x = Just x add :: Maybe Int -> Maybe Int -> Maybe Int add mx my = do x <- mx y <- my return (x + y)
  4. Lessons, that we lerned • Monads are some kind of

    masked values – type<a> M<a> • The >>= operator extracts a from M<a> – operator<a,b> M<a> >>= (a -> M<b>) -> M<b> • The >>= operator may delay the execution of the function • And that‘s it.
  5. Applying what we lerned back to node.js • First we

    need the foundation for this • Javascript has – No operator overloading – No >>= operator – Is dynamically typed • Our requirements are: – Something thats to use like a monad – Some replacement for the >>= operator
  6. Defining JS equivalents Haskell 1. a >>= func 2. Monad

    value 3. y <- f(x) Javascript 1. a(func) 2. function( func ){…} 3. f(x)(function(y){…})
  7. So we need to redefine our api a bit Whereever

    we get: apiFunction(param1,param2,callback) Well redefine it as: apiFunction(param1,param2)(callback)
  8. Then the code we get at first looks like this

    readRequest(conn)(function(req){ readTemplateFile(fn)(function(data){ parseTemplateFile(data)(function(tepl){ queryDataBase("S…")(function(resultset){ fetchNextResult(resultset)(function(row){ sendResponse(conn,...); }); }); }); }); });
  9. In CoffeeScript our code would look like this readRequest(conn) (req)->

    readTemplateFile(fn) (data)-> parseTemplateFile(data) (tepl)-> queryDataBase("S...") (resultset)-> fetchNextResult(resultset) (row)-> sendResponse(conn,...)
  10. And with even more syntactic sugar readRequest(conn) (req)->\ readTemplateFile(fn) (data)->\

    parseTemplateFile(data) (tepl)->\ queryDataBase("S...") (resultset)->\ fetchNextResult(resultset) (row)->\ sendResponse(conn,...)
  11. Thats about loops ;-) repeat((recur,end,whil)-> s.readLine(10) (data)->\ print('XML> '+data) ->\

    w.write(data) ->\ whil(data.length) ) ->\ more… # and you can also use # tail recursion