Joshua T Kalis he/him/his

Functional Javascript

Wat?!


Why Functional?


Write Better Code

Greater Confidence

Testable code promotes reliable re-writing and can be objectively ensured to have fewer bugs. Who wants to fix code that was thought to already have been fixed?

Increased Productivity

Safe, stable code can be relied on and you can move onto other, more important or interesting, projects. Composing preexisting code will reduce new code and require fewer tests.

Easier Comprehension

Shorter, more focused, code is easier to grasp for yourself and other developers. Fewer lines of code means fewer chances for things to go wrong.


SO!

What does it all mean?


Moar Laziness!


Hooked?

Good, now some boring stuff.


Agenda

  1. Introduction
    • Why Javascript?
    • Programming Paradigms
  2. Functional Programming Concepts
    • Functional Javascript snippets
  3. Code Refactoring Examples
  4. Questions
  5. Teach myself - basically I don't care about any of you

Me


Brief experience time-line

  1. Started as a Graphic Designer, NOT a programmer
  2. Moved to Web Design through images first then CSS and HTML
  3. Picked up ASP Classic
  4. Forced to learn Javascript (HATED all of it!)
  5. Learned a little of these: PHP4, C# .NET 2.0, Java
  6. Began to LOVE Javascript

Self-taught mostly.


Hi, my name is Josh.

I <3 Javascript. I might be biased.


Javascript has a LOT of BAD parts!


What is there to love about Javascript?


Main Programming Paradigms (source)


Imperative

var message = 'Hello ';
var promptMessage = 'What is your name?';
var name = prompt(promptMessage);
alert(message + name);
  1. Set some variables.
  2. Ask the user for their name and store that to a variable.
  3. Finally, greet them with a message including their name.

Do we see the 'Procedure' here?

"... describes computation in terms of statements that change a program state." ~~ wikipedia


Object Oriented

function Greeting () {
    this.name = prompt(Greeting.promptMessage);
}

Greeting.promptMessage = 'What is your name?'; // static(-like) property
Greeting.prototype.say = function (message) {  // inherited function
    alert(message + this.name);
}

var personalGreeting = new Greeting();

personalGreeting.say('Hello ');

Here we gain some re-usability, albeit with some verbosity.

  1. Define a 'class'; see the quotes, because Javascript doesn't truly have classes.
    • Added a 'static' property; that is publicly available
    • Added a type-based method; prototypically inherited by all instances
  2. Create an instance of the 'class' with an instance variable of the user's name.
  3. Greet the user with a message including their name.

I write non-functional Javascript

Just to set you at ease, I am not a functional Javascript doyen writing everything in a functional manner. Actually, from time to time, I even write Javascript that doesn't even function.

function myAwesomeness (arg) {
  // perform some intense computation on arg
  // fully unit tested
  // purely functional
  // return some computed value
}

// ...

var myVar = myAwesomeness(); // derp derp

One Big Difference

Imperative and Object Oriented

Focus is on 'how' to accomplish the desired outcome.

Functional

Focus is on 'what' to do to accomplish the desired outcome.


Fair Warning

Functional Programming might infect your brain and change the way that you think about problems. You might find yourself re-evaluating old code and saying something similar to:

"The small experience I've had with #Haskell is already changing the way I write #JavaScript, mostly regarding avoiding side effects." ~~ @tlhunter


What is Functional?

"In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as elaborations on the lambda calculus." ~~ wikipedia


That's Boring!

And what...?


What does functional mean?

Here are the topics I found to be most talked about within the FP research that I performed for this talk.


Impurity

Relying on side effects leads to problems and brain-ache.

var sum = 0;

function addToSum (a) {
  sum += a;
  return sum;
}

addToSum(1); // returns 1
addToSum(2); // returns 3
sum = 0;
addToSum(3); // returns 3 -> WTF!

This code is reliant on no other programmers changing the value of sum (intentionally or otherwise); it is also not testable over the life of execution because of that.


Purity

function sum (a, b) {
  return a + b;
}

// ...

sum(1, 2); // returns 3, every time.

This is referentially transparent, meaning it can be logically reasoned about and the input dictates the output. Testing this will be straight-forward and reliable.


Functions as values

A function is a 'value' that can be assigned to an 'identifier'. This declaration:

function add (a, b) {
  return a + b;
}

... is very similar to this expression:

var add = function (a, b) {
  return a + b;
}

The only difference being when they are initialized in the Javascript interpreter. The end result is the same; a function identified as 'add'.

"Function Expressions and Functional Programming are inseparable." ~~ JavaScript JavaScript


Higher Order Functions

Examples: Array mutators, Event Handlers, etc.

Functions as arguments
[1, 2, 3, 4, 5, 6]
  .map(function (num) {
    return num * 3.14159;
  });

Higher Order Functions (cont.)

Examples: bind, 'factories', etc.

Functions as returned values

// add factory
function makeAdder (baseValue) {
  return function (x) {
    return baseValue + x;
  };
}

var add5 = makeAdder(5);

add5(10);   // returns 15
add5(1000); // returns 1005
add5(-4);   // returns 1

or...

function add (a, b) {
  return a + b;
}

var add5 = add.bind(null, 5); // partial function application 'topic coming soon'

IIFE - Immediately Invoked Function Expression

And now for a little (Algebraic) Substitution. The two equations below are equal.

var add = function (a, b) {return a + b;};

add(1, 2); // returns 3 every time

// Baby step, remember from math class, parens are just grouping
(add)(1, 2); // returns 3 every time

// Here is the IIFE
(function (a, b) {return a + b;})(1, 2); // returns 3 every time

