• 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.iterators.js

  • ¶

    Underscore-contrib (underscore.function.iterators.js 0.0.1) (c) 2013 Michael Fogus and DocumentCloud Inc. 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 HASNTBEENRUN = {};
      
      function unary (fun) {
        return function (first) {
          return fun.call(this, first);
        };
      }
      
      function binary (fun) {
        return function (first, second) {
          return fun.call(this, first, second);
        };
      }
      
      var undefined = void 0;
    
      
  • ¶

    Mixing in the iterator functions

         function foldl (iter, binaryFn, seed) {
          var state, element;
          if (seed !== void 0) {
            state = seed;
          }
          else {
            state = iter();
          }
          element = iter();
          while (element != null) {
            state = binaryFn.call(element, state, element);
            element = iter();
          }
          return state;
        };
      
        function unfold (seed, unaryFn) {
          var state = HASNTBEENRUN;
          return function () {
            if (state === HASNTBEENRUN) {
              return (state = seed);
            }
            else if (state != null) {
              return (state = unaryFn.call(state, state));
            }
            else return state;
          };
        };
      
  • ¶

    note that the unfoldWithReturn behaves differently than unfold with respect to the first value returned

        function unfoldWithReturn (seed, unaryFn) {
          var state = seed,
              pair,
              value;
          return function () {
            if (state != null) {
              pair = unaryFn.call(state, state);
              value = pair[1];
              state = value != null
                      ? pair[0]
                      : void 0
              return value;
            }
            else return void 0;
          };
        };
    
        function accumulate (iter, binaryFn, initial) {
          var state = initial;
          return function () {
            element = iter();
            if (element == null) {
              return element;
            }
            else {
              if (state === void 0) {
                return (state = element);
              }
              else return (state = binaryFn.call(element, state, element));
            }
          }
        };
      
        function accumulateWithReturn (iter, binaryFn, initial) {
          var state = initial,
              stateAndReturnValue;
          return function () {
            element = iter();
            if (element == null) {
              return element;
            }
            else {
              if (state === void 0) {
                return (state = element);
              }
              else {
                stateAndReturnValue = binaryFn.call(element, state, element);
                state = stateAndReturnValue[0];
                return stateAndReturnValue[1];
              }
            }
          }
        };
      
        function map (iter, unaryFn) {
          return function() {
            var element;
            element = iter();
            if (element != null) {
              return unaryFn.call(element, element);
            } else {
              return void 0;
            }
          };
        };
    
        function select (iter, unaryPredicateFn) {
          return function() {
            var element;
            element = iter();
            while (element != null) {
              if (unaryPredicateFn.call(element, element)) {
                return element;
              }
              element = iter();
            }
            return void 0;
          };
        };
      
        function reject (iter, unaryPredicateFn) {
          return select(iter, function (something) {
            return !unaryPredicateFn(something);
          });
        };
      
        function find (iter, unaryPredicateFn) {
          return select(iter, unaryPredicateFn)();
        }
    
        function slice (iter, numberToDrop, numberToTake) {
          var count = 0;
          while (numberToDrop-- > 0) {
            iter();
          }
          if (numberToTake != null) {
            return function() {
              if (++count <= numberToTake) {
                return iter();
              } else {
                return void 0;
              }
            };
          }
          else return iter;
        };
      
        function drop (iter, numberToDrop) {
          return slice(iter, numberToDrop == null ? 1 : numberToDrop);
        }
      
        function take (iter, numberToTake) {
          return slice(iter, 0, numberToTake == null ? 1 : numberToTake);
        }
    
        function List (array) {
          var index = 0;
          return function() {
            return array[index++];
          };
        };
      
        function Tree (array) {
          var index, myself, state;
          index = 0;
          state = [];
          myself = function() {
            var element, tempState;
            element = array[index++];
            if (element instanceof Array) {
              state.push({
                array: array,
                index: index
              });
              array = element;
              index = 0;
              return myself();
            } else if (element === void 0) {
              if (state.length > 0) {
                tempState = state.pop(), array = tempState.array, index = tempState.index;
                return myself();
              } else {
                return void 0;
              }
            } else {
              return element;
            }
          };
          return myself;
        };
      
        function K (value) {
          return function () {
            return value;
          };
        };
    
        function upRange (from, to, by) {
          return function () {
            var was;
          
            if (from > to) {
              return void 0;
            }
            else {
              was = from;
              from = from + by;
              return was;
            }
          }
        };
    
        function downRange (from, to, by) {
          return function () {
            var was;
          
            if (from < to) {
              return void 0;
            }
            else {
              was = from;
              from = from - by;
              return was;
            }
          }
        };
      
        function range (from, to, by) {
          if (from == null) {
            return upRange(1, Infinity, 1);
          }
          else if (to == null) {
            return upRange(from, Infinity, 1);
          }
          else if (by == null) {
            if (from <= to) {
              return upRange(from, to, 1);
            }
            else return downRange(from, to, 1)
          }
          else if (by > 0) {
            return upRange(from, to, by);
          }
          else if (by < 0) {
            return downRange(from, to, Math.abs(by))
          }
          else return k(from);
        };
      
        var numbers = unary(range);
    
        _.iterators = {
          accumulate: accumulate,
          accumulateWithReturn: accumulateWithReturn,
          foldl: foldl,
          reduce: foldl,
          unfold: unfold,
          unfoldWithReturn: unfoldWithReturn,
          map: map,
          select: select,
          reject: reject,
          filter: select,
          find: find,
          slice: slice,
          drop: drop,
          take: take,
          List: List,
          Tree: Tree,
          constant: K,
          K: K,
          numbers: numbers,
          range: range
        };
    
    })(this);