Categories
Functional Javascript

Functional Programming Features in JavaScript

JavaScript is an easy to learn programming language. It also uses lots of functional programming features that make our lives easier.

In this article, we’ll take a look at some functional programming features of JavaScript that we can use in our code.

What is Functional Programming?

Functional programming is a programming paradigm where we treat computations as an evaluation of mathematical functions. This means we avoid changing state and mutating data,

It’s a declarative programming paradigm where we only tell how the program should run in a high level to create our program rather than writing instructions to tell the computer how to run a program step by step.

Functional programming emphasizes the use of pure functions, where a function’s arguments determine its output.

Also, side effects should be eliminated in functions since they make a function impure.

Eliminating side effects also make functions easier to test since we only have to put in inputs and check its output rather than also having to check what the side effects have done.

Lazy Evaluation

Lazy evaluation is evaluating values only when the value is needed. In JavaScript, we can do that by returning a value in a function and then invoking the function when needed.

For instance, we can write the following code to do that:

const lazy = () => 2 + 1

In the code above, we put our value 3 as the return value of the lazy function.

Now we only get the value when we need it by calling the lazy function.

This is opposed to setting 3 as a variable as we do below:

let val = 2 + 1;

The code above is evaluated immediately rather than waiting for the lazy function to be evaluated before returning the value.

Lazy evaluations avoid repeated evaluation, which makes our code more efficient than evaluating expressions immediately.

We can also implement lazy evaluation with functions by return the function instead of assigning a function directly to a variable.

For instance, we can write the following to create a lazily evaluated function as follows:

const lazyAdd = (a, b) => () => a + b;
const add = lazyAdd(1, 2);
const result = add();

In the code above, we have the lazyAdd function, which returns a function that returns the 2 parameters added together.

Then when we call the lazyAdd function with 2 numbers, we return a function that’ll return the 2 numbers added together instead of returning the evaluated expression directly.

Then when we call add , we actually return 1 and 2 added together.

This again delays the evaluation of the sum until it’s needed. And it’s opposed to the following code:

const add = (a, b) => a + b;
const result = add(1, 2);

which evaluates the 2 arguments added together immediately.

Monoid

In functional programming, a monoid is a set of elements that has 3 special properties when combined with an operation named concat .

Monoids have the following characteristics:

  • The operation must combine 2 values into the 3rd value of the same set. If a and b are part of the set, then concat(a, b) should also be part of the same set.
  • The operation must be associative. That is, concat(a, concat(b, c)) should be the same as concat(concat(a, b), c) .
  • The set must have a neutral element regarding its operation. If the neutral element is combined with any other value, it shouldn’t change it. That is, concat(a, neutral) === concat(neutral, a) .

There’re many examples of monoids in JavaScript. The most common are strings and numbers.

For instance, with numbers, we can check that they meet the 3 properties above.

Given that a is 1 and b is 2, and the concat operator is + , we can check that the first property is met by writing:

a + b === 3

a and b are both numbers and 3 is a number, so they’re in the same set, and the first criterion is met.

Then we can check associativity as follows:

((a + b) + 3) === (a + (b + 3))

Since that returns true , we can group them in the order we want, so + with numbers is associative.

We can check if a set has a neutral element by picking 0 as the neutral element.

For instance:

a + 0 === 0 + a

returns true , so we know that the set of numbers has a neutral element, which is 0. Therefore, we know that there’s a neutral element when adding numbers.

Therefore, the addition operation with numbers is a monoid.

Monoids are useful because it lets us compose multiple simple operations to create complex behavior out of them, without having to introduce new concepts in our code.

They always return the elements in the same set, so we can continue composing these elements and operations together.

Associativity lets us disregard the order of the compose and still get the same result, reducing the cognitive load that we need when we need to compose multiple operations.

Conclusion

JavaScript exhibits some functional programming characteristics. This makes writing code more like defining and using mathematical functions.

For instance, things can be lazily evaluated to increase efficiency and it has monoids like number addition. Monoids are useful because of the easy composition of multiple operations.

