Categories
Functional Javascript

Functional JavaScript — Piping and Functors

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 pipe functions and functors with JavaScript.

Pipe

We can create a pipe function by creating a function that takes an array of functions as arguments.

It returns a function that takes a value and we call reduce on it with that calls fn with acc .

For example, we can write:

const compose = (...fns) =>
  (value) =>
  fns.reduceRight((acc, fn) => fn(acc), value)

The only difference is that we used reduceRight instead of reduce so that we don’t have to call reverse to apply all the functions.

Composition is Associative

Composition is associative, this means we can rearrange the parentheses of our operations

For instance:

compose(f, compose(g, h)) == compose(compose(f, g), h)

returns true .

Functors

Functor is a plain object that implements the function map while running River each value to produce a new object.

A functor is a container that holds some value in it.

For example, we can write:

const Container = function(val) {
  this.value = val;
}

to create our container.

Then we can use new to invoke the Container constructor:

let foo = new Container(3);

We can create a Container.of property to add a container to let us return a Container instance:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}

We added the of static method to return a Container instance.

The of method just gives us an alternative to using the new operator to create the Container instance.

Then we can create a Container instance with the of method:

const nested = Container.of(Container.of(1));

Then we’ll see the nested Container instances.

Functor Implements Method Called map

Functors implement the map method.

We can add it as an instance method by adding it to the prototype property:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}

Container.prototype.map = function(fn) {
  return Container.of(fn(this.value));
}

Then we can use the map method after we create a Container instance.

For instance, we can use it by writing:

const squared = Container.of(3).map(a => a ** 2);

Then squared is a Container instance with value being 9.

We call map repeatedly to repeat an operation.

So we can write:

const squared = Container.of(3)
  .map(square)
  .map(square)
  .map(square);

Then squared is a Container instance with value being 6561.

Functor is just an object that implements a map method.

Conclusion

Functors are plain objects that have value.

The object has a map method.

We can pipe functions to call multiple functions and get the returned value.

Composition is associative, so we can rearrange the parentheses of our operations.

Categories
Functional Javascript

Functional JavaScript — Partial Application and Composition

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 partial application and composition of functions with JavaScript.

Partial Application

Partial application is where we only apply some of the arguments that are expected in a function.

For example, if we have a function with 3 parameters:

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

Then we can create a function that has the add function with arguments partially applied by writing:

const add1 = (y, z) => add(1, y, z);

Then we can use it by writing:

const sum = add1(2, 3);

And we get 6.

To generalize this, we can write:

const partial = function(fn, ...partialArgs) {
  let args = partialArgs;
  return function(...fullArguments) {
    return fn(...[...partialArgs, ...fullArguments]);
  };
};

We create our own partial function by returning a function with the partialArgs and fullArguments spread as arguments into the fn function.

Then we can use it by writing:

const sum = partial(add, 1)(2, 3);

and sum is 6 again.

Currying vs. Partial Application

Currying is good whenever we need to convert functions that take multiple arguments to multiple functions that take one argument.

Situations where we need to convert a function that takes multiple arguments to a callback for map that only takes one parameter an example of that.

Partial application of a function is useful for any situation where we need to apply one or arguments to a function and return a function that has the arguments applied.

Composition

Composition is where we chain multiple function calls to return the result that we want.

We have many functions that do one thing, and we combine them into one so that we can get the result we want.

For instance, we can compose the array map and filter methods by writing:

const arr = [1, 2, 3]
  .filter(a => a % 2 === 1)
  .map(a => a ** 2);

And arr is [1, 9] .

We call filter to return an array with only the odd numbers.

And then we call map to square each odd number.

compose Function

We can generalize the compose function by writing:

const compose = (fn1, fn2) =>
  (c) => fn1(fn2(c))

Our function takes 2 functions as parameters and then we return a function that calls one after the other.

fn2 is called first, then fn1 is called on the result returned by fn2 .

Then we can use it by writing:

let number = compose(Math.round, parseFloat)('10.1')

We called compose with Math.round and parseFloat .

parseFloat is called first with '10.1' and then Math.round is called on the returned result.

Then number is 10.

Compose Many Functions

We can create a general version of the compose function by using the array reduce method.

For example, we can write:

const compose = (...fns) =>
  (value) =>
  fns.reverse().reduce((acc, fn) => fn(acc), value)

We created a function which takes an array of functions fns as a parameter.

Then we return a function that takes a value as the initial value and call reduce on it to call each function in the array with the returned result.

acc is the returned result from calling the functions so far, and fn is the function.

And then we can use it by writing:

let splitIntoSpaces = (str) => str.split(" ");
let count = (array) => array.length;
const countWords = compose(count, splitIntoSpaces)('foo bar baz');

We split the string by the space with splitIntoSpaces function.

And we get the length of the split string array with the count function.

And then we use compose to combine them together.

Once we call the returned function with a string, we get the number words separated by a space.

So countWords is 3.

Conclusion

We can partially apply and compose functions with JavaScript.

Partial application lets us call functions with some arguments applied.

And composition lets us call multiple functions in a chain.

Categories
Functional Javascript

Functional JavaScript — Monads

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 pipe functions and functors with JavaScript.

MayBe Functors

A MayBe functor is one that lets us implement a map function in a different way.

We start off by creating a constructor that stores a value:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

Then we add the methods unique to the MayBe functor.

We have the isNothing method to check if this.value has anything.

The map method will return something different depending on whether this.value has something or not.

We add:

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

Together, we have:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

Then we can use it by writing:

const str = MayBe.of("foo").map((x) => x.toUpperCase())

Then we get the the value property of the MayBe instance is 'FOO' .

If this.value is null or undefined , then map will return a MayBe functor with value being null .

So if we have something like:

const str = MayBe.of("james")
  .map(() => undefined)
  .map((x) => `Mr. ${x}`)

We’ll get the final value of value being null instead of throwing an error.

Either Functor

The Either functor allows us to solve problems with branches.

We create a Nothing or Some functor and out them in an object.

So we write:

const Nothing = function(val) {
  this.value = val;
};

Nothing.of = function(val) {
  return new Nothing(val);
};

Nothing.prototype.map = function(f) {
  return this;
};

const Some = function(val) {
  this.value = val;
};

Some.of = function(val) {
  return new Some(val);
};

Some.prototype.map = function(fn) {
  return Some.of(fn(this.value));
}

Now if want to hold some data, then we can use the Some functor.

Otherwise, we use the Nothing functor to hold some non-existent value.

Monads

A monad is a functor with a chain method.

The chain method calls a join method to call it return an a MayBe instance if this.value has a value.

For example, we can write:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

MayBe.prototype.join = function() {
  return this.isNothing() ? MayBe.of(null) : this.value;
}

MayBe.prototype.chain = function(f) {
  return this.map(f).join()
}

The join method checks if this.value is null or undefined .

If it is, then we return a null MayBe functor.

Otherwise, we return this.value .

chain just calls map and join together.

This way, if we map something to null , then it stays null .

Then we can use this by writing:

let mayBe = MayBe.of({
  data: [{
    title: 'foo',
    children: [{
      bar: 2
    }]
  }]
})

let ans = mayBe.map((arr) => arr.data)
  .chain((obj) => map(obj, (x) => {
    return {
      title: x.title
    }
  }))

then we get the title from the object we passed into of .

Conclusion

A monad is a functor that has the chain method, which does the mapping and joining together.

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.