JavaScript functional programming

Functional programming in JavaScript

I’ve been programming javascript for a long time, and I’ve seen the language grow from being a simple tool for validating forms using jquery to being able to develop huge backend applications. Since THE advent of ES6 and the addition of classes, I think this only refers to the chaos of programming and brings javascript programming closer to Java.

Since getting into functional programming, I’ve seen its potential to adapt to javascript and write much cleaner code.

What is functional programming

In computer science, functional programming is a programming paradigm — a style of constructing the structure and elements of a computer program — that treats computations as mathematical functions, avoiding changes in state and mutable data. It is a declarative programming paradigm because programs are done with expressions or declarations rather than statements. In a function, the value of the output depends only on its parameters; in other words, the same output always yields the same output. This is in contrast to imperative programming, where global program loading, in addition to function arguments, can also affect the final result of a function. Eliminating side effects, that is, state changes that do not depend on the output of the function, makes the program easier to understand, which is one of the main motivations for developing programs using functional programming.

The concepts we are going to study

  • Lazy evaluation
  • Monoid
  • Monad
  • Functor
  • Curry
  • Lambda
  • Recursion
  • Closure
  • Stateless
  • Compose
  • High order functions
  • Pure functions
  • First Class
  • Side effects

reading

There are some very interesting links in the back of my notes

  • Adit. IO/posts / 2013 -…
  • Github.com/haskellcama… (Nice!)
  • leanpub.com/fljs
  • medium.com/@lunasunkai… (Nice!)
  • medium.com/@_cyberglot… ? (Nice!)

Inertia is evaluated

define

Lazy evaluation, or call on demand, is an evaluation strategy that delays the evaluation of an expression until its value is needed (not strictly evaluated), which also avoids repeated evaluation.

Code sample

Lazy evaluation is the deferred expression evaluation until later execution, which can be implemented with Thunks.

Put parameters in a temporary function and pass the temporary function into the function body. This temporary function is called the Thunk function

Example 1

// non-lazy evaluation
var value = 1 + 1  // Get 2 immediately

// lazy evaluation
var lazyValue = () = > 1 + 1  // lazyValue gets a value of 2 when called
Copy the code

Example 2

// non-lazy evaluation
var add = (x, y) = > x + y
var result = add(1.2)  // Immediately calculate the value to be 3

// lazy evaluation
var addLazy = (x, y) = > () = > x + y;
var result = addLazy(1.2)  // Returns a 'thunk', which results in 3 when needed
Copy the code

Example 3

// Corrie add (non-lazy evaluation)
var add = x= > y= > x + y
var add3 = add(3)
var result = add3(7)  // Immediately calculate the value 10
Copy the code

Example 4

// non-lazy evaluation
var callApi = spec= > fetch(spec.url, spec.options);
var result = callApi({url: '/api'.options: {}});

// lazy evaluation
var callApiLazy = spec= > () = > fetch(spec.url, spec.options);
var result = callApiLazy({url: '/api'.options: {}});
Copy the code

Monoid (MAO semigroup)

define

It describes a set of elements that have three special attributes when used in conjunction with a specific operation (usually called concat) :

Monoid is a set M with a binary operation *: M × M → M

This operator must combine two values in the collection into a third value in the same collection. Assuming that a and B are both part of the set, then concat(a,b) must both be part of the set. In category theory, this is called magma

For any * A * and *b* within *M*, * A **b* will also be within *M*.

Operators must satisfy the associative law: concat(x, concat(y, z)) must be equal to concat(concat(x, y), z), where x,y,z can be any value in the set. No matter how you organize the operators, as long as you follow the rules, the result should be the same.

, namely the associative law, for any M in * * * a *, * *, b * c *, (* * * * b *) = c * * * * a * * (* * * * b * c)

The collection should have a neutral element associated with the operator, and if the neutral element is combined with any other value, the value should not be changed. concat(element, neutral) == concat(neutral, element) == element

, per unit of yuan: the elements within a M in * * * * e, makes any within * M * * * a * * * e a * will be consistent with * = * * * * e a * = * * a

