## Function

#### attempt

Attempts to invoke a function with the provided arguments, returning either the result or the caught error object.

Use a `try... catch` block to return either the result of the function or an appropriate error.

    const attempt = (fn, ...args) => {
      try {
        return fn(...args);
      } catch (e) {
        return e instanceof Error ? e : new Error(e);
      }
    };

examples

    var elements = attempt(function(selector) {
      return document.querySelectorAll(selector);
    }, '>_>');
    if (elements instanceof Error) elements = []; // elements = []

#### bind

Creates a function that invokes `fn` with a given context, optionally adding any additional supplied parameters to the beginning of the arguments.

Return a `function` that uses `Function.prototype.apply()` to apply the given `context` to `fn`. Use `Array.prototype.concat()` to prepend any additional supplied parameters to the arguments.

    const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);

examples

    function greet(greeting, punctuation) {
      return greeting + ' ' + this.user + punctuation;
    }
    const freddy = { user: 'fred' };
    const freddyBound = bind(greet, freddy);
    console.log(freddyBound('hi', '!')); // 'hi fred!'

#### bindKey

Creates a function that invokes the method at a given key of an object, optionally adding any additional supplied parameters to the beginning of the arguments.

Return a `function` that uses `Function.prototype.apply()` to bind `context[fn]` to `context`. Use the spread operator (`...`) to prepend any additional supplied parameters to the arguments.

    const bindKey = (context, fn, ...boundArgs) => (...args) =>
      context[fn].apply(context, [...boundArgs, ...args]);

examples

    const freddy = {
      user: 'fred',
      greet: function(greeting, punctuation) {
        return greeting + ' ' + this.user + punctuation;
      }
    };
    const freddyBound = bindKey(freddy, 'greet');
    console.log(freddyBound('hi', '!')); // 'hi fred!'

#### chainAsync

Chains asynchronous functions.

Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed.

    const chainAsync = fns => {
      let curr = 0;
      const next = () => fns[curr++](next);
      next();
    };

examples

    chainAsync([
      next => {
        console.log('0 seconds');
        setTimeout(next, 1000);
      },
      next => {
        console.log('1 second');
      }
    ]);

#### compose

Performs right-to-left function composition.

Use `Array.prototype.reduce()` to perform right-to-left function composition. The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

    const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));

examples

    const add5 = x => x + 5;
    const multiply = (x, y) => x * y;
    const multiplyAndAdd5 = compose(
      add5,
      multiply
    );
    multiplyAndAdd5(5, 2); // 15

#### composeRight

Performs left-to-right function composition.

Use `Array.prototype.reduce()` to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

    const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));

examples

    const add = (x, y) => x + y;
    const square = x => x * x;
    const addAndSquare = composeRight(add, square);
    addAndSquare(1, 2); // 9

#### converge

Accepts a converging function and a list of branching functions and returns a function that applies each branching function to the arguments and the results of the branching functions are passed as arguments to the converging function.

Use `Array.prototype.map()` and `Function.prototype.apply()` to apply each function to the given arguments. Use the spread operator (`...`) to call `coverger` with the results of all other functions.

    const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));

examples

    const average = converge((a, b) => a / b, [
      arr => arr.reduce((a, v) => a + v, 0),
      arr => arr.length
    ]);
    average([1, 2, 3, 4, 5, 6, 7]); // 4

#### curry

Curries a function.

Use recursion. If the number of provided arguments (`args`) is sufficient, call the passed function `fn`. Otherwise, return a curried function `fn` that expects the rest of the arguments. If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. `Math.min()`), you can optionally pass the number of arguments to the second parameter `arity`.

    const curry = (fn, arity = fn.length, ...args) =>
      arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);

examples

    curry(Math.pow)(2)(10); // 1024
    curry(Math.min, 3)(10)(50)(2); // 2

#### debounce

Creates a debounced function that delays invoking the provided function until at least `ms` milliseconds have elapsed since the last time it was invoked.

Each time the debounced function is invoked, clear the current pending timeout with `clearTimeout()` and use `setTimeout()` to create a new timeout that delays invoking the function until at least `ms` milliseconds has elapsed. Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary arguments. Omit the second argument, `ms`, to set the timeout at a default of 0 ms.

    const debounce = (fn, ms = 0) => {
      let timeoutId;
      return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn.apply(this, args), ms);
      };
    };