Functional programming emphasizes pure functions, which are easier to test.

Categories
Functional Javascript

Manipulate JavaScript Arrays the Functional Way

Functional programming is a programming paradigm which states that we create computations as the evaluation of functions and avoid changing state and mutable data.

To write programs in a functional way, we use pure functions and immutable data structures.

In JavaScript, we can easily apply functional principles to arrays by using its built-in array methods.

In this article, we’ll look at the array methods that let us manipulate them in a functional way.

Filtering Items

We can use the filter method to return an array with entries from the original array that has the condition that the callback of the filter method returns.

For example, if we have the following array:

const store = [{
    name: "Apple",
    price: 1
  },
  {
    name: "Banana",
    price: 2
  },
  {
    name: "Grape",
    price: 1.2
  }
];

We can get the items that have price less than 2 as follows:

const cheapItems = store.filter(s => s.price < 2);

Then we get the following for cheapItems:

[
  {
    "name": "Apple",
    "price": 1
  },
  {
    "name": "Grape",
    "price": 1.2
  }
]

Using the filter method fits with the functional paradigm since the function is pure, given the same array and same condition, we always get the same results returned.

It also doesn’t change the existing elements of the array that it’s called on, which means we can’t accidentally change anything from the original array.

Mapping Array Objects

map is used to map entries of an array into something else. It’s frequently used to convert and transform data. Using map fits with the functional programming paradigm because again it’s a pure function that gives the same outputs for the given inputs, and it doesn’t change the original array.

As long as the function we pass into the map function to combine the values is pure, the map method should also be pure since it just calls this callback function and returns the updated values into a new array.

For example, given the following array:

const volumesInLiters = [{
    name: "Milk",
    volumeInLiters: 1
  },
  {
    name: "Apple Juice",
    volumeInLiters: 2
  },
  {
    name: "Orange Joice",
    volumeInLiters: 1.2
  }
];

We can add the volumeInQuarts field to each entry of the object and set the volume in quarts to as the value of each by writing:

const volumesInQuarts = volumesInLiters.map(v => {
  v = {
    ...v,
    volumeInQuarts: v.volumeInLiters * 1.057
  };
  return v;
})

We convert v.volumeInLiters * 1.057 and set it to volumeInQuarts for each entry.

Then we get:

[
  {
    "name": "Milk",
    "volumeInLiters": 1,
    "volumeInQuarts": 1.057
  },
  {
    "name": "Apple Juice",
    "volumeInLiters": 2,
    "volumeInQuarts": 2.114
  },
  {
    "name": "Orange Joice",
    "volumeInLiters": 1.2,
    "volumeInQuarts": 1.2684
  }
]

Using Reduce to Combine Values of Array Entries

Like filter and map, reduce also fits with the functional paradigm since we use it to gather entries of an array and return one value by the way that we specify.

As long as the function we pass into the reduce function to combine the values is pure, the reduce method should be pure. The function just calls the callback function we pass into reduce to compute the combined value.

For example, given the following array:

const store = [{
    name: "Apple",
    price: 1
  },
  {
    name: "Banana",
    price: 2
  },
  {
    name: "Grape",
    price: 1.2
  }
];

We can write the following to get the total price of all items:

const totalPrice = store.map(s => s.price).reduce((subtotal, b) => subtotal + b, 0);

We have to use map to map all the entries in the store array to price numbers. Then we can use the reduce method to add the new value to subtotal.

Then we should get 4.2 for totalPrice, which is the total of all the prices of the 3 items in store.

The second argument of reduce is the starting value of the reduction, or combining the values into one.

Conclusion

The filter, map, and reduce array methods are the main methods for manipulating arrays in a functional manner. They all return values and don’t change the array that it’s called on. This makes it difficult to unintentionally change the values.

filter returns an array that meets the condition that we return in the callback that we pass in.

map returns a new array that has the values of the original array mapped to new values in a way that we specify.

reduce combines the values of array entries into one by taking a callback function that we pass in to do the combining and returns the combined value.

The functions are pure if we pass in pure functions to them as callbacks since they just call the functions that we pass in to do the manipulation.

