Categories
Functional Javascript

Functional JavaScript — Generators

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 JavaScript generators.

Callback Hell

If we some functions like:

let sync = () => {
  //..
}
let sync2 = () => {
  //...
}
let sync3 = () => {
  //...
}

and each function is synchronous, then we can call it one by one and compose them our way.

But if they’re async, then we can’t call one by one.

An async function may have a callback to let us call the callback when we get the result:

let async1 = (fn) => {
  //...
  fn( /* result data */ )
}
let async2 = (fn) => {
  //...
  fn( /* result data */ )
}
let async3 = (fn) => {
  //...
  fn( /* result data */ )
}

Then if we want to call them sequentially, we’ve to write something like:

async1(function(x) {
  async2(function(y) {
    async3(function(z) {
      //...
    });
  });
});

As we can see, there’s a lot of nesting in our code.

We got to make this cleaner.

Generators

We can clean up this code with generators.

To create a generator function, we can write:

function* gen() {
  return 'foo';
}

A generator function is indicated by the function* keyword.

Then we can call it to create a generator:

let generator = gen();

The generatorResult object has the next method to return the value we yielded.

The returned object has the value and done properties.

So we can write:

generator.next().value

and we get 'foo' .

Calling next for a second time will return an object with the value being undefined .

The yield keyword is a new keyword that will bring value to the next method.

The value of each yield statement will return in the sequence they’re listed.

yield pauses the execution of the function and sends back the result to the caller.

Then next time next is called, the next yield statement is run.

So if we have:

function* gen() {
  yield 'first';
  yield 'second';
  yield 'third';
}

let generator = gen();

The first generator.next() call returns:

{value: "first", done: false}

Then 2nd call returns:

{value: "second", done: false}

The 3rd call returns:

{value: "third", done: false}

The 4th call returns:

{value: undefined, done: true}

which indicates that the generator has no more values to return.

The done property indicates whether the generator bis done with returning all the values.

We know when to stop calling next once done is true .

Passing Data to Generators

We can also pass data to generators.

To do that, we create a generator function with a yield statement that has no value after it.

For example, we can write:

function* fullName() {
  const firstName = yield;
  const lastName = yield;
  console.log(`${firstName} ${lastName}`);
}

We have the yield statement without a value after it, so it’ll accept values we pass into next .

Then we can use it by writing:

const fn = fullName();
fn.next()
fn.next('mary')
fn.next('jones')

We create the generator function.

Then we call next to start the generator.

Once we did that, we can start passing values into the generator.

We call:

fn.next('mary')

to pass in a value to the first yield statement.

Then we do the same with the 2nd one with:

fn.next('jones')

Once we did that, we get 'mary jones' from the console log.

Async Code and Generators

The async and await syntax is created based on generators.

For instance, we can use it by writing:

const getData = async () => {
  const res = await fetch('https://api.agify.io/?name=michael')
  const data = await res.json();
  console.log(data);
}

We have the async and await syntax.

await pauses the execution of getData until the result is present.

So it acts like yield .

Now we run our async code line by line.

The only difference is that await only works with promises.

Conclusion

We can use generators to return items in sequence.

The function is paused after a result is returned and resumed when the next result is requested.

The async and await syntax for promises is based on the generator syntax.

Categories
Functional Javascript

Functional JavaScript — Useful Higher-Order 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 closures to create our own higher-order functions.

unary Function

We can create our own unary function that returns a function that only calls one argument.

For example, we can write:

const unary = (fn) =>
  fn.length === 1 ?
  fn :
  (arg) => fn(arg)

We have the fn which is a function.

We check the length property of fn , which returns how many parameters it has.

If it only has one parameter, then we return the fn function.

Otherwise, we return a function that calls fn with only one argument.

This way, we can use functions like parseInt with the map method safely.

For example, we can write:

const nums = ['1', '2', '3'].map(unary(parseInt));

We call the unary function with parseInt so that we can use the callback withn only of parameter to parse the string to an integer.

parseInt takes the value to parse, and the radix as the second argument, so we can’t just pass parseInt straight to map because the radix will be the index of the array entry, which isn’t what we want.

With our unary function, we always call parseInt with only the value passed in.

Therefore, nums is [1, 2, 3] .

once Function

We can create a once function to only call a function once.

For example, we can write:

