Functional Programming

Easy parts

https://slides.com/salamaashoush/fp-easy

I think the lack of reusability comes in object-oriented languages, not functional languages. Because the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Joe Armstrong, creator of Erlang, on software reusability

A monad is just a monoid in the category of endofunctors.

Functional programmer:

(noun) One who names variables "x", names functions "f", and names code patterns "zygohistomorphic prepromorphism"

https://twitter.com/jamesiry/status/598547781515485184

Agenda

  • What is a function?

  • First-class Functions

  • Pure functions

  • Curried functions

  • Composing functions

  • Point-free style

  • Naming Games

  • WHY?

function sayHello(){

  const name = prompt("what is your name?");

  if(name === "salama"){
    alert("Hello boss");
  }else{
    alert(`Hello ${name}`);
  }

}
// f(x) = x + 1
// addOne :: Int -> Int
function addOne(x){
  return x + 1
}

Functions

are a mapping from an input to an output

First-class Functions

We can treat functions like any other data type and there is nothing particularly special about them — they may be stored in arrays, passed around as function parameters, assigned to variables, etc.

const hi = name => `Hi ${name}`; // as a normal value

const greeting = name => hi(name); // returned from a function
// callbacks
const getServerStuff = callback => ajaxCall(json => callback(json));

// same as above
const getServerStuff = ajaxCall;

Pure Functions

A pure function is a function that, given the same input, will always return the same output and does not have any observable side effects

const xs = [1,2,3,4,5];
// impure
xs.splice(0,3); // [1,2,3]

xs.splice(0,3); // [4,5]
// pure
xs.slice(0,3); // [1,2,3]

xs.slice(0,3); // [1,2,3]


// impure
const minimum = 21;
const checkAge = age => age >= minimum;

// pure
const checkAge = (age) => {
  const minimum = 21;
  return age >= minimum;
};

Side effects may include, but are not limited to

  • changing the file system
  • inserting a record into a database
  • making an http call
  • mutations
  • printing to the screen / logging
  • obtaining user input
  • querying the DOM
  • accessing system state

 

Side Effects

Curried Functions

currying is the concept of calling a function with fewer arguments than it expects

const add = x => y => x + y;
const increment = add(1);
const addTen = add(10);

increment(2); // 3
addTen(2); // 12

in languages like Haskell all function are automatically curried,

but in javascript you have to do it manually this is possible in javascript because of first-class functions, recursion and closures

function curry(fn) {
  const arity = fn.length;

  return function $curry(...args) {
    if (args.length < arity) {
      return $curry.bind(null, ...args);
    }

    return fn.call(null, ...args);
  };
}

const match = curry((what, s) => s.match(what));
const replace = curry((what, replacement, s) => s.replace(what, replacement));
const filter = curry((f, xs) => xs.filter(f));
const map = curry((f, xs) => xs.map(f));

the curried function is the concept that allow us to partially apply function

Function Composition

 mixing more than one small function to make a bigger one

 
const toUpperCase = x => x.toUpperCase();
const exclaim = x => `${x}!`;
// this one 
const shout = x => toUpperCase(exclaim(x))
// is the same as 
const shout = x => exclaim(toUpperCase(x))

shout('send in the clowns'); // "SEND IN THE CLOWNS!"
// compose is the same as pipe 
// the difference is the order of calling functions
// compose from right to left
// pipe from left to right

function compose(...fns) {
  const n = fns.length;

  return function $compose(...args) {
    let $args = args;

    for (let i = n - 1; i >= 0; i -= 1) {
      $args = [fns[i].call(null, ...$args)];
    }

    return $args[0];
  };
}
const head = x => x[0];
const reverse = reduce((acc, x) => [x].concat(acc), []);
const last = compose(head, reverse);

last(['jumpkick', 'roundhouse', 'uppercut']); // 'uppercut'

Point-free style

 means functions that never mention the data upon which they operate. First class functions, currying, and composition all play well together to create this style.

point  ===  argument

 

// not pointfree because we mention the data: word
const snakeCase = word => word.toLowerCase().replace(/\s+/ig, '_');

// pointfree
const snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
// not pointfree because we mention the data: name
const initials = name => name.split(' ').map(compose(toUpperCase, head)).join('. ');
// pointfree
const initials = compose(join('. '), map(compose(toUpperCase, head)), split(' '));
initials('hunter stockton thompson'); // 'H. S. T'

Naming Game

const Box = x =>({
  map: ƒ => Box(ƒ(x)),
  fold: ƒ => ƒ(x),
  inspect: ()=> `Box(${x})`
})


const nextChar = str =>
    Box(str)
      .map(s=>s.trim())
      .map(s => parseInt(s))
      .map(i=>i+1)
      .map(i => String.fromCharCode(i))
      .fold(c=>c.toLowerCase())

const result = nextChar(' 64 ')

[1,2,3].map(x => x +1) // [2,3,4]
const Sum = x =>({
  x,
  concat: ({x:y}) => Sum(x+ y),
  inspect: ()=> `Sum(${x})`,
  empty: ()=> Sum(0)
})


const All = x =>({
  x,
  concat: ({x:y}) => All(x && y),
  inspect: ()=> `All(${x})`,
  empty: ()=> All(true)
})


const result = Sum().empty().concat(Sum(1).concat(Sum(2)))
const result = All().empty().concat(All().concat(All(true)))

[].concat([1,2,3]).map(x => x+1) //[2,3,4]

"" + "Salama" === "Salama"
0 + 5 === 5
const Box = x =>({
  x,
  chain: ƒ => ƒ(x), // sometime it called join, flatmap or bind 
  map: ƒ => Box(ƒ(x)),
  fold: ƒ => ƒ(x),
  inspect: ()=> `Box(${x})`,
   
})


Box().empty().map(x => x+1).chain(x => console.log(x))


Promise.resolve()
  .then(getValuesFromServer)
  .then((values)=> console.log(values))

A monad is just a monoid in the category of endofunctors.

 

Why?

  1. Declarative

  2. Pure functions are easier to reason about

  3. Testing is easier

  4. Debugging is easier

  5. Programs are more bulletproof

  6. Parallel/concurrent programming is easier

NEXT

?

Functional programming the easy parts

By Salama Ashoush

Functional programming the easy parts

  • 126