• Jump To … +
    underscore.array.builders.js underscore.array.selectors.js underscore.function.arity.js underscore.function.combinators.js underscore.function.iterators.js underscore.function.predicates.js underscore.object.builders.js underscore.object.selectors.js underscore.util.existential.js underscore.util.strings.js underscore.util.trampolines.js
  • underscore.function.combinators.js

  • ¶

    Underscore-contrib (underscore.function.combinators.js 0.0.1) (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors Underscore-contrib may be freely distributed under the MIT license.

    (function(root) {
  • ¶

    Baseline setup

  • ¶

    Establish the root object, window in the browser, or global on the server.

      var _ = root._ || require('underscore');
  • ¶

    Helpers

      var existy = function(x) { return x != null; };
      var truthy = function(x) { return (x !== false) && existy(x); };
      var __reverse = [].reverse;
      var __slice = [].slice;
      
  • ¶

    Mixing in the combinator functions

      _.mixin({
  • ¶

    Takes a value and returns a function that always returns said value.

        always: function(value) {
          return function() { return value; };
        },
  • ¶

    Takes some value as its first argument and runs it through a pipeline of functions given as the rest arguments.

        pipeline: function(/*, funs */){
          var funs = arguments;
    
          return function(seed) {
            return _.reduce(funs,
                            function(l,r) { return r(l); },
                            seed);
          };
        },
  • ¶

    Composes a bunch of predicates into a single predicate that checks all elements of an array for conformance to all of the original predicates.

        conjoin: function(/* preds */) {
          var preds = arguments;
    
          return function(array) {
            return _.every(array, function(e) {
              return _.every(preds, function(p) {
                return p(e);
              });
            });
          };
        },
  • ¶

    Composes a bunch of predicates into a single predicate that checks all elements of an array for conformance to any of the original predicates.

        disjoin: function(/* preds */) {
          var preds = arguments;
    
          return function(array) {
            return _.some(array, function(e) {
              return _.some(preds, function(p) {
                return p(e);
              });
            });
          };
        },
  • ¶

    Takes a predicate-like and returns a comparator (-1,0,1).

        comparator: function(fun) {
          return function(x, y) {
            if (truthy(fun(x, y)))
              return -1;
            else if (truthy(fun(y, x)))
              return 1;
            else
              return 0;
          };
        },
  • ¶

    Returns a function that reverses the sense of a given predicate-like.

        complement: function(pred) {
          return function() {
            return !pred.apply(null, arguments);
          };
        },
  • ¶

    Takes a function expecting varargs and returns a function that takes an array and uses its elements as the args to the original function

        splat: function(fun) {
          return function(array) {
            return fun.apply(null, array);
          };
        },
  • ¶

    Takes a function expecting an array and returns a function that takes varargs and wraps all in an array that is passed to the original function.

        unsplat: function(fun) {
          var funLength = fun.length;
    
          if (funLength < 1) {
            return fun;
          }
          else if (funLength === 1)  {
            return function () {
              return fun.call(this, __slice.call(arguments, 0))
            }
          }
          else {
            return function () {
              var numberOfArgs = arguments.length,
                  namedArgs = __slice.call(arguments, 0, funLength - 1),
                  numberOfMissingNamedArgs = Math.max(funLength - numberOfArgs - 1, 0),
                  argPadding = new Array(numberOfMissingNamedArgs),
                  variadicArgs = __slice.call(arguments, fun.length - 1);
    
              return fun.apply(this, namedArgs.concat(argPadding).concat([variadicArgs]))
            }
          }
        },
  • ¶

    Returns a function that returns an array of the calls to each given function for some arguments.

        juxt: function(/* funs */) {
          var funs = arguments;
    
          return function(arg) {
            return _.map(funs, function(f) {
              return f(arg);
            });
          };
        },
  • ¶

    Returns a function that protects a given function from receiving non-existy values. Each subsequent value provided to fnull acts as the default to the original function should a call receive non-existy values in the defaulted arg slots.

        fnull: function(fun /*, defaults */) {
          var defaults = _.rest(arguments);
    
          return function(/*args*/) {
            var args = _.toArray(arguments);
            var sz = _.size(defaults);
    
            for(var i = 0; i < sz; i++) {
              if (!existy(args[i]))
                args[i] = defaults[i];
            }
    
            return fun.apply(null, args);
          };
        },
  • ¶

    Flips the first two args of a function

        flip2: function(fun) {
          return function(/* args */) {
            var tmp = arguments[0];
            arguments[0] = arguments[1];
            arguments[1] = tmp;
    
            return fun.apply(null, arguments);
          };
        },
  • ¶

    Flips an arbitrary number of args of a function

        flip: function(fun) {
          return function(/* args */) {
            var reversed = __reverse.call(arguments);
    
            return fun.apply(null, reversed);
          };
        },
        
        k: _.always,
        t: _.pipeline
      });
    
    })(this);