const once = (fn) => {
  let done = false;
  return function(...args) {
    if (!done) {
      done = true;
      fn.apply(this, args);
    }
  }
}

We have the once function, which only runs the fn function that’s passed in when done is false .

If that’s the case, then we set done to true and call fn with apply .

apply takes the this value as the first argument and the array of arguments as the 2nd argument.

Then we can use it to only call a function once by writing:

const foo = once(() => {
  console.log("foo")
})

foo();
foo();

We call the once function with a function that we only want to call only once.

Then we can call it twice and see that 'foo' is only logged once.

Memoize

We can cache the return value of our function call by creating our own memoize function.

For example, we can write:

const memoize = (fn) => {
  const cache = {};
  return (arg) => {
    if (!cache[arg]) {
      cache[arg] = fn(arg);
    }
    return cache[arg]
  }
}

We created a memoize function that takes the fn function.

In the function, we define the cache object.

And we return a function that takes the arg argument.

We check if cache[arg] is in the cache.

If it’s not, then we set the value in the cache object.

And then we return the cached value.

Then we can use it by writing:

let fastFib = memoize((n) => {
  if (n === 0 || n === 1) {
    return 1;
  }
  return n + fastFib(n - 1);
});

We pass in our Fibonacci function to return the Fibonacci number given the value of n .

This is much faster since we can look up the past computed values from the cache object.

Conclusion

We can create our own higher-order functions to do various things with it.

Categories
Functional Javascript

Functional JavaScript — The Basics

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.

What Is Functional Programming?

Functional programming is the use of various principles in our app’s code.

The most basic principle is that we abstract out the how part into reusable code.

And we create functions that don’t depend on the outside.

Also, if the function have the same input, we get the same output.

Functions are mathematical functions.

They take arguments and return values.

The arguments we pass in will always create the same output if the arguments are the same.

Also, they don’t interact with the outside world.

For instance, we can have a function like:

const calculateTax = (value, percentValue) => {
  return value / 100 * (100 +
    percentValue)
}

It takes some arguments and doesn’t reference anything outside in the function body.

This is called a pure function.

A pure function is a function that doesn’t reference anything outside.

And if we give it the same inputs, it’ll always give the same outputs.

JavaScript Functions vs Methods

A function is a piece of code that can be called by its name.

It can pass arguments and return values.

A method is a piece of code that may be called by its name with its associated object name.

So a function is something like:

const foo = (a) => {
  return a
}

And a method is something like:

const obj = {
  foo: (a) => {
    return a
  }
}

We call the method by writing:

obj.foo(1)

Referential Transparency

Functions return the same output for the same input.

This property is called referential transparency.

If we have referential transparent, then we can infer the return value from the function call.

So if we have:

const sameVal = (i) => {
  return i
}

and:

sum(4,5) + sameVal(1)

We can infer that the expression above is the same as:

sum(4,5) + 1

The substitution model lets us substitute the direct result of a function.

This leads to parallel code and caching since they don’t depend on anything outside.

All they depend on is their argument.

Imperative, Declarative, Abstraction

Functional programming is about being declarative and writing abstracted code.

Declarative code means we tell the computer what the compiler needs to do rather than how to do it.

The how part is abstracted into higher-order functions.

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

For example, the array instance forEach method takes a callback and then log an element.

We can iterate through an array with it by writing:

const array = [1, 2, 3];
array.forEach((a) => console.log(a))

Conclusion

Functional programming follows some basic principles.

We create functions that don’t depend on the outside and if we give them the same inputs, we always get the same outputs.

Categories
Functional Javascript

Functional JavaScript — Higher-Order Functions in the Real World

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 higher-order functions.

Higher-Order Functions in the Real World

Higher-order functions are used in the real world a lot.

For example, arrays have many instance methods that are higher-order functions.

One of them is the every method.

every takes a callback that returns the boolean expression to check if each item is what we’re looking for.

For example, we can use it by writing:

const allEven = [1, 2, 3].every(a => a % 2 === 0);

We pass in a callback to check if each entry is evenly divisible by 2.

This should return false since we have 1 and 3 which are odd.

Also, the every method can be implemented with our own code:

const every = (arr, fn) => {
  for (const a of arr) {
    if (!fn(a)) {
      return false;
    }
  }
  return true;
}

We loop through the entries of arr and then call fn to check if the entry matches the given condition.

If it does, then we return false since we have at least one item that doesn’t match the given we have in the callback.

We can use it by writing:

const allEven = every([1, 2, 3], a => a % 2 === 0)

And allEven should be false .

some Function

The some method is similar to every .

It’s also part of the array instance.

For example, we can call the array instance’s some method by writing:

const hasEven = [1, 2, 3].some(a => a % 2 === 0)

We call the some method on the array.

The callback returns the condition and that we’re looking for.

It checks if at least one item matches the given condition.

Therefore, hasEven should be true since 2 is even.

Also, we can implement it in our own way.

For example, we can write:

const some = (arr, fn) => {
  for (const a of arr) {
    if (fn(a)) {
      return true;
    }
  }
  return false;
}

We loop through the items and check if fn(a) returns true .

If one does, then we return true .

Otherwise, we return false .

We can call our own some function by writing:

const hasEven = some([1, 2, 3], a => a % 2 === 0)

then we get true .

We pass in the array and the callback function that returns the function we’re checking for.

sort

The array instance sort method takes a function that lets us compare 2 entries and sort them.

The callback takes 2 parameters, which are 2 entries of the array.

If the first parameter should come before the second, then we return a negative number.

If we keep the same order, then we return 0.

Otherwise, we return a positive number.

We can improve this by creating a function that returns a comparator function.

For example, we can write:

const sortBy = (property) => {
  return (a, b) => a[property] - b[property];
}

const arr = [{
    foo: 3
  },
  {
    foo: 1
  },
  {
    foo: 2
  }
]

const sorted = arr.sort(sortBy('foo'));
console.log(sorted);

We have the sortBy function that returns a function to let us compare a property value.

Then we call arr.sort with our sortBy function, which returns the comparator function for the property we want.

Then sorted should be:

[
  {
    "foo": 1
  },
  {
    "foo": 2
  },
  {
    "foo": 3
  }
]

We can see the items are sorted.

Conclusion

We can implement various array methods our way.

There are many applications of higher-order functions in the real world.

Categories
Functional Javascript

Functional JavaScript — Higher-Order 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 higher-order functions.

Higher-Order Functions

Higher-order functions are functions that take other functions as arguments and return a function.

It also takes other data and let us manipulate them.

JavaScript Data Types

JavaScript has several data types.

They include numbers, strings, booleans, objects, null and undefined .

Functions are data types like strings.

We can pass them around, store them as variables, etc.

This means they act like any other data type.

Storing a Function

We can store a function in a variable.

For example, we can write:

let fn = () => {}

Then we can check its type by using the typeof operator:

typeof fn

We should get 'function' returned with that.

Passing a Function

Functions can have parameters.

So we can write:

const getType = (arg) => {
  console.log(typeof arg)
}

We get the type by using the typeof operator from the arg .

We can also make our function call a function that’s passed in.

To do that, we can check if we passed in a function to our function.

For example, we can write:

const getType = (arg) => {
  if (typeof arg === "function") {
    arg()
  } else {
    console.log(arg)
  }
}

to check if arg is a function.

If it’s a function, we call it.

Otherwise, we log its value.

Returning a Function

We can return a function inside a function.

For instance, we can write:

let crazy = () => {
  return Number
}

We return the built-in Number function in our function.

Also, we can call the returned function.

So we can write:

let fn = crazy();
fn("abc");

We call the function returned by crazy .

Then we call fn and return the value that it returns.

Abstraction and Higher-Order Functions

We can abstract the higher-order functions by getting the function from the parameter and calling it.

For example, we can write:

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

fn is a function, so we can call it.

We loop through the array array and call fn with each entry of array as an argument.

Then we can use it by writing:

forEach([1, 2, 3], (data) => {
  //...
})

We have the array as the first argument.

The 2nd argument is a function that we call on each item.

forEach traverses the array and do what we want with it.

Also, we can do the same with an object by writing:

const forEachObj = (obj, fn) => {
  for (const [key, value] of Object.entries(obj)) {
    fn(key, value);
  }
}

forEach({
  a: 1,
  b: 2,
  c: 3
}, (key, value) => {
  //...
})

We created the forEachObj function which takes an object and a function as parameters.

Then we loop through the key-value pairs with the Object.entries method and call the fn function on each key and value .

Conclusion

We can create higher-order function getting a function and then calling it with a function.

This can be done easily for code that traverses arrays and objects.