In the set of real numbers, for example, 0 is the unit of the set of real numbers corresponding to addition, and adding any element of the real number to 0 does not change the value of the element

Code sample

Monoid examples can be string concatenation, number addition, function composition, asynchronous composition.

Example 1 –Strings

const concat = (a, b) = > a.concat(b);

concat("hello", concat(""."world")); // "hello world"
concat(concat("hello".""), "world"); // "hello world"

concat("hello".""); // 'hello'
concat(""."hello"); // 'hello'
Copy the code

Example 2 –Numbers

(1 + 2) + 3= =1 + (2 + 3); // true

x + 0; // x
Copy the code

Example 3 –Functions

const compose = (func1, func2) = > arg= > func1(func2(arg));

const add5   = a= > a + 5;
const double = a= > a * 2;

const doubleThenAdd5 = compose(add5,double);
doubleThenAdd5(3); / / 11
Copy the code

Functor (Functor)

define

Functors are things that you can map to. Is anything that can be mapped. In practice, functors represent a type that maps…

Code sample

In other words, we can map any object and apply functions to generate another instance of an object of the same type and connection.

Example 1

[1.2.3].map(val= > val * 2); // get [2, 4, 6], Array is a functor
Copy the code

Example 2

// Number -> string mapping
const numberToString = num= > num.toString()
Copy the code

Example 3

const Identity = value= > ({
  map: fn= > Identity(fn(value)),
});
const myFunctor = Identity(1);
myFunctor.map(trace); / / 1
myFunctor.map(myFunction).map(trace); / / 2
Copy the code

Pure functions

define

A function is a procedure that takes some input, called parameters, and produces some output, called return values.

Code sample

There are pure and impure functions, and side effects can occur if the function modifies the external return value.

  • Given the same input, the same output will be produced
  • There are no side effects

Example 1

/ / pure functions
const add = (x, y) = > x+y;
const sub = (x, y) = > x-y;

// an impure function
let tmp = 2;

const concat = (a,b) = >{
 tmp = 3;
 return a+b;
};
Copy the code

Example 2

const double = x= > x * 2;
Copy the code

Example 3

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

function mul(a, b) {
  return a * b;
}

let x = add(2, mul(3.4));
Copy the code

Side effects

define

Side effects are any changes in application state that can be observed outside of the function being called, in addition to the return value.

  • Modify any external or global variables (such as global variables, or variables in the parent function’s scope chain)
  • Print to console
  • Output to screen
  • Write to file
  • Write to the network
  • Trigger any external processes
  • Call any other functions that have side effects

Code sample

Functional programming largely avoids side effects by making programs seem easier to understand and easier to test

Example 1

let default = ' ';

