Categories
Functional Javascript

Functional JavaScript — Functional Array Methods

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to create our own array methods.

concatAll

We can create our own concatAll method to concatenate all the nested array into one big array.

For example, we can write:

const concatAll = (arrays) => {
  let results = []
  for (const array of arrays) {
    results = [...results, ...array];
  }
  return results;
}

We just spread the array entries of all the arrays and then return the resulting array.

Then we can use it to unnest nested arrays.

For example, we can write:

const arr = concatAll([
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]);

Then arr is:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Reducing Function

Reduce is a function that lets us combine the entries of an array into a single value.

To create our own reduce function, we can write:

const reduce = (array, fn) => {
  let accumlator = 0;
  for (const a of array) {
    accumlator = fn(accumlator, a)
  }
  return accumlator;
}

The reduce function takes an array and a fn function.

array is the array we loop through to combine the values from the array and assign it as the value of accumulator .

fn returns a value with the accumulator and a values combined into one with some operations.

Once we looped through the array, then we return the accumulator value.

Then we can use it to add the numbers in the array by writing:

const sum = reduce([1, 2, 3, 4, 5], (acc, val) => acc + val)

We pass in a number array and a callback to combine the entries of the array together.

Then sum is 15 since we added all the numbers together.

We can make the reduce function more robust by accepting an initial value for accumulator .

For example, we can write:

const reduce = (array, fn, initialValue) => {
  let accumlator = initialValue;
  for (const a of array) {
    accumlator = fn(accumlator, a)
  }
  return accumlator;
}

We assign the initialValue as the initial value of accumulator .

This way, we don’t assume that we’re always working with number arrays.

Zipping Arrays

We can zip multiple arrays into one.

We create the entry for each array with our own function.

And then we push that into the array we return.

We only loop up to the length of the shortest array, so the returned array will also have the same length as the shortest array.

For example, we can write:

const zip = (leftArr, rightArr, fn) => {
  let index, results = [],
    length = Math.min(leftArr.length, rightArr.length);
  for (index = 0; index < length; index++) {
    results.push(fn(leftArr[index], rightArr[index]));
  }
  return results;
}

We created a zip function with the leftArr , rightArr , and fn parameters.

leftArr and rightArr are arrays and fn is a function.

We loop through the shortest length, which is the length .

In the loop body, we push the zipped entry to the results array.

Once we did that, we return results .

Then we can use that by writing:

const zipped = zip([1, 2, 3, 4], ['foo', 'bar', 'baz'], (a, b) => `${a} - ${b}`)

We have a callback to combine the entry from the left and right together into a string.

Then zipped is:

["1 - foo", "2 - bar", "3 - baz"]

Conclusion

We can unnest arrays and zip them together with our own functions.

Categories
Functional Javascript

Functional JavaScript — Currying

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use currying with JavaScript.

Unary Function

A unary function is a function that takes a single argument.

For example, a unary function is:

const identity = (x) => x;

Binary Function

A binary function is a function that takes 2 arguments.

An example of one is:

const add = (x, y) => x + y;

Variadic Function

A variadic function is a function that takes a variable number of arguments.

We can define a variadic function in JavaScript by using the rest operator:

function variadic(...args) {
  console.log(args)
}

args has an array of all the arguments we pass in.

Currying

Curry is converting a function with multiple arguments into nested unary functions.

This is useful because it lets us create functions with some of the arguments applied.

For example, we can convert a binary function:

const add = (x, y) => x + y;

into a function unary function that returns another unary function by writing:

const addCurried = x => y => x + y;

The addCurried function takes a parameter x and returns a function that takes a parameter y which returns the sum of x and y together.

Then we can use it by writing:

const add1 = addCurried(1);
const sum = add1(2);

We called addCurried with 1 to return a function with x set to 1 and assign that to the add variable.

Then we call add1 with 2 to return the final sum.

We can generalize this by creating a function that returns a function that takes one argument, which is the binary function.

Inside that function, we return a function that takes the 2nd argument.

And inside that, we return the result of the binary function called with the parameters of the outer functions.

For example, we can write:

