compose.js (2044B)
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 25 26 // MAIN // 27 28 /** 29 * Function composition. 30 * 31 * @param {...Function} f - functions to compose 32 * @throws {Error} must provide more than one argument 33 * @throws {TypeError} must provide functions 34 * @returns {Function} composite function 35 * 36 * @example 37 * function a( x ) { 38 * return 2 * x; 39 * } 40 * 41 * function b( x ) { 42 * return x + 3; 43 * } 44 * 45 * function c( x ) { 46 * return x / 5; 47 * } 48 * 49 * var f = compose( c, b, a ); 50 * 51 * var z = f( 6 ); 52 * // returns 3 53 */ 54 function compose() { 55 var nFuncs; 56 var f; 57 var i; 58 nFuncs = arguments.length; 59 if ( nFuncs < 2 ) { 60 throw new Error( 'insufficient input arguments. Must provide multiple functions to compose.' ); 61 } 62 f = new Array( nFuncs ); 63 for ( i = 0; i < nFuncs; i++ ) { 64 f[ i ] = arguments[ i ]; 65 if ( !isFunction( f[ i ] ) ) { 66 throw new TypeError( 'invalid argument. All arguments must be functions. Value: `'+f[ i ]+'`.' ); 67 } 68 } 69 return composite; 70 71 /** 72 * Composite function. 73 * 74 * @private 75 * @param {...*} args - arguments 76 * @returns {*} result 77 */ 78 function composite() { 79 var args; 80 var i; 81 args = new Array( arguments.length ); 82 for ( i = 0; i < args.length; i++ ) { 83 args[ i ] = arguments[ i ]; 84 } 85 args = f[ nFuncs-1 ].apply( null, args ); 86 for ( i = nFuncs-2; i >= 0; i-- ) { 87 args = f[ i ]( args ); 88 } 89 return args; 90 } 91 } 92 93 94 // EXPORTS // 95 96 module.exports = compose;