const run = () = >{
 default = '1111; return 'aaaaaaaa'; } run();Copy the code

Example 2

let counter = 0;

const sum = (a,b) = >{
  counter++;
  return a+b;
}
Copy the code

Reference transparent

define

In functional programming, reference transparency is often defined by the fact that in a program, an expression can be replaced by its value (or anything with the same value) without changing the result of the program. This means that the same result is always returned for a given parameter without any side effects.

Code sample

Example 1

int add(int a, int b) {
    return a + b
}

int mult(int a, int b) {
    return a * b;
}

// 1) Add (2, mult(3, 4))
// 2) if we replace it with mult(3,4), it also results in 12.
// 3) add(2, 12) === add(2, mult(3, 4))
Copy the code

Higher-order functions

define

Higher-order functions are functions that take other functions as arguments or return values.

Code sample

In Javasript, functions can be treated as values (first-class citizens). This means they can be passed as variables or as parameters

Example – the Map:

const double = n= > n * 2

// This map is a higher-order function
[1.2.3.4].map(double); // [2, 4, 6, 8]
Copy the code

Example – Filter

let isBoy = student= > student.sex === 'M';

//Filter is a higher-order function
let getBoys = grades= >grades.filter(isBoy);
Copy the code

Example – Custom

const ivaTax = (a) = > ((a*21) /100);

//Calc is a higher-order function
const calc = (ammount, tax) = > tax(ammount);

/ / call
calc(100.50,ivaTax);
Copy the code

The wait function

define

I think this concept is very important, and maybe it doesn’t come from functional programming, but it’s interesting. First-class functions mean that you can treat first-class objects like any other — they can be stored as variables, passed around, returned by other functions, and even hold their own attributes. Sometimes referred to as first-class citizen, as an object, it supports all operations that can be performed on other objects.

In fact, JavaScript objects are themselves an object type. So first-class functions can support the same operations as other objects.

  • Is stored in a variable
  • Pass parameters to other functions
  • As a return value to other functions
  • Is stored in a data structure
  • Save their own properties and methods

Code sample

For JavaScript programmers, this means you can use powerful design patterns, such as higher-order functions, callback functions, and so on.

Examples – stored in functions

const sayHi = (name) = >console.log('HI',name);
sayHi('Damian');
Copy the code

Example — passed as a parameter

const tax = (tax) = >(tax*21) /100;
const buy = (value,taxes) = > value+taxes(value);

/ / call
buy(100,tax);
Copy the code

Example — stored in a data structure

const tax = (tax) = >(tax*21) /100;
const buy = (value,taxes) = > value+taxes(value);

const scooter = {
 ammount:100,
 buy,
 tax
};

/ / call
scooter.buy(scooter.value,scooter.tax);
Copy the code

recursive

define

Recursion is the technique of iterating, calling itself over and over until the final result is reached. Most loops can be rewritten to a recursive style, which is the default in some functional languages.

Code sample

JavaScript does support recursive functions, but it is important to know that most JavaScript compilers are not currently optimized to safely support them.

In JS, we can use filter, map, reduce, foreach and other higher-order functions to use recursion.

Code Example 1

const countdown = (value) = > (value>0)? countdown(value-1):value;
Copy the code

Code Example 2

const factorial = (number) = > (number<=0)?1:(number*factorial(number-1));
Copy the code

Pay attention to

Using this function can cause an overflow in the call stack of the JS engine.

RangeError: Maximum call stack size exceeded:

countdown(100000)

Uncaught RangeError: Maximum call stack size exceeded
    at countdown (<anonymous>:1:19)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
    at countdown (<anonymous>:1:40)
Copy the code

Solution — Tail recursion

There is a technique called tail recursion that can solve this situation

Here are some related articles:

Eddmann.com/posts/recur… medium.com/@cukejianya… En.wikipedia.org/wiki/Trampo… Raganwald.com/2013/03/28/…

Code sample

/ / tail recursion
const trampoline = (fn) = > {
    while (typeof fn === 'function') {
        fn = fn();
    }
    return fn;
};

/ / test
const odd  = (n) = > () = > n === 0 ? false : even(n - 1);
const even = (n) = > () = > n === 0 ? true : odd(n - 1);

/ / call
trampoline(factorial(100000)) // 
Copy the code

closure

A closure is a combination of functions that are bundled together (closed) with references to their surrounding state (lexical environment). In other words, closures allow you to access the scope of an outer function from an inner function. In JavaScript, closures are created every time a function is created.

stateless

define

Stateless programming is a paradigm in which the operations you implement (functions, methods, procedures, whatever you want to call them) are insensitive to the state of the computation. This means that all data used in the operation is passed as input to the operation, and all data used by any operation that invokes the operation is returned as output.

Code sample

This is a form of function composition, because it is the result of the multiplication passed to add.

The sample

const isEven = x= > x % 2= = =0
const filterOutOdd = collection= > collection.filter(isEven)

const add = (x, y) = > x + y
const sum = collection= > collection.reduce(add)

const sumEven = collection= > compose(sum, filterOutOdd)(collection)

sumEven([1.2.3.4])
Copy the code

combination

define

In the most general terms, we can divide the entire programming principle into stages:

  • Understand the logic of complex problems
  • Break down a complex problem into smaller problems
  • Tackle one small problem at a time and then combine them to form a coherent solution.

Code sample

This is a form of function composition, because it is the result of the multiplication passed to add. In mathematics, we understand it: f (x) (x) = 0 g f (x) (g), example, f (x) = 2 x + 5 and g (x) = 1 + 2 = x > f (x) (g) = 2 x (1 + 2) + 5

Example — function composition

const isEven = x= > x % 2= = =0
const filterOutOdd = collection= > collection.filter(isEven)

const add = (x, y) = > x + y
const sum = collection= > collection.reduce(add)

const sumEven = collection= > compose(sum, filterOutOdd)(collection)

sumEven([1.2.3.4])
Copy the code

Cory,

define

Coiling is the process of converting a function with multiple arguments into a function with a single argument.

Code sample

A coriization function is one that takes more than one argument at a time.

Example — Corrification 1

const notCurry = (x, y, z) = > x + y + z; // Regular function
const curry    = x= > y= > z= > x + y + z; // Corylization function
Copy the code

Example — Corrification 2

const divisible = mod= > num= > num % mod;

/ / call
divisible(10) (2);

/ / call
const divisibleEn3 = divisible(3);
divisibleEn3(10)
Copy the code

Lambda

define

Lambda expressions appear in most modern programming languages (Python, Ruby, Java…) , which are simple expressions for creating functions. This is important for programming languages because it supports first-class functions, which basically means passing functions as arguments to other functions or assigning them to variables.

What is theLambda?

In computer science, the most important feature of lambda expressions is their use as data. This means that a function can be passed as an argument to another function, as a return value of a function, or assigned to a variable or data structure. This is a classic of programming languages that we use => or ->simbols when we talk about lambda.

LambdaVs Anonymous functions

Anonymous functions are functions that have no name.

const hello = function(name){console.log('Hi '+name); } Or using arrow functionsconst hello = (name) = > {console.log('Hi '+name); } Other example: [1.2.3.4.6].filter((num) = >num>=3); (num)=>num>=3 is an anonymous function
Copy the code

Lambda functions are functions that are used as arguments:

[1.2.3.4.5.6.7.8].map(e= >({value:e})); //e=>({value:e}

$('#el').on('click'.() = >{... });// is a lambda, an anonymous function, and an arrow function
$('#el').on('click'.function(){... });// is a lambda, also an anonymous function
$('#el').on('click'.function clickHandler() = >{... });// is a lambda, also a named function
Copy the code

Code sample

Lambda is not always an anonymous function, which may seem confusing, because you take Lambda equals an anonymous function as a truism. While this is a useful concept and anonymous functions have interesting uses, such as points-free-style is a useful concept, it’s not the main thing about lambda expressions; it’s mostly syntactic sugar.

Example — arrow function

const isChildren = (person) = >person.age<18;
const isTeen     = (person) = >person.age>18 and person.age<25;

const course = [{name:'bob'.age:18}, {name:'Damian'.age:32}, {name:'Alexander'.age:19}];

//Get childrens.
course.filter(person= >isChildren(person));

//Get teens.
course.filter(person= >isTeen(person));
Copy the code

Example — named functions

$('#el').on('click'.function clickHandler() = >{... });/ / Lambda expressions
Copy the code

Example — anonymous functions

$('#el').on('click'.() = >{... });Copy the code

The resources

  • 2016.jsunconf.eu/

  • Bangbangcon.com/speakers.ht…

  • Gist.github.com/ericelliott…

  • Teamtreehouse.com/community/w…

  • Medium.com/front-end-w…

  • Marmelab.com/blog/2018/0…

  • Codewords.recurse.com/issues/four…

  • www.tutorialspoint.com/functional_…

  • www.youtube.com/watch?v=-tn…

  • www.youtube.com/watch?v=q2N…

  • Github.com/vakila/func…

  • Speakerdeck.com/vakila/firs…

  • www.codingame.com/playgrounds…

  • Hackernoon.com/function-ty…

  • Marmelab.com/blog/2018/0…

  • Developer.mozilla.org/es/docs/Web…

  • www.codementor.io/agustinchia…

  • Hackernoon.com/lazy-evalua…

  • Stephen – young. Me. UK / 2013/01/20 /…

  • Marmelab.com/blog/2018/0…

  • Marmelab.com/blog/2019/0…

The original link

Functional programming in Javascript