Categories
Functional Javascript

Functional Programming Concepts in JavaScript

Functional programming is a programming paradigm which states that we create computation as the evaluation of functions and avoid changing state and mutable data.

In JavaScript, we can apply these principles to make our programs more robust and create fewer bugs.

In this article, we’ll look at how to apple some functional programming principles in our JavaScript programs, including pure functions and creating immutable objects.

Pure Functions

Pure functions are functions that always return the same output given the same set of inputs.

We should use pure functions as much as possible because they’re easier to test and the output is always predictable given a set of inputs.

Also, pure functions don’t create any side effects, which means that it does change anything outside the function.

An example of a pure function would be the following add function:

const add = (a, b) => a + b;

This function is a pure function because if we pass in 2 numbers, we’ll get the 2 numbers added together returned.

It doesn’t do anything outside the function, and it doesn’t have values that change the returned value inside the function.

Example of functions that aren’t pure functions include:

let x;
const setX = val => x = val;

setX isn’t a pure function because it sets the value of x which is outside the function. This is called a side effect.

A side effect is a state change that’s observed outside the called function other than its returned value. setX sets a state outside the function, so it commits a side effect.

Another example would be the following:

const getCurrentDatePlusMs = (milliseconds) => +new Date() + milliseconds;

getCurrentDatePlusMs returns a value that depends on +new Date() which always changes, so we can check the value of it with tests easily. It’s also hard to predict the return value given the input since it always changes.

getCurrentDatePlusMs isn’t a pure function and it’s also a pain to maintain and test because of its ever-changing return value.

To make it pure, we should put the Date object outside as follows:

const getCurrentDatePlusMs = (date, milliseconds) => +date + milliseconds;

That way, given the same date and milliseconds, we’ll always get the same results.

Immutability

Immutability means that a piece of data can’t be changed once it’s defined.

In JavaScript, primitive values are immutable, this includes numbers, booleans, strings, etc.

However, there’s no way to define an immutable object in JavaScript. This means that we have to be careful with them.

We have the const keyword, which should create a constant by judging from the name of it, but it doesn’t. We can’t reassign new values to it, and we can’t redefine a constant with the same name.

However, the object assigned to const is still mutable. We can change its properties’ values, and we can remove existing properties. Array values can be added or removed.

This means that we need some other way to make objects immutable.

Fortunately, JavaScript has the Object.freeze method to make objects immutable. It prevents property descriptors of an object from being modified. Also, it prevents properties from being deleted with the delete keyword.

Once an object is frozen, it can’t be undone. To make it mutable again, we have to copy the object to another variable.

It applies these changes to the top level of an object. So if our object has nesting, then it won’t be applied to the nested objects.

We can define a simple recursive function to do freeze level of an object:

const deepFreeze = (obj) => {
  for (let prop of Object.keys(obj)) {
    if (typeof obj[prop] === 'object') {
      Object.freeze(obj[prop]);
      deepFreeze(obj[prop]);
    }
  }
}

The function above goes through every level of an object and calls Object.freeze on it. This means it makes the whole nested object immutable.

We can also make a copy of an object before manipulating it. To do this, we can use the spread operator, which works with objects since ES2018.

For example, we can write the following function to make a deep copy of an object:

const deepCopy = (obj, copiedObj) => {
  if (!copiedObj) {
    copiedObj = {};
  }

  for (let prop of Object.keys(obj)) {
    copiedObj = {
      ...copiedObj,
      ...obj
    };
    if (typeof obj[prop] === 'object' && !copiedObj[prop]) {
      copiedObj = {
        ...copiedObj,
        ...obj[prop]
      };
      deepCopy(obj[prop], copiedObj);
    }
  }
  return copiedObj;
}

In the code above, we create a new copiedObj object to hold the properties of the copied object if it doesn’t exist yet, which shouldn’t in the first call.

Then we loop through each property of the obj object and then apply the spread operator to copiedObj and obj to make a copy of the values at a given level. Then we do this recursively at every level until we went through every level, then we return the final copiedObj .