const curry = (binaryFn) => {
  return (firstArg) => {
    return (secondArg) => {
      return binaryFn(firstArg, secondArg);
    };
  };
};

const add = (x, y) => x + y
const sum = curry(add)(1)(2);

to create the curry function to do what we described.

Then we can pass in any binary function like our add function.

And then it’ll be curried automatically.

We can generalize this further with a curry function that recursively returns functions with one argument, until there’s only one argument left.

For instance, we can write:

let curry = (fn) => {
  if (typeof fn !== 'function') {
    throw Error('No function provided');
  }

  return function curriedFn(...args) {
    if (args.length < fn.length) {
      return function(...moreArgs) {
        return curriedFn(...[...args, ...moreArgs]);
      };
    }
    return fn(...args);
  };
};

We check if fn is a function.

If it is, then we return a function that returns a function that calls the same function that’s returned if fn has more parameters than args .

If there are more arguments in fn than args , that means that we can curry it more.

If the number of parameters of the curried function is the same as the number of parameters in fn , then we can’t curry more.

So we just call the function.

Then we can call it by writing:

const add = (x, y, z) => x + y + z;
const sum = curry(add)(1)(2)(3);

We curried the function, so we call the curried function with their individual arguments.

And sum is 6 since we add all the numbers together.

Conclusion

We can curry functions so that we can create functions with some arguments applied and reuse that function for something else.

Categories
Functional Javascript

Functional JavaScript — Creating Functions

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use the functional programming features in JavaScript.

Pure Function Is a Mathematical Function

Pure functions are mathematical functions.

They exhibit all the same characteristics.

Given the same input, then return one output.

JavaScript and Functional Programming

JavaScript is partly a functional programming language.

It has some of the features, but it also allows us to program it in a non-functional way.

For instance, we can create a function in JavaScript that takes no arguments.

But functions are treated as first-class citizens.

So we can have higher-order functions.

JavaScript Functions

We can create a simple JavaScript function by writing:

() => "foo"

We created an arrow function, which is available only in ES6.

We can assign it to a variable by writing:

const foo = () => "foo";

Then we can call the function by writing:

foo()

Strict Mode

JavaScript has a strict mode to let us write better JavaScript code.

To enable strict mode, we can add the 'use strict' directive to add the make the code below it use strict mode.

For example, we can write:

"use strict";

const bar = function bar() {
  return "bar";
};

to enable strict mode.

It’ll stop us from writing bad code like creating global variables accidentally:

"use strict";

global = 'bad';

Multiple Statement Functions

We can write functions with multiple statements.

For instance, we can write:

const simpleFn = () => {
  let value = "abc"
  return value;
}

We have an assignment statement and a return statement to return the value.

Function Arguments

Functions can take arguments.

For example, we can write:

const identity = (value) => value

It takes a value and returns it.

ES5 functions are valid in ES6.

But it doesn’t work the other way around.

So we can’t use arrow functions in an ES5 only environment.

Functional Alternatives to Loops

We can rewrite loops in a functional way by abstracting out the loop body into its own function.

For example, instead of writing:

const array = [1, 2, 3];
for (const a of arr) {
  console.log(a);
}

We can write:

const forEach = (array, fn) => {
  for (const a of arr) {
    fn(a)
  }
}

Our forEach function has an array and fn parameters.

We loop through the array and call our function.

This way, we can abstract out our logic to the outside and pass it in.

If we use const , then we can’t assign a new value to forEach accidentally.

Conclusion

We can create functions to a functional way by creating functions that don’t reference things from the outside.

Also, we can abstract out logic into their own functions and pass them in.

Categories
Functional Javascript

Functional JavaScript — Closures

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use closures.

Closures

Closures are inner functions.

An inner function is a function within a function.

For example, it’s something like:

function outer() {
  function inner() {}
}

Closures have access to 3 scopes.

They include variables that are declared in its own declaration.

Also, they have access to global variables.

And they have access to an outer function’s variable.

For example, if we have:

function outer() {
  function inner() {
    let x = 1;
    console.log(x);
  }
  inner();
}

then the console log logs 1 because we have x inside the inner function and we access it in the same function in the console log.

The inner function won’t be visible outside the outer function.

We can also access global variables within the inner function.

For example, if we have:

let global = "foo";

function outer() {
  function inner() {
    let a = 5;
    console.log(global)
  }
  inner()
}

Then 'foo' is logged since inner has access to the global variable.

Another scope that inner has access to is the scope of the outer function.

For example, we can write:

function outer() {
  let outer = "outer"

  function inner() {
    let a = 5;
    console.log(outer);
  }
  inner()
}

We have the outer variable and we access it in the inner function.

Closure Remembers its Context

A closure remembers its context.

So if we use it anywhere, the variables that are in the function are whatever they are within the original context.

For example, if we have:

const fn = (arg) => {
  let outer = "outer"
  let innerFn = () => {
    console.log(outer)
    console.log(arg)
  }
  return innerFn;
}

Then the outer and arg variable values will be the same regardless of where it’s called.

outer is 'outer' and arg is whatever we passed in.

Since we return innerFn with fn , we can call fn and assign the returned function to a variable and call it:

const foo = fn('foo');
foo()

We pass in 'foo' as the value of arg .

Therefore, we get:

outer
foo

from the console log.

We can see that the values are the same even if we called it outside the fn function.

Real-World Examples

We can create our own tap function to let us log values for debugging.

For example, we can write:

const tap = (value) =>
  (fn) => {
    typeof(fn) === 'function' && fn(value);
    console.log(value);
  }

tap("foo")((it) => console.log('value:', it))

to create our tap function and call it.

We have a function that takes a value and then returns a function that takes a function fn and runs it along with the console log.

This way, we can pass in a value and a function.

Then we get:

value: foo
foo

logged.

The first is from the callback we passed in.

And the 2nd is from the function we returned with tap .

Conclusion

Closures are inner functions.

They have access to the outer function’s scope, global variables, and their own scope.

We can use it or various applications.

Categories
Functional Javascript React

Functional JavaScript — Benefits

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use the functional programming features in JavaScript.

Functional Programming Benefits

Functional programming has various benefits.

This is why it’s being adopted into programming languages like JavaScript.

Pure Functions

One benefit of functional programming is that we define pure functions in our code.

A pure function returns the same output if we pass in the same input to it.

For instance, we can write:

const square = (value) => value ** 2;

We get the value and we return the square of it.

This doesn’t change regardless of what happens outside.

The benefit is that pure functions can easily be tested.

We can just check the output after giving it some input.

Since it doesn’t depend on anything outside, we can check for it easily.

We can check the returned value by writing something like:

square(2) === 4

Reasonable Code

It’s easy to read the code since the code for the function all reside inside the function.

For example, if we have:

const square = (value) => value ** 2;

All we did is square the number which is passed in.

There’s nothing outside, so we can look at it easily.

Parallel Code

Since pure functions don’t depend on any values outside the function, we don’t have to worry about synchronize our function’s value with something outside.

If we have global values, then we may have to do something like this:

let global = "something"
let foo = (input) => {
  global = "somethingElse"
}

let bar = () => {
  if (global === "something") {
    //...
  }
}

We’ve to check the value for the global variable before doing something.

With pure function, we don’t have to do that since there are no external dependencies.

Cachable

Pure functions always return the same output for the given input.

So we can cache the function outputs easily.

We just use the input as the key and the output as the value.

We can just look up the value from the cache.

With caching, we can increase the speed of our code.

For example, we can keep a cache with an object:

const cache = {
  1: 2,
  3: 4,
  //...
}

Then we can check or the cached value by writing:

const value = cache.hasOwnProperty(input) ?
  cache[input] :
  cache[input] = longRunningFunction(input)

We check for the cached value before we run the longRunningFunction .

Pipelines and Composable

We can compose pure functions easily.

We just pass in the return value of one pure function to another pure function.

For example, we can write:

const foo = (a) => {
  return a * 2;
}

const bar = (b) => {
  return b * 3;
}

We can compose the functions by writing:

foo(bar(100));

It looks like a mathematical function and it’s a mathematical function.

Conclusion

Functional programming has various benefits.

We can run code in parallel easily since we don’t have to synchronous code.

Also, we can compose functions easily.

They’re also easier to read and test.