examples

    window.addEventListener(
      'resize',
      debounce(() => {
        console.log(window.innerWidth);
        console.log(window.innerHeight);
      }, 250)
    ); // Will log the window dimensions at most every 250ms

#### defer

Defers invoking a function until the current call stack has cleared.

Use `setTimeout()` with a timeout of 1ms to add a new event to the browser event queue and allow the rendering engine to complete its work. Use the spread (`...`) operator to supply the function with an arbitrary number of arguments.

    const defer = (fn, ...args) => setTimeout(fn, 1, ...args);

examples

    // Example A:
    defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'

    // Example B:
    document.querySelector('#someElement').innerHTML = 'Hello';
    longRunningFunction(); // Browser will not update the HTML until this has finished
    defer(longRunningFunction); // Browser will update the HTML then run the function

#### delay

Invokes the provided function after `wait` milliseconds.

Use `setTimeout()` to delay execution of `fn`. Use the spread (`...`) operator to supply the function with an arbitrary number of arguments.

    const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);

examples

    delay(
      function(text) {
        console.log(text);
      },
      1000,
      'later'
    ); // Logs 'later' after one second.

#### functionName

Logs the name of a function.

Use `console.debug()` and the `name` property of the passed method to log the method's name to the `debug` channel of the console.

    const functionName = fn => (console.debug(fn.name), fn);

examples

    functionName(Math.max); // max (logged in debug channel of console)

#### hz

Returns the number of times a function executed per second. `hz` is the unit for `hertz`, the unit of frequency defined as one cycle per second.

Use `performance.now()` to get the difference in milliseconds before and after the iteration loop to calculate the time elapsed executing the function `iterations` times. Return the number of cycles per second by converting milliseconds to seconds and dividing it by the time elapsed. Omit the second argument, `iterations`, to use the default of 100 iterations.

    const hz = (fn, iterations = 100) => {
      const before = performance.now();
      for (let i = 0; i < iterations; i++) fn();
      return (1000 * iterations) / (performance.now() - before);
    };

examples

    // 10,000 element array
    const numbers = Array(10000)
      .fill()
      .map((_, i) => i);

    // Test functions with the same goal: sum up the elements in the array
    const sumReduce = () => numbers.reduce((acc, n) => acc + n, 0);
    const sumForLoop = () => {
      let sum = 0;
      for (let i = 0; i < numbers.length; i++) sum += numbers[i];
      return sum;
    };

    // `sumForLoop` is nearly 10 times faster
    Math.round(hz(sumReduce)); // 572
    Math.round(hz(sumForLoop)); // 4784

#### memoize

Returns the memoized (cached) function.

Create an empty cache by instantiating a new `Map` object. Return a function which takes a single argument to be supplied to the memoized function by first checking if the function's output for that specific input value is already cached, or store and return it if not. The `function` keyword must be used in order to allow the memoized function to have its `this` context changed if necessary. Allow access to the `cache` by setting it as a property on the returned function.

    const memoize = fn => {
      const cache = new Map();
      const cached = function(val) {
        return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
      };
      cached.cache = cache;
      return cached;
    };

examples

    // See the `anagrams` snippet.
    const anagramsCached = memoize(anagrams);
    anagramsCached('javascript'); // takes a long time
    anagramsCached('javascript'); // returns virtually instantly since it's now cached
    console.log(anagramsCached.cache); // The cached anagrams map

#### negate

Negates a predicate function.

Take a predicate function and apply the not operator (`!`) to it with its arguments.

    const negate = func => (...args) => !func(...args);

examples

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

#### once

Ensures a function is called only once.

Utilizing a closure, use a flag, `called`, and set it to `true` once the function is called for the first time, preventing it from being called again. In order to allow the function to have its `this` context changed (such as in an event listener), the `function` keyword must be used, and the supplied function must have the context applied. Allow the function to be supplied with an arbitrary number of arguments using the rest/spread (`...`) operator.

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

examples

    const startApp = function(event) {
      console.log(this, event); // document.body, MouseEvent
    };
    document.body.addEventListener('click', once(startApp)); // only runs `startApp` once upon click

#### partial

Creates a function that invokes `fn` with `partials` prepended to the arguments it receives.

Use the spread operator (`...`) to prepend `partials` to the list of arguments of `fn`.

    const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);

examples

    const greet = (greeting, name) => greeting + ' ' + name + '!';
    const greetHello = partial(greet, 'Hello');
    greetHello('John'); // 'Hello John!'

