@ramda/droplast
Version:
R.dropLast exported as a module
363 lines (340 loc) • 11.8 kB
JavaScript
// 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 });
})));