We only apply the spread operator if the property doesn’t exist at that level yet.

How do we know that this works? First, we can check if properties of each value are the same, which it is if we run console.log on it. Then we can also check with the === if the copied object has the same reference as the original object.

For example, if we have:

const obj = {
  foo: {
    bar: {
      bar: 1
    },
    a: 2
  }
};

Then we can check by writing:

const result = deepCopy(obj);
console.log(result);

To check the content of result .

We should get:

{
  "foo": {
    "bar": {
      "bar": 1
    },
    "a": 2
  }
}

This is the same as obj . If we run:

console.log(result === obj);

we get false , which means the 2 aren’t referencing the same object. This means that they’re a copy of each other.

Pure functions and immutability are important parts of functional programming. These concepts are popular for a reason. They make outputs predictable and make accidental state changes harder.

Pure functions are predictable since they return the same output for the same set of inputs.

Immutable objects are good because it prevents accidental changes. Primitive values in JavaScript are immutable, but objects are not. We can freeze it with the Object.freeze method to prevent changes to it and we can also make a copy of it recursively with the spread operator.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Playing With Function Arguments

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement more Lodash methods that are used to manipulate function arguments.

flip

The Lodashy flip method applies the arguments to a function in reverse order.

We can easily implement this ourselves with the spread operator. For instance, we can create our own flip method as follows:

const flip = (fn) => (...args) => fn(...args.reverse())

In the code above, we created the flip function by getting the fn parameter, which is a function.

Then we return a function with the args array and then return fn with the args applied in reverse by calling args.reverse() and then use the spread operator to apply the arguments.

We can then call it as follows:

const flipped = flip((...args) => args);

And then when we call the flipped function as follows:

flipped('a', 'b', 'c', 'd')

We then see that the returned value is [“d”, “c”, “b”, “a”] .

negate

The Lodash negate method that returns a function that negates the predicate that’s passed into the negate method.

For instance, we can write the following code:

const negate = (predicate) => (...args) => !predicate(...args)

In the code above, we created the negate function by making a function that takes in a predicate and then return a function that takes in the args and then return the predicate called with args spread by the spread operator negated.

Then we can call it as follows:

const isEven = (n) => n % 2 == 0;
[1, 2, 3, 4, 5, 6].filter(negate(isEven))

We called by first defining an isEven function that has the condition that the n % 2 == 0 , which returns true if the number is even.

Then we can used it with the filter method as follows:

[1, 2, 3, 4, 5, 6].filter(negate(isEven))

We negated the isEven method’s returned value with negate , so the returned numbers are odd numbers.

partial

The Lodash partial method returns a function that takes a function with the arguments partially applied to it. Then we can call that returned function with more arguments.

For instance, we can create our own partial method with the following code:

const partial = (fn, ...partialArgs) => (...args) => fn(...partialArgs, ...args)

In the code above, we created a function that takes fn , which is a function, and partialArgs , which are some of the arguments that are called. Then we return a function that takes more arguments and calls fn with the partialArgs and args spread within the fn .

Both partialArgs and args are applied to fn with the spread operator.

Then we can call it as follows:

const greet = (greeting, name) => {
  return `${greeting} ${name}`;
}

const sayHelloTo = partial(greet, 'hello');
console.log(sayHelloTo('joe'));

We defined the greet function, which takes 2 arguments. With our partial function, we returned a function with the first greeting argument and then returns the function with the given argument applied and set it to sayHelloTo

Then we call sayHelloTo and with the 2nd argument and then we can see from the console log that it’s hello joe as we expected.

partialRight

The partialRight method is like partial , except that we apply the arguments from right to left instead.

We can just change partial slightly to create the partialRight function as follows:

const partialRight = (fn, ...partialArgs) => (...args) => fn(...args, ...partialArgs)

In the code above, we just flipped the partialArgs and args order.

Then we can call it as follows:

function greet(greeting, name) {
  return `${greeting} ${name}`;
}

const greetFred = partialRight(greet, 'joe');
console.log(greetFred('hi'));

