Skip to content

Latest commit

 

History

History
272 lines (230 loc) · 7.62 KB

File metadata and controls

272 lines (230 loc) · 7.62 KB

Practical Functional Programming

  1. What I Plan to Cover:
    • Briefly: Higher Order Functions, Chaining, Pipelines
    • Not-So-Briefly: Closures, Partial Application, Currying, Immutable Data
  2. What I Do Not Plan to Cover:
    • Redux
    • Recursion
    • Formal definitions of functional concepts

Familiar Functional Concepts:

  1. Functions as Building Blocks
    • Functions that are simple blocks for building larger blocks (functions), that do not mutate their parameters, are easy to test.
  2. Higher Order Functions
    • functions that take functions as arguments
    • see map, filter, reduce
  3. Lambda functions
    • nameless functions to give higher order functions

Chaining

  • using functions as building blocks, we create 'chains' of methods:
  • Example 1
return someData.json().cleanup(...).filter(...).map(...).doSomething().finalizeTheData();
  • Example 2
Promise.resolve(someData).then(...).then(...).catch(...);

Pipelines

renderATitle(turnSentenceIntoTitle(readIn(someData)));

Closures

  • Bind data or methods to a function only to use them later
function divideBy(d) {
  return function(n) {
    return n / d;
  };
}
const divideBy10 = divideBy(10);
const answer = divideBy10(20);
console.log(answer); // 2
  • In this example, we "bind" 10 to d when we create the function divideBy10. We can say 10 is "closed" to divideBy10.

React and Closures

  • what React components may look like without React

Stateless Functional Component:

const MyFunctionalComponent = (props = { stuff: '' }) => {
  return function() { // render
    const { stuff } = props;
    return `This is printing out props: ${stuff}`;
  };
};
const comp = MyFunctionalComponent({ stuff: 'yeah!' });
console.log(comp()); // This is printing out props: yeah!

Stateless Class Component:

function MyClassComponent(props = { stuff: '' }) {
  // Constructor :
  this.props = props;
  // End Constructor

  // render
  return function() {
    const { stuff } = this.props;
    return `This is printing out props: ${stuff}`;
  };
}

const comp = MyClassComponent({ stuff: 'yeah!' });
console.log(comp()); // This is printing out props: yeah!

Stateful Class Component

function MyStatefulClassComponent(props = { stuff: '' }) {
  // Constructor :
  this.props = props;
  this.state = { count: 0 };
  // End Constructor

  const increment = () => {
    this.state.count++;
  };

  const decrement = () => {
    this.state.count--;
  };

  const render = () => {
    const { stuff } = this.props;
    const { count } = this.state;
    return `My Props: ${stuff}, My State: ${this.state.count} `;
  };
  // Render method
  return {
    render,
    increment,
    decrement
  };
}

const comp = /*new*/ MyStatefulClassComponent({ stuff: 'yeah!' });
console.log(comp.render()); // My Props: yeah!, My State: 0

comp.increment();
console.log(comp.render()); // My Props: yeah!, My State: 1

comp.decrement();
console.log(comp.render()); // My Props: yeah!, My State: 0

Partial Application (PA)

  • You apply some of the required parameters of a function and return a function that takes the rest of the parameters.

Not PA

function turnArrayInto(func = () => {},list = []) {
        return list.map(func);
}

const apples = ['golden delicious','red','fuji'];
const orangeFunc = item => 'red naval';
const oranges = turnArrayInto(orangeFunc,apples);
console.log('Oranges',oranges); // ['red naval','red naval','red naval']

With PA

function turnArrayInto(func = () => {},list = []) {
        return list.map(func);
}

function partialTurnArrayInto(func) {
        return function(list) {
                return turnArrayInto(func,list);
        }
}
const apples = ['golden delicious','red','fuji'];
const orangeFunc = item => 'red naval';
const turnIntoOranges = partialTurnArrayInto(orangeFunc);
const oranges = turnIntoOranges(apples);
console.log('Oranges',oranges); // ['red naval','red naval','red naval']

PA In React

  • We can use Partial Application in event handlers in our render methods
class MyComponent extends React.Component {
  partialHandleLinkClick(type){
    const { activeType } = this.props;
    return function(e) {
      const hasKeyboardModifier = e.ctrlKey || e.shiftKey || e.altKey || e.metaKey;
      updateType(type, activeType, hasKeyboardModifier);
    };
  }
  render() {
    const types = [ 'Foo', 'Bar', 'Baz' ];
    return (
      <div>
        {
          types.map( (type, i) => {
            <a key={i} href="#"
              onClick={this.partialHandleLinkClick(type)}>
              {type}
            </a>
          })
        }
      </div>
    );
  }
}

Currying

  • Generalization of Partial Application
  • You apply a parameter one at a time to a function
  • Turn a single function with many parameters into a many functions each with a single parameter

First Example

function curry(func) {
  return function(arg) {
    return func(arg);
  };
}
console.log(['11', '11', '11', '11'].map(parseInt));         // [ 11, NaN, 3, 4 ]
console.log(['11', '11', '11', '11'].map(curry(parseInt)));  // [ 11, 11, 11, 11 ]

Second Example

function curry2(func) {
  return function(secondArg) {
    return function(firstArg) {
      return func(firstArg, secondArg);
    };
  };
}
const parseBinary = curry2(parseInt)(2);

console.log(parseBinary('111'));  // 7
console.log(parseBinary('10'));   // 2

Third Example

// Revisited from Closures
function divideNByD(n, d) {
  return n / d;
}

const divideBy10 = curry2(divideNByD)(10);
const answer = divideBy10(20);
console.log(answer); // 2

Immutable Data

  • Remember those higher order functions?
  1. javascript filter - create a new list with equal or fewer items
  2. javascript map - create a new array of apples from an array of oranges
  3. javascript reduce - create a new elephant from a list of mice

An Example:

Non-Functional Approach:

let someArray = [];
   ... 
   someListOfData...
   someArray.push(...data);
   ...
return someArray;

Functional Approach:

return someListOfData.reduce((accumulator,data) => accumulate(data,accumulator),[]);

Some Reasons why we may care about Immutable Data (not-exhaustive):

  1. For the higher-order functions, the existing list is not modified, and the new data is created when it is needed
  2. Mutating data opens us up for bugs, in the same vein as do stateful components, objects, services, etc. do
  3. Functions that do not mutate their parameters are easy to test
  4. Immutability makes our methods and applications deterministic

Side Effects

  1. What is a Side Effect: A function or expression is said to have a side effect if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value.

References