UNPKG

@ramda/droplast

Version:

R.dropLast exported as a module

363 lines (340 loc) 11.8 kB
// Ramda v0.26.1 // https://github.com/ramda/ramda // (c) 2013-2019 Scott Sauyet, Michael Hurley, and David Chambers // Ramda may be freely distributed under the MIT license. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.R = {}))); }(this, (function (exports) { 'use strict'; function _isPlaceholder(a) { return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true; } /** * Optimized internal one-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry1(fn) { return function f1(a) { if (arguments.length === 0 || _isPlaceholder(a)) { return f1; } else { return fn.apply(this, arguments); } }; } /** * Optimized internal two-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry2(fn) { return function f2(a, b) { switch (arguments.length) { case 0: return f2; case 1: return _isPlaceholder(a) ? f2 : _curry1(function(_b) { return fn(a, _b); }); default: return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function(_a) { return fn(_a, b); }) : _isPlaceholder(b) ? _curry1(function(_b) { return fn(a, _b); }) : fn(a, b); } }; } /** * Tests whether or not an object is an array. * * @private * @param {*} val The object to test. * @return {Boolean} `true` if `val` is an array, `false` otherwise. * @example * * _isArray([]); //=> true * _isArray(null); //=> false * _isArray({}); //=> false */ var _isArray = Array.isArray || function _isArray(val) { return (val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]'); }; function _isTransformer(obj) { return obj != null && typeof obj['@@transducer/step'] === 'function'; } /** * Returns a function that dispatches with different strategies based on the * object in list position (last argument). If it is an array, executes [fn]. * Otherwise, if it has a function with one of the given method names, it will * execute that function (functor case). Otherwise, if it is a transformer, * uses transducer [xf] to return a new transformer (transducer case). * Otherwise, it will default to executing [fn]. * * @private * @param {Array} methodNames properties to check for a custom implementation * @param {Function} xf transducer to initialize if object is transformer * @param {Function} fn default ramda implementation * @return {Function} A function that dispatches on object in list position */ function _dispatchable(methodNames, xf, fn) { return function() { if (arguments.length === 0) { return fn(); } var args = Array.prototype.slice.call(arguments, 0); var obj = args.pop(); if (!_isArray(obj)) { var idx = 0; while (idx < methodNames.length) { if (typeof obj[methodNames[idx]] === 'function') { return obj[methodNames[idx]].apply(obj, args); } idx += 1; } if (_isTransformer(obj)) { var transducer = xf.apply(null, args); return transducer(obj); } } return fn.apply(this, arguments); }; } function _reduced(x) { return x && x['@@transducer/reduced'] ? x : { '@@transducer/value': x, '@@transducer/reduced': true }; } var _xfBase = { init: function() { return this.xf['@@transducer/init'](); }, result: function(result) { return this.xf['@@transducer/result'](result); } }; function XTake(n, xf) { this.xf = xf; this.n = n; this.i = 0; } XTake.prototype['@@transducer/init'] = _xfBase.init; XTake.prototype['@@transducer/result'] = _xfBase.result; XTake.prototype['@@transducer/step'] = function(result, input) { this.i += 1; var ret = this.n === 0 ? result : this.xf['@@transducer/step'](result, input); return this.n >= 0 && this.i >= this.n ? _reduced(ret) : ret; }; var _xtake = _curry2(function _xtake(n, xf) { return new XTake(n, xf); }); /** * This checks whether a function has a [methodname] function. If it isn't an * array it will execute that function otherwise it will default to the ramda * implementation. * * @private * @param {Function} fn ramda implemtation * @param {String} methodname property to check for a custom implementation * @return {Object} Whatever the return value of the method is. */ function _checkForMethod(methodname, fn) { return function() { var length = arguments.length; if (length === 0) { return fn(); } var obj = arguments[length - 1]; return (_isArray(obj) || typeof obj[methodname] !== 'function') ? fn.apply(this, arguments) : obj[methodname].apply(obj, Array.prototype.slice.call(arguments, 0, length - 1)); }; } /** * Optimized internal three-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry3(fn) { return function f3(a, b, c) { switch (arguments.length) { case 0: return f3; case 1: return _isPlaceholder(a) ? f3 : _curry2(function(_b, _c) { return fn(a, _b, _c); }); case 2: return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function(_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) ? _curry2(function(_b, _c) { return fn(a, _b, _c); }) : _curry1(function(_c) { return fn(a, b, _c); }); default: return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function(_a, _b) { return fn(_a, _b, c); }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function(_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function(_b, _c) { return fn(a, _b, _c); }) : _isPlaceholder(a) ? _curry1(function(_a) { return fn(_a, b, c); }) : _isPlaceholder(b) ? _curry1(function(_b) { return fn(a, _b, c); }) : _isPlaceholder(c) ? _curry1(function(_c) { return fn(a, b, _c); }) : fn(a, b, c); } }; } /** * Returns the elements of the given list or string (or object with a `slice` * method) from `fromIndex` (inclusive) to `toIndex` (exclusive). * * Dispatches to the `slice` method of the third argument, if present. * * @func * @memberOf R * @since v0.1.4 * @category List * @sig Number -> Number -> [a] -> [a] * @sig Number -> Number -> String -> String * @param {Number} fromIndex The start index (inclusive). * @param {Number} toIndex The end index (exclusive). * @param {*} list * @return {*} * @example * * R.slice(1, 3, ['a', 'b', 'c', 'd']); //=> ['b', 'c'] * R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd'] * R.slice(0, -1, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c'] * R.slice(-3, -1, ['a', 'b', 'c', 'd']); //=> ['b', 'c'] * R.slice(0, 3, 'ramda'); //=> 'ram' */ var slice = _curry3(_checkForMethod('slice', function slice(fromIndex, toIndex, list) { return Array.prototype.slice.call(list, fromIndex, toIndex); })); /** * Returns the first `n` elements of the given list, string, or * transducer/transformer (or object with a `take` method). * * Dispatches to the `take` method of the second argument, if present. * * @func * @memberOf R * @since v0.1.0 * @category List * @sig Number -> [a] -> [a] * @sig Number -> String -> String * @param {Number} n * @param {*} list * @return {*} * @see R.drop * @example * * R.take(1, ['foo', 'bar', 'baz']); //=> ['foo'] * R.take(2, ['foo', 'bar', 'baz']); //=> ['foo', 'bar'] * R.take(3, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz'] * R.take(4, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz'] * R.take(3, 'ramda'); //=> 'ram' * * const personnel = [ * 'Dave Brubeck', * 'Paul Desmond', * 'Eugene Wright', * 'Joe Morello', * 'Gerry Mulligan', * 'Bob Bates', * 'Joe Dodge', * 'Ron Crotty' * ]; * * const takeFive = R.take(5); * takeFive(personnel); * //=> ['Dave Brubeck', 'Paul Desmond', 'Eugene Wright', 'Joe Morello', 'Gerry Mulligan'] * @symb R.take(-1, [a, b]) = [a, b] * @symb R.take(0, [a, b]) = [] * @symb R.take(1, [a, b]) = [a] * @symb R.take(2, [a, b]) = [a, b] */ var take = _curry2(_dispatchable(['take'], _xtake, function take(n, xs) { return slice(0, n < 0 ? Infinity : n, xs); })); function dropLast(n, xs) { return take(n < xs.length ? xs.length - n : 0, xs); } function XDropLast(n, xf) { this.xf = xf; this.pos = 0; this.full = false; this.acc = new Array(n); } XDropLast.prototype['@@transducer/init'] = _xfBase.init; XDropLast.prototype['@@transducer/result'] = function(result) { this.acc = null; return this.xf['@@transducer/result'](result); }; XDropLast.prototype['@@transducer/step'] = function(result, input) { if (this.full) { result = this.xf['@@transducer/step'](result, this.acc[this.pos]); } this.store(input); return result; }; XDropLast.prototype.store = function(input) { this.acc[this.pos] = input; this.pos += 1; if (this.pos === this.acc.length) { this.pos = 0; this.full = true; } }; var _xdropLast = _curry2(function _xdropLast(n, xf) { return new XDropLast(n, xf); }); /** * Returns a list containing all but the last `n` elements of the given `list`. * * Acts as a transducer if a transformer is given in list position. * * @func * @memberOf R * @since v0.16.0 * @category List * @sig Number -> [a] -> [a] * @sig Number -> String -> String * @param {Number} n The number of elements of `list` to skip. * @param {Array} list The list of elements to consider. * @return {Array} A copy of the list with only the first `list.length - n` elements * @see R.takeLast, R.drop, R.dropWhile, R.dropLastWhile * @example * * R.dropLast(1, ['foo', 'bar', 'baz']); //=> ['foo', 'bar'] * R.dropLast(2, ['foo', 'bar', 'baz']); //=> ['foo'] * R.dropLast(3, ['foo', 'bar', 'baz']); //=> [] * R.dropLast(4, ['foo', 'bar', 'baz']); //=> [] * R.dropLast(3, 'ramda'); //=> 'ra' */ var dropLast$1 = _curry2(_dispatchable([], _xdropLast, dropLast)); exports.dropLast = dropLast$1; Object.defineProperty(exports, '__esModule', { value: true }); })));