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

Functional Programming in JavaScript

Functional Programming in JavaScript

presentation given for the Las Vegas Functional Programmers Group

Jed Schneider

March 24, 2016
Tweet

More Decks by Jed Schneider

Other Decks in Programming

Transcript

  1. What are we talking about? • solutions that do not

    follow the semantics of Javascript • solutions that follow JavaScript semantics
  2. JavaScript • Babel (ES2016, …) - all code in this

    talk is in ES2016 • collections of libraries, frameworks, etc written in ‘vanilla JS’* to support FP ideas.
  3. Is JS Functional? • all we really have are first

    class functions (the rest is up to the dev team to enforce) • immutability, referential transparency, purity, types (esp ADTs), pattern matching, TCO* • open object model, dynamic context, duck typing, non-strict arity, metaprogramming • despite all that, there are some really exciting things happening.
  4. We can do FP [1,2,3].map(x => x) //-> [1,2,3] const

    isEven = x => x % 2 === 0 [1,2,3].filter(isEven) // [2] const fn = ([head, …tail])=> [...tail, head] fn([1,2,3]) //-> [2,3,1] const update = (obj, props)=> Object.assign({}, obj, props) update({foo: ‘foo’, bar: ‘bar’}, {bar: ‘foo’}) // -> {foo: ‘foo’, bar: ‘foo’}
  5. We can do FP // the old way // addSome

    :: Int -> Int -> Int var addSome = function(x) { return function(y) { return x + y; } } // ES2016 (the new way) // addSome :: Int -> Int -> Int const addSome = x => y => x + y const addTwo = addSome(2) addTwo(2) // -> 4 FP newbies, remember this pattern!
  6. first there was Jeremy Ashkenas • coffeescript • list comprehensions,

    spread operator, existential (Maybe monadic*) expression, everything is an expression, shorthand function notations - compiled white space sensitive, a ‘radical’ departure. • underscore.js • utility toolbelt for (mostly data enumeration) akin to the Enumerable module in Ruby. Also, partial application, compose, combinators.
  7. lodash examples const fn = (a,b)=> a + b _.curry(fn)(1)(2)

    //-> 3 const fn1 = _.partial(fn, 1) fn1(2) // -> 3 _.map([1,2,3], fn1) //-> [2, 3, 4] _.map([1,2,3], _.identity) //-> [1,2,3] _.curry(_.add)(1)(2) //-> 3
  8. bacon.js example var up = $('#up').asEventStream('click'); var down = $('#down').asEventStream('click');

    var counter = up.map(1).merge(down.map(-1)) .scan(0, function(x,y) { return x + y }); counter.assign($('#counter'), 'text'); https://baconjs.github.io/
  9. hey underscore you’re doing it wrong • Brian Lonsdorf •

    goo.gl/vTfGUW • addresses limitations to the argument structure and partial application / currying (mainly)
  10. example from huydiw const firstTwoLetters = (words)=> { return _.map(words,

    word => _.first(word, 2)) } firstTwoLetters([‘jim’, ‘kate’]) //-> [‘ji’, ‘ka’] var firstTwoLetters = function(words) { return _.map(words, function(word) { return _.first(word, 2); }); }
  11. example from huydiw // original implementation word => _.first(word, 2)

    _.map(words, fn) // better arg structure for _.first, _.map fn = word => _.first(2, word) _.map(fn, words) // partially applied fn = _.map(_.first(2)) fn(words) // finally, no function wrapper needed const firstTwoLetters = _.map(_.first(2)) (we need something to do this)
  12. Ramda.js // ramda doesn’t have a _.first fn so make

    one // could have also used // String.prototype.slice.call(str, idx, idx) const sliceX = n => str => str.slice(0,n) const first = (n, str)=> sliceX(n)(str) const firstTwo = str => R.partial(first, [2]) const getFirstLetters = R.map(firstTwo) getFirstLetters([‘jim’, ‘kate’]) // -> [‘ji’, ‘ka’]
  13. ramda.js • http://ramdajs.com/ • also has lenses, functors like ‘either’,

    combinators like ‘identity’, almost ‘do’ notation through things like ‘pipeP’ (piped promises), transducers, and many object property functions. // remember lodash? const addOne = _.partial(_.add, 1) _.map([1,2,3], addOne) //-> [2,3,4] // ramda const addOne = R.add(1) R.map(addOne, [1,2,3])//-> [2,3,4]
  14. leftpad module.exports = leftpad; function leftpad (str, len, ch) {

    str = String(str); var i = -1; if (!ch && ch !== 0) ch = ' '; len = len - str.length; while (++i < len) { str = ch + str; } return str; } http://goo.gl/IH32oC
  15. leftpad in Ramda const {curryN, times} = R; // times

    :: (a -> b) -> Int -> [ b ] // leftpad :: Int -> Char -> String -> String const leftpad = curryN(3, (len, char, str)=> { return "".concat(...times(_ => char, len), [str])) } const pad6 = leftpad(6) pad6('y', 'bar') // -> "yyyyyybar" const pad7 = leftpad(7, ' ') pad7('foo') // -> " foo"
  16. sweet.js • http://sweetjs.org/ • hygienic macros for javascript // https://github.com/mozilla/sweet.js/wiki/Example-

    macros arg |> foo[0].bar(42) |> baz("hello", "there") |> quux.foo().bar() |> new Foo() // Expands to: // new Foo(quux.foo().bar(baz('hello', 'there', foo[0].bar(42, arg))));
  17. React • https://facebook.github.io/react/ • Not specifically functional, but one way

    data flow makes it a ‘perfect target’ for immutability and other functional ideas. • Immutability is not just an FP idea, but it is typical in most FP languages.
  18. Redux • http://redux.js.org/ • A data store ‘state container’ for

    javascript apps. • Often used with React • Takes cues from Elm (remember that from slide 2) • designed around returning a new state that is the aggregate of reduction functions
  19. immutable.js • https://facebook.github.io/immutable-js/ • persistent data structures for javascript •

    can be used with or without react/redux • written in TypeScript (remember that from slide 2) • uses structural sharing via tries just like Scala and Clojure
  20. Some more resources • promise composition, lenses, ramda, other ramblings

    • https://medium.com/@dtipson • State of the art JavaScript 2016 • https://goo.gl/0ePp12 • functional programming for javascript people • https://goo.gl/ATjZET • hardcore* functional programming in javascript • https://frontendmasters.com/courses/functional-javascript/ • https://egghead.io/series/getting-started-with-redux