The Power of Function

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

Functional Programming

Functors

Applicative

Monads

Currying

Functions

SideEffects

Pure

Academic

Math

Point-free

Declarative

Category

First-class

Lamda

Haskell

Monoids

Unit

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

Hello EgyptJS

 

My name Salama Ashoush 

currently working as a frontend engineer for tajawal

I love javascript and never liked the big fat java

In my free time,

sometimes I study about programming, design, 3d animation and web technologies

sometimes I watch movies, anime, and play games

 

find me anywhere  @salamaashoush or www.salamaashoush.com

I am not a functional programming guru

Agenda

  • What is a function?

  • First-class Functions

  • Pure functions

  • Curried functions

  • Composing functions

  • Point-free style

  • Naming Games

  • Benefits of FP

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

 

SideEffects

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));

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

?

The power of function

By Salama Ashoush

The power of function

  • 299