Closure (lexical scoping)

Objects retain access to the context (scope) in which they were created.

var outterObj = (function () {
  var hidden = 'I have a secret.';

  // return this object to outterObj
  // privileged methods inside have access to 'hidden' through closure
  return {
    get: function () {
      return hidden;
    }
    , set: function (newValue) {
      hidden = newValue;
    }
  };
}());

outterObj.get();  // returns 'I have a secret.'
outterObj.set('Javascript is awesome!');
outterObj.get();  // returns 'Javascript is awesome!'
outterObj.hidden; // undefined

Scope Chain

Let's take a little side step for a second. Behold the ASCII diagram.

program execution drills down through scopes building a scope chain
          ↓
+-------------------+
|    Global Scope   | <-- default location for variables
|-------------------|
| Namespace Context | <-- single global namespace object
|-------------------|
|    IIFE Context   | <-- variables instantiated with 'var' inside
|-------------------|
|        ...        |
|-------------------|
|  Binding Context  | <-- functions can have a binding context
|-------------------|
| Execution Context | <-- argument values and closure variables
+-------------------+
          ↑
variable resolution looks up the scope chain
finding the reference or hitting global and returning undefined

Currying

"...transforming a function that takes n multiple arguments [into] a chain of functions, each with a single argument..." ~~ wikipedia

This might take some explanation to fully grasp; it did for me anyway.

function sumOfSix (a, b, c, d, e, f) {
  return a + b + c + d + e + f;
}

sumOfSix(1, 2, 3); // some argument values will be undefined

                   // curry is a fictitious function here
var sumOfSixCurried = curry(sumOfSix);
sumOfSixCurried(1);       // returns a new function expecting one argument
sumOfSixCurried(1)(2);    // returns a new function expecting one argument
sumOfSixCurried(1)(2)(3); // returns a new function expecting one argument
sumOfSixCurried(1)(2)(3)(4)(5)(6); // returns 21

Partial Application

Reducing the number of needed arguments by supplying values ahead of time.

function add (a, b) {
  return a + b;
}

var add5 = add.bind(null, 5);

add5(10); // returns 15
add5(-4); // returns 1

The bind method on the Function prototype allows us to do two things: explicitly set the context a function will execute with - value of 'this' inside the function - and supply arguments that will be available when the function is called.

Partial Application in JavaScript by Ben Alman

// !WARNING! unsafe for actual use
function partial (fn) {
  var args = [].slice.call(arguments, 1);     // get all arguments after the first
  return function () {
    fn.apply(null, args.concat(arguments)); // add args to partially applied args
  }
}

Composition

A new function that, when called, will pass the output of one function call as the input of the next and so on through all functions in the composition.

function fnA (_) { return _ + 2; }
function fnB (_) { return _ * 3; }
function fnC (_) { return _ - 5; }

var resultA = fnA(7);           // 9
var resultB = fnB(resultA);     // 27
var resultC = fnC(resultB);     // 22

// or

var result = fnC(fnB(fnA(7)));  // 22

with composition:

var compositionABC = compose(fnA, fnB, fnC);
var result = compositionABC(7);             // 22

// ...

var map = [13, 17, 23].map(compositionABC); // [40, 52, 70]

Composition reduces the number of times the list is iterated over from once per function in the composition to just once. Benefits: reusable, passable, composable, testable, scalable etc.


Lazy evaluation

Known as Generators, Sequences, or Streams (StreamJS), these constructs only return values on-demand. Collections of infinite length are actually workable without enormous processing power or infinite system memory.

// native Javascript array (not lazy)
var jsArray = [1,2,3,4,5,6,7,8,9];

jsArray.length;  // returns 9

Lazy evaluated structures will work quite a bit differently.

// using Stream.js library
var simple = Stream.range(); // create a stream of natural numbers [1,2,3...&infin;]

simple.length(); // returns... umm, infinitely loops as it attempts to find the end

simple.take(10).length(); // returns 10

Checkout Stream and do some cool things. I would love to see it!


Continuations

Continuations are not possible in Javascript. http://idea-log.blogspot.com/

Think of the old "goto" statements of yore but add in the fact that state of computation/execution is kept.

"[a reification of] an instance of a computational process at a given point in the process's execution" ~~ http://eriwen.com/

Javascript does not support Continuations natively; however, the Rhino environment does provide them as first-class objects.


Continuation-Passing Style (CPS)

Commonly used as callbacks in Javascript land.

doAJAX(
    'http://url.to.api'
  , JSON.stringify({name: 'Joshua'})
  , function succesHandler (data) {/*do cool stuff*/}
  , function failHandler  (error) {/*do cool stuff*/});

Possible stack overflow problems for deeply nested calls due to no tail optimization.

"No procedure is allowed to return to its caller ever..." ~~ By example: Continuation-passing style in JavaScript


Functional Elsewhere?

We can gain some of the benefits that Functional offers us by just working in that way.

"Programming in a functional style can also be accomplished in languages that aren't specifically designed for functional programming." ~~ wikipedia


Example Time!


#FunctionalJS

Go, now, and be functional


Further Learning


Resources

  1. Functional Programming - Wikipedia
  2. Functional Programming For The Rest of Us
  3. Pure, functional JavaScript
  4. Stream.js
  5. Functional Programming - igstan.ro
  6. Function Declarations vs. Function Expressions
  7. By example: Continuation-passing style in JavaScript
  8. Continuation-Passing Style
  9. lz
  10. http://idea-log.blogspot.com/
  11. Overview of the four main programming paradigms

Joshua T Kalis

August 2012