We defined the greet function with the greeting and name arguments and then we applied the arguments in reverse order.

Then we get that console log outputs 'hi joe' .

Conclusion

The flip method returns a function that has the arguments applied in reverse. We can implement that easily with the spread and rest operators.

Lodash’s negate method returns a function that negates the result of the given predicate function. We can just return a function that negates the returned result of the predicate function.

The partial and partialRight methods return a function that’s partially applied partially and takes more arguments that’s applied in addition to the partially applied arguments.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Combining Values

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement Lodash methods that deal with combining items in a collection.

reduce

The Lodash reduce method combines the values in a collection into one value by calling the iteratee function, which takes an accumulator parameter with the values that are combined so far and the 2nd parameter is the item to be combined for the array version.

The object version takes the result , which has the accumulated value, value , which has the value of the object, and key which has the key of the object that’s being processed.

It also takes an optional accumulator object with the initial value of the accumulator parameter before iteratee is run.

Then we can write the following code:

const reduce = (collection, iteratee, accumulator) => {
  if (Array.isArray(collection)) {
    return collection.reduce(iteratee, accumulator)
  } else {
    let reduced = accumulator;
    for (const key of Object.keys(collection)) {
      iteratee(reduced, collection[key], key)
    }
    return reduced;
  }
}

In the code above, we check if collection is an array. If it is, then we call reduce on the array instance with the iteratee function as the callback and the accumulator as the initial value.

Otherwise, we create a new reduced variable with the accumulator as the initial value.

Then we loop through the keys of the collection object with the iteratee , which takes the reduced value, the value of the given key and the key itself as the arguments.

We then return the reduced object, which has the combined results.

Then we can call it as follows:

const result = reduce({
  'a': 1,
  'b': 2,
  'c': 1
}, (result, value, key) => {
  (result[value] || (result[value] = [])).push(key);
  return result;
}, {});

In the code above, we called our own reduce method with an object and a iteratee function with the result , value , and key parameters. Then in the function, we combined the values by populating the keys of the resulting object with the value and push the keys into the array.

Then we get:

{
  "1": [
    "a",
    "c"
  ],
  "2": [
    "b"
  ]
}

as the value of result .

We can also call our reduce function with an array as follows:

const result = reduce([1, 2], (sum, n) => {
  return sum + n;
}, 0);

Then we get that result is 3.

Photo by Brett Jordan on Unsplash

reduceRight

The reduceRight method is similar to reduce except that the values are combined from the end to the start.

We can implement it in a similar way to reduce as follows:

const reduceRight = (collection, iteratee, accumulator) => {
  if (Array.isArray(collection)) {
    return collection.reverse().reduce(iteratee, accumulator)
  } else {
    let reduced = accumulator;
    const keys = Object.keys(collection)
    for (let i = keys.length - 1; i >= 0; i--) {
      iteratee(reduced, collection[keys[i]], keys[i])
    }
    return reduced;
  }
}

In the code above, in the array case, we reversed the array by calling reduce with the same arguments as the reduce implementation.

Otherwise, we loop through the object’s keys in reverse order. In the loop, we call iteratee on each item. The iteraee function takes the same parameters as the one we pass into reduce .

We can call reduceRight as follows:

const result = reduceRight({
  'a': 1,
  'b': 2,
  'c': 1
}, (result, value, key) => {
  (result[value] || (result[value] = [])).push(key);
  return result;
}, {});

Then we get that result is:

{
  "1": [
    "c",
    "a"
  ],
  "2": [
    "b"
  ]
}

since we looped through object entries in reverse order.

We can call reduceRight with an array as follows:

const result = reduceRight([1, 2], (sum, n) => {
  return sum + n;
}, 0);

Then we get the same result as reduce , which is 3.

Conclusion

The reduce and reducerRight methods can be done with existing array methods for arrays. We can just call reduce on the array instance with the iteratee function and the accumulator .

For objects, it’s more complex. We have to loop through the items by getting the keys and the pass the keys and values into the iteratee function, which takes the result as the first argument. The second argument is the value and the 3rd is the key .