#### partialRight

Creates a function that invokes `fn` with `partials` appended to the arguments it receives.

Use the spread operator (`...`) to append `partials` to the list of arguments of `fn`.

    const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);

examples

    const greet = (greeting, name) => greeting + ' ' + name + '!';
    const greetJohn = partialRight(greet, 'John');
    greetJohn('Hello'); // 'Hello John!'

#### runPromisesInSeries

Runs an array of promises in series.

Use `Array.prototype.reduce()` to create a promise chain, where each promise returns the next promise when resolved.

    const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());

examples

    const delay = d => new Promise(r => setTimeout(r, d));
    runPromisesInSeries([() => delay(1000), () => delay(2000)]); // Executes each promise sequentially, taking a total of 3 seconds to complete

#### sleep

Delays the execution of an asynchronous function.

Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`.

    const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

examples

    async function sleepyWork() {
      console.log("I'm going to sleep for 1 second.");
      await sleep(1000);
      console.log('I woke up after 1 second.');
    }

#### throttle

Creates a throttled function that only invokes the provided function at most once per every `wait` milliseconds

Use `setTimeout()` and `clearTimeout()` to throttle the given method, `fn`. Use `Function.prototype.apply()` to apply the `this` context to the function and provide the necessary `arguments`. Use `Date.now()` to keep track of the last time the throttled function was invoked. Omit the second argument, `wait`, to set the timeout at a default of 0 ms.

    const throttle = (fn, wait) => {
      let inThrottle, lastFn, lastTime;
      return function() {
        const context = this,
          args = arguments;
        if (!inThrottle) {
          fn.apply(context, args);
          lastTime = Date.now();
          inThrottle = true;
        } else {
          clearTimeout(lastFn);
          lastFn = setTimeout(function() {
            if (Date.now() - lastTime >= wait) {
              fn.apply(context, args);
              lastTime = Date.now();
            }
          }, Math.max(wait - (Date.now() - lastTime), 0));
        }
      };
    };

examples

    window.addEventListener(
      'resize',
      throttle(function(evt) {
        console.log(window.innerWidth);
        console.log(window.innerHeight);
      }, 250)
    ); // Will log the window dimensions at most every 250ms

#### times

Iterates over a callback `n` times

Use `Function.call()` to call `fn` `n` times or until it returns `false`. Omit the last argument, `context`, to use an `undefined` object (or the global object in non-strict mode).

    const times = (n, fn, context = undefined) => {
      let i = 0;
      while (fn.call(context, i) !== false && ++i < n) {}
    };

examples

    var output = '';
    times(5, i => (output += i));
    console.log(output); // 01234

#### uncurry

Uncurries a function up to depth `n`.

Return a variadic function. Use `Array.prototype.reduce()` on the provided arguments to call each subsequent curry level of the function. If the `length` of the provided arguments is less than `n` throw an error. Otherwise, call `fn` with the proper amount of arguments, using `Array.prototype.slice(0, n)`. Omit the second argument, `n`, to uncurry up to depth `1`.

    const uncurry = (fn, n = 1) => (...args) => {
      const next = acc => args => args.reduce((x, y) => x(y), acc);
      if (n > args.length) throw new RangeError('Arguments too few!');
      return next(fn)(args.slice(0, n));
    };

examples

    const add = x => y => z => x + y + z;
    const uncurriedAdd = uncurry(add, 3);
    uncurriedAdd(1, 2, 3); // 6

#### unfold

Builds an array, using an iterator function and an initial seed value.

Use a `while` loop and `Array.prototype.push()` to call the function repeatedly until it returns `false`. The iterator function accepts one argument (`seed`) and must always return an array with two elements ([`value`, `nextSeed`]) or `false` to terminate.

    const unfold = (fn, seed) => {
      let result = [],
        val = [null, seed];
      while ((val = fn(val[1]))) result.push(val[0]);
      return result;
    };

examples

    var f = n => (n > 50 ? false : [-n, n + 10]);
    unfold(f, 10); // [-10, -20, -30, -40, -50]

#### when

Tests a value, `x`, against a predicate function. If `true`, return `fn(x)`. Else, return `x`.

Return a function expecting a single value, `x`, that returns the appropriate value based on `pred`.

    const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);

examples

    const doubleEvenNumbers = when(x => x % 2 === 0, x => x * 2);
    doubleEvenNumbers(2); // 4
    doubleEvenNumbers(1); // 1