/* eslint-disable prefer-rest-params */
import { arrayProtoSlice, mathMax } from './internals/native';
import isUndefined from './isUndefined';
import toInteger from './toInteger';
const PLACEHOLDER = {
__ut2_curry_ph__: null
};
/**
* 创建一个函数。该函数接受 `func` 参数,在提供的参数数量达到 `arity` 后调用 `func` 并返回其结果。
*
* `curry._` 或 `curry.placeholder` 可用作参数的占位符。
*
* @function
* @alias module:Function.curry
* @since 1.8.0
* @param {Function} func 需要柯里化的函数。
* @param {number} [arity] 指定参数数量。默认值为 `func.length`。
* @returns {Function} 新的柯里化函数。
* @example
*
* function abc(a, b, c){
* return [a, b, c];
* }
*
* var curried = curry(abc);
*
* curried(1)(2)(3); // [1, 2, 3]
*
* curried(1, 2)(3); // [1, 2, 3]
*
* curried(1, 2, 3); // [1, 2, 3]
*
* curried(1)(curry._, 3)(2); // [1, 2, 3]
*
* curried(curry._, curry._, 3)(curry._, 2)(1); // [1, 2, 3]
*
*/
const curry = function (func, arity) {
arity = isUndefined(arity) ? func.length : mathMax(toInteger(arity), 0);
function wrap() {
let args = arrayProtoSlice.call(arguments);
const context = this;
function inner() {
const argsInner = arrayProtoSlice.call(arguments);
for (let i = 0; i < args.length; i++) {
args[i] = args[i] === PLACEHOLDER && argsInner.length > 0 ? argsInner.shift() : args[i];
}
args = args.concat(argsInner);
const realArgsLength = args.filter((arg) => arg !== PLACEHOLDER).length;
if (realArgsLength >= arity) {
return func.apply(context, args);
}
return inner;
}
return inner();
}
return wrap;
};
curry.placeholder = curry._ = PLACEHOLDER;
export default curry;