curry_right.js (2580B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var isFunction = require( '@stdlib/assert/is-function' ); 24 var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive; 25 26 27 // MAIN // 28 29 /** 30 * Transforms a function into a sequence of functions each accepting a single argument. 31 * 32 * @param {Function} fcn - function to curry 33 * @param {PositiveInteger} [arity=fcn.length] - number of parameters 34 * @param {*} [thisArg] - evaluation context 35 * @throws {TypeError} first argument must be a function 36 * @throws {TypeError} `arity` argument must be a positive integer 37 * @returns {Function} curry function 38 * 39 * @example 40 * function add( x, y ) { 41 * return x + y; 42 * } 43 * 44 * var f = curryRight( add ); 45 * 46 * var sum = f( 2 )( 3 ); 47 * // returns 5 48 */ 49 function curryRight( fcn, arity, thisArg ) { 50 var context; 51 var len; 52 if ( !isFunction( fcn ) ) { 53 throw new TypeError( 'invalid argument. First argument must be a function. Value: `' + fcn + '`.' ); 54 } 55 if ( arguments.length < 2 ) { 56 len = fcn.length; 57 } 58 else if ( arguments.length > 2 ) { 59 len = arity; 60 context = thisArg; 61 if ( !isPositiveInteger( len ) ) { 62 throw new TypeError( 'invalid argument. Arity argument must be positive integer. Value: `' + len + '`.' ); 63 } 64 } 65 else if ( isPositiveInteger( arity ) ) { 66 len = arity; 67 } 68 else { 69 len = fcn.length; 70 context = arity; 71 } 72 return createCurried( [] ); 73 74 /** 75 * Returns a curry function. 76 * 77 * @private 78 * @param {Array} args - arguments 79 * @returns {Function} curry function 80 */ 81 function createCurried( args ) { 82 return curried; 83 84 /** 85 * Curry function. 86 * 87 * @private 88 * @param {*} v - curried function parameter 89 * @returns {(Function|*)} partially applied curry function or curried function result 90 */ 91 function curried( v ) { 92 var cargs = args.slice(); 93 cargs.unshift( v ); 94 if ( cargs.length < len ) { 95 return createCurried( cargs ); 96 } 97 return fcn.apply( context, cargs ); 98 } 99 } 100 } 101 102 103 // EXPORTS // 104 105 module.exports = curryRight;