├── .gitignore ├── index.js ├── LICENSE ├── test.js ├── package.json ├── benchmark ├── index.js └── generate-test.js ├── .circleci └── config.yml ├── README.md └── compose-tiny.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | coverage -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = (...c) => (...a) => { 2 | let i = c.length - 1; 3 | a = c[i](...a); 4 | while (i--) a = c[i](a); 5 | return a; 6 | }; 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Joe Martella 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const compose = require('.'); 2 | 3 | const add = x => y => x + y; 4 | const sqr = x => x ** 2; 5 | const add1 = add(1); 6 | const add2 = add(2); 7 | 8 | test('should compose functions', () => { 9 | const testFunction = compose( 10 | sqr, 11 | add2 12 | ); 13 | 14 | expect(testFunction(2)).toBe(16); 15 | }); 16 | 17 | test("should error when a function isn't passed", () => { 18 | const testFunction = compose( 19 | sqr, 20 | new Date(), 21 | add2 22 | ); 23 | 24 | expect(() => testFunction(2)).toThrow(); 25 | }); 26 | 27 | test('should work with different combinations', () => { 28 | expect( 29 | compose( 30 | sqr, 31 | add1 32 | )(2) 33 | ).toBe(sqr(add1(2))); 34 | expect(sqr(add1(2))).toBe(9); 35 | expect( 36 | compose( 37 | sqr, 38 | add1 39 | )(2) 40 | ).toBe(9); 41 | }); 42 | 43 | test('should be able to use function multiple times', () => { 44 | const testFunction = compose( 45 | sqr, 46 | add2 47 | ); 48 | 49 | expect(testFunction(2)).toBe(16); 50 | expect(testFunction(2)).toBe(16); 51 | }); 52 | 53 | test('should allow multiple args to first functions', () => { 54 | const testFunction = compose( 55 | sqr, 56 | add2, 57 | (x, y) => x * y 58 | ); 59 | 60 | expect(testFunction(2, 4)).toBe(100); 61 | expect(testFunction(2, 7)).toBe(256); 62 | }); 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "compose-tiny", 3 | "version": "1.1.3", 4 | "description": "A very tiny compose function.", 5 | "main": "dist/index.js", 6 | "umd:main": "dist/index.umd.js", 7 | "module": "dist/index.m.js", 8 | "source": "index.js", 9 | "types": "compose-tiny.d.ts", 10 | "license": "MIT", 11 | "files": [ 12 | "index.js", 13 | "compose-tiny.d.ts", 14 | "dist/" 15 | ], 16 | "author": { 17 | "name": "Andrew Lisowski", 18 | "email": "lisowski54@gmail.com" 19 | }, 20 | "scripts": { 21 | "test": "jest", 22 | "lint": "xo", 23 | "build": "microbundle", 24 | "dev": "microbundle watch", 25 | "benchmark": "node benchmark", 26 | "check-bundle": "bundlewatch", 27 | "release": "github-semantic-version --bump --changelog --push --publish" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "https://github.com/hipstersmoothie/compose-tiny.git" 32 | }, 33 | "devDependencies": { 34 | "benchmark": "^2.1.4", 35 | "bundlewatch": "^0.2.1", 36 | "chain-function": "^1.0.1", 37 | "cli-table2": "^0.2.0", 38 | "compose-funcs": "^1.0.0", 39 | "compose-function": "^3.0.3", 40 | "composing": "^1.0.1", 41 | "fj-compose": "^1.1.0", 42 | "github-semantic-version": "^7.6.0", 43 | "husky": "^1.0.1", 44 | "jest": "^23.6.0", 45 | "just-compose": "^1.1.0", 46 | "lint-staged": "^7.3.0", 47 | "logdown": "^3.2.7", 48 | "microbundle": "^0.6.0", 49 | "ora": "^3.0.0", 50 | "prettier": "^1.14.3", 51 | "squad": "^3.0.0", 52 | "xo": "^0.23.0" 53 | }, 54 | "xo": { 55 | "env": [ 56 | "jest" 57 | ], 58 | "extends": [ 59 | "prettier" 60 | ], 61 | "plugins": [ 62 | "prettier" 63 | ] 64 | }, 65 | "husky": { 66 | "hooks": { 67 | "pre-commit": "lint-staged" 68 | } 69 | }, 70 | "lint-staged": { 71 | "*.{js,json,css,md}": [ 72 | "prettier --write", 73 | "git add" 74 | ] 75 | }, 76 | "prettier": { 77 | "singleQuote": true 78 | }, 79 | "jest": { 80 | "coverageDirectory": "./coverage/", 81 | "collectCoverage": true 82 | }, 83 | "gsv": { 84 | "majorLabel": "major", 85 | "minorLabel": "minor", 86 | "patchLabel": "patch", 87 | "internalLabel": "internal", 88 | "addReleasedLabelOnSuccess": "released" 89 | }, 90 | "bundlewatch": { 91 | "files": [ 92 | { 93 | "path": "index.js", 94 | "maxSize": "150B" 95 | } 96 | ] 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /benchmark/index.js: -------------------------------------------------------------------------------- 1 | const ora = require('ora'); 2 | const Benchmark = require('benchmark'); 3 | const debug = require('logdown')('compose'); 4 | const Table = require('cli-table2'); 5 | 6 | const compose = require('..'); 7 | const composeFunction = require('compose-function'); 8 | const justCompose = require('just-compose'); 9 | const fjCompose = require('fj-compose'); 10 | const chainFunction = require('chain-function'); 11 | const squad = require('squad'); 12 | const composeFuncs = require('compose-funcs'); 13 | const composing = require('composing'); 14 | const generateTest = require('./generate-test'); 15 | 16 | let spinner = ora('Running benchmark'); 17 | const benchmark = new Benchmark.Suite('compose'); 18 | const INPUT = 100; 19 | const results = []; 20 | 21 | function showResults(benchmarkResults) { 22 | const table = new Table({ 23 | head: ['NAME', 'OPS/SEC', 'RELATIVE MARGIN OF ERROR', 'SAMPLE SIZE'] 24 | }); 25 | benchmarkResults.forEach(result => { 26 | table.push([ 27 | result.target.name, 28 | result.target.hz.toLocaleString('en-US', { maximumFractionDigits: 0 }), 29 | `± ${result.target.stats.rme.toFixed(2)}%`, 30 | result.target.stats.sample.length 31 | ]); 32 | }); 33 | console.log(table.toString()); 34 | } 35 | 36 | function sortDescResults(benchmarkResults) { 37 | return benchmarkResults.sort((a, b) => (a.target.hz < b.target.hz ? 1 : -1)); 38 | } 39 | 40 | function onCycle(event) { 41 | results.push(event); 42 | spinner.succeed(event.target.name); 43 | spinner = ora('Running benchmark'); 44 | spinner.start(); 45 | } 46 | 47 | function onComplete() { 48 | spinner.stop(); 49 | debug.log(); 50 | 51 | const orderedBenchmarkResults = sortDescResults(results); 52 | showResults(orderedBenchmarkResults); 53 | } 54 | 55 | spinner.start(); 56 | 57 | const defaultOptions = { minSamples: 100 }; 58 | 59 | benchmark 60 | .add('compose-tiny', generateTest(compose, INPUT), defaultOptions) 61 | .add('squad', generateTest(squad, INPUT), defaultOptions) 62 | .add('compose-function', generateTest(composeFunction, INPUT), defaultOptions) 63 | .add('just-compose', generateTest(justCompose, INPUT), defaultOptions) 64 | .add('fj-compose', generateTest(fjCompose, INPUT), defaultOptions) 65 | .add('chain-function', generateTest(chainFunction, INPUT), defaultOptions) 66 | .add('compose-funcs', generateTest(composeFuncs, INPUT), defaultOptions) 67 | .add('composing', generateTest(composing, INPUT), defaultOptions) 68 | .on('cycle', onCycle) 69 | .on('complete', onComplete) 70 | .run({ async: true }); 71 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | defaults: &defaults 4 | working_directory: ~/compose-tiny 5 | docker: 6 | - image: circleci/node:latest-browsers 7 | 8 | jobs: 9 | install: 10 | <<: *defaults 11 | steps: 12 | - checkout 13 | - restore_cache: 14 | keys: 15 | # Find a cache corresponding to this specific package.json checksum 16 | # when this file is changed, this key will fail 17 | - compose-tiny-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} 18 | - compose-tiny-{{ .Branch }}-{{ checksum "yarn.lock" }} 19 | - compose-tiny-{{ .Branch }} 20 | # Find the most recent cache used from any branch 21 | - compose-tiny-master 22 | - compose-tiny- 23 | - run: 24 | name: Install Dependencies 25 | command: yarn install --frozen-lockfile 26 | - save_cache: 27 | key: compose-tiny-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} 28 | paths: 29 | - ~/.cache/yarn 30 | - node_modules 31 | - persist_to_workspace: 32 | root: . 33 | paths: 34 | - . 35 | 36 | lint: 37 | <<: *defaults 38 | steps: 39 | - attach_workspace: 40 | at: ~/compose-tiny 41 | - run: 42 | name: Lint 43 | command: yarn lint 44 | - run: 45 | name: Check Bundle Size 46 | command: yarn check-bundle || echo 47 | 48 | test: 49 | <<: *defaults 50 | steps: 51 | - attach_workspace: 52 | at: ~/compose-tiny 53 | - run: 54 | name: Test 55 | command: yarn test --ci 56 | - run: 57 | name: Send CodeCov Results 58 | command: bash <(curl -s https://codecov.io/bash) -t $CODECOV_KEY 59 | 60 | publish: 61 | <<: *defaults 62 | steps: 63 | - attach_workspace: 64 | at: ~/compose-tiny 65 | - run: mkdir ~/.ssh && ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts 66 | - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 67 | - run: 68 | name: Build Library 69 | command: npm run build 70 | - run: 71 | name: Publish Library 72 | command: npm run release 73 | 74 | workflows: 75 | version: 2 76 | build_and_test: 77 | jobs: 78 | - install: 79 | filters: 80 | tags: 81 | only: /.*/ 82 | - lint: 83 | requires: 84 | - install 85 | filters: 86 | tags: 87 | only: /.*/ 88 | - test: 89 | requires: 90 | - install 91 | filters: 92 | tags: 93 | only: /.*/ 94 | - publish: 95 | requires: 96 | - lint 97 | - test 98 | filters: 99 | branches: 100 | only: 101 | - master 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 4 |

compose-tiny

5 |

A very tiny and fast compose function.

6 |
7 | 8 | [![CircleCI](https://img.shields.io/circleci/project/github/hipstersmoothie/compose-tiny/master.svg?style=for-the-badge)](https://circleci.com/gh/hipstersmoothie/compose-tiny/tree/master) [![Codecov](https://img.shields.io/codecov/c/github/hipstersmoothie/compose-tiny.svg?style=for-the-badge)](https://codecov.io/gh/hipstersmoothie/compose-tiny) [![npm](https://img.shields.io/npm/v/compose-tiny.svg?style=for-the-badge)](https://www.npmjs.com/package/compose-tiny) [![bundle size](http://img.badgesize.io/hipstersmoothie/compose-tiny/master/index.js.svg?style=for-the-badge)](https://www.npmjs.com/package/compose-tiny) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=for-the-badge)](https://github.com/prettier/prettier) 9 | 10 | > Function composition is an act or mechanism to combine simple functions to build more complicated ones. 11 | 12 | `compose-tiny` aims to provide a simple function for composition at the smallest possible size and the fasted possible speed. It's TypeScript friendly too! 13 | 14 | ## Installation 15 | 16 | ```sh 17 | npm install compose-tiny 18 | ``` 19 | 20 | ## Usage 21 | 22 | ```js 23 | const compose = require('compose-tiny'); 24 | 25 | const add = x => x + 2; 26 | const sqr = x => x ** 2; 27 | 28 | const blastOff = compose( 29 | x => `🚀 ${x} 🚀` 30 | sqr, 31 | add 32 | ); 33 | 34 | blastOff(2); 35 | ``` 36 | 37 | Output: 38 | 39 | ```sh 40 | 🚀 16 🚀 41 | ``` 42 | 43 | ## Multiple Arguments 44 | 45 | The first function in the composition can take multiple arguments. 46 | 47 | ```js 48 | const compose = require('compose-tiny'); 49 | 50 | const add = x => x + 2; 51 | const sqr = x => x ** 2; 52 | 53 | const blastOff = compose( 54 | sqr, 55 | add, 56 | (x, y, z) => (x + y) * z 57 | ); 58 | 59 | blastOff(1, 2, 4); 60 | ``` 61 | 62 | ## Performance 63 | 64 | NOTE: bundlephobia measures all package files 65 | 66 | | NAME | OPS/SEC | RELATIVE MARGIN OF ERROR | SAMPLE SIZE | BUNDLE SIZE | 67 | | ---------------- | -------- | --------------------------------------------- | ----------- | ---------------------------------------------------------- | 68 | | compose-tiny | 1108,413 | ± 0.72% | 187 | [112 B](https://bundlephobia.com/result?p=compose-tiny) | 69 | | squad | 105,070 | ± 0.62% | 185 | [517 B](https://bundlephobia.com/result?p=squad) | 70 | | just-compose | 46,964 | ± 1.88% | 181 | [334 B](https://bundlephobia.com/result?p=just-compose) | 71 | | chain-function | 22,556 | ± 0.50% | 187 | [341 B](https://bundlephobia.com/result?p=chain-function) | 72 | | compose-function | 20,817 | ± 0.49% | 186 | [1.2 kB](https://bundlephobia.com/result?p=compose-function) | 73 | | fj-compose | 8,581 | ± 0.61% | 184 | [334 B](https://bundlephobia.com/result?p=fj-compose) | 74 | | compose-funcs | 356 | ± 1.58% | 176 | [594 B](https://bundlephobia.com/result?p=compose-funcs) | 75 | 76 | To rerun this benchmark 77 | 78 | ```sh 79 | node benchmark 80 | ``` 81 | -------------------------------------------------------------------------------- /compose-tiny.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'compose-tiny' { 2 | 3 | const compose: typeof $; 4 | 5 | // Credits to 6 | function $(fn1: () => R1): () => R1; 7 | function $(fn1: (v1: V1) => R1): (v1: V1) => R1; 8 | function $(fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R1; 9 | function $(fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R1; 10 | function $(fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R1; 11 | function $(fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1; 12 | function $(fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1; 13 | function $(fn2: (v: R1) => R2, fn1: () => R1): () => R2; 14 | function $(fn2: (v: R1) => R2, fn1: (v1: V1) => R1): (v1: V1) => R2; 15 | function $(fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R2; 16 | function $(fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R2; 17 | function $(fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R2; 18 | function $(fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R2; 19 | function $(fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R2; 20 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: () => R1): () => R3; 21 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1) => R1): (v1: V1) => R3; 22 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R3; 23 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R3; 24 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R3; 25 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R3; 26 | function $(fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R3; 27 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: () => R1): () => R4; 28 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1) => R1): (v1: V1) => R4; 29 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R4; 30 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R4; 31 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R4; 32 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R4; 33 | function $(fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R4; 34 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: () => R1): () => R5; 35 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1) => R1): (v1: V1) => R5; 36 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R5; 37 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R5; 38 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R5; 39 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R5; 40 | function $(fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R5; 41 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: () => R1): () => R6; 42 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1) => R1): (v1: V1) => R6; 43 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2) => R1): (v1: V1, v2: V2) => R6; 44 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3) => R1): (v1: V1, v2: V2, v3: V3) => R6; 45 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4) => R1): (v1: V1, v2: V2, v3: V3, v4: V4) => R6; 46 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => R6; 47 | function $(fn6: (v: R5) => R6, fn5: (v: R4) => R5, fn4: (v: R3) => R4, fn3: (v: R2) => R3, fn2: (v: R1) => R2, fn1: (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R1): (v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => R6; 48 | 49 | // Support unlimited arity with any in first function and higher number of composed functions 50 | function $(fn0: (...arg: any[]) => T1): (...arg: any[]) => T1; 51 | function $(fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T2; 52 | function $(fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T3; 53 | function $(fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T4; 54 | function $(fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T5; 55 | function $(fn5: (a: T5) => T6, fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T6; 56 | function $(fn6: (a: T6) => T7, fn5: (a: T5) => T6, fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T7; 57 | function $(fn7: (a: T7) => T8, fn6: (a: T6) => T7, fn5: (a: T5) => T6, fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T8; 58 | function $(fn8: (a: T8) => T9, fn7: (a: T7) => T8, fn6: (a: T6) => T7, fn5: (a: T5) => T6, fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T9; 59 | function $(fn9: (a: T9) => T10, fn8: (a: T8) => T9, fn7: (a: T7) => T8, fn6: (a: T6) => T7, fn5: (a: T5) => T6, fn4: (a: T4) => T5, fn3: (a: T3) => T4, fn2: (a: T2) => T3, fn1: (a: T1) => T2, fn0: (...arg: any[]) => T1): (...arg: any[]) => T10; 60 | 61 | export = compose; 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/generate-test.js: -------------------------------------------------------------------------------- 1 | const add = x => x + 1; 2 | const sqr = x => x * x; 3 | const dec = x => x - 1; 4 | 5 | module.exports = (compose, input) => () => 6 | compose( 7 | add, 8 | sqr, 9 | dec, 10 | sqr, 11 | sqr, 12 | add, 13 | sqr, 14 | dec, 15 | sqr, 16 | sqr, 17 | add, 18 | dec, 19 | sqr, 20 | sqr, 21 | add, 22 | sqr, 23 | dec, 24 | sqr, 25 | sqr, 26 | add, 27 | dec, 28 | sqr, 29 | sqr, 30 | add, 31 | sqr, 32 | dec, 33 | sqr, 34 | sqr, 35 | add, 36 | dec, 37 | sqr, 38 | sqr, 39 | add, 40 | sqr, 41 | dec, 42 | sqr, 43 | sqr, 44 | add, 45 | dec, 46 | sqr, 47 | sqr, 48 | add, 49 | sqr, 50 | dec, 51 | sqr, 52 | sqr, 53 | add, 54 | sqr, 55 | dec, 56 | sqr, 57 | sqr, 58 | add, 59 | dec, 60 | sqr, 61 | sqr, 62 | add, 63 | sqr, 64 | dec, 65 | sqr, 66 | sqr, 67 | add, 68 | dec, 69 | sqr, 70 | sqr, 71 | add, 72 | sqr, 73 | dec, 74 | sqr, 75 | sqr, 76 | add, 77 | dec, 78 | sqr, 79 | sqr, 80 | add, 81 | sqr, 82 | dec, 83 | sqr, 84 | sqr, 85 | add, 86 | dec, 87 | sqr, 88 | sqr, 89 | add, 90 | sqr, 91 | dec, 92 | sqr, 93 | sqr, 94 | add, 95 | sqr, 96 | dec, 97 | sqr, 98 | sqr, 99 | add, 100 | dec, 101 | sqr, 102 | sqr, 103 | add, 104 | sqr, 105 | dec, 106 | sqr, 107 | sqr, 108 | add, 109 | dec, 110 | sqr, 111 | sqr, 112 | add, 113 | sqr, 114 | dec, 115 | sqr, 116 | sqr, 117 | add, 118 | dec, 119 | sqr, 120 | sqr, 121 | add, 122 | sqr, 123 | dec, 124 | sqr, 125 | sqr, 126 | add, 127 | dec, 128 | sqr, 129 | sqr, 130 | add, 131 | sqr, 132 | dec, 133 | sqr, 134 | sqr, 135 | add, 136 | sqr, 137 | dec, 138 | sqr, 139 | sqr, 140 | add, 141 | dec, 142 | sqr, 143 | sqr, 144 | add, 145 | sqr, 146 | dec, 147 | sqr, 148 | sqr, 149 | add, 150 | dec, 151 | sqr, 152 | sqr, 153 | add, 154 | sqr, 155 | dec, 156 | sqr, 157 | sqr, 158 | add, 159 | dec, 160 | sqr, 161 | sqr, 162 | add, 163 | sqr, 164 | dec, 165 | sqr, 166 | sqr, 167 | add, 168 | dec, 169 | sqr, 170 | sqr, 171 | add, 172 | sqr, 173 | dec, 174 | sqr, 175 | sqr, 176 | add, 177 | sqr, 178 | dec, 179 | sqr, 180 | sqr, 181 | add, 182 | dec, 183 | sqr, 184 | sqr, 185 | add, 186 | sqr, 187 | dec, 188 | sqr, 189 | sqr, 190 | add, 191 | dec, 192 | sqr, 193 | sqr, 194 | add, 195 | sqr, 196 | dec, 197 | sqr, 198 | sqr, 199 | add, 200 | dec, 201 | sqr, 202 | sqr, 203 | add, 204 | sqr, 205 | dec, 206 | sqr, 207 | sqr, 208 | add, 209 | dec, 210 | sqr, 211 | sqr, 212 | add, 213 | sqr, 214 | dec, 215 | sqr, 216 | sqr, 217 | add, 218 | sqr, 219 | dec, 220 | sqr, 221 | sqr, 222 | add, 223 | dec, 224 | sqr, 225 | sqr, 226 | add, 227 | sqr, 228 | dec, 229 | sqr, 230 | sqr, 231 | add, 232 | dec, 233 | sqr, 234 | sqr, 235 | add, 236 | sqr, 237 | dec, 238 | sqr, 239 | sqr, 240 | add, 241 | dec, 242 | sqr, 243 | sqr, 244 | add, 245 | sqr, 246 | dec, 247 | sqr, 248 | sqr, 249 | add, 250 | dec, 251 | sqr, 252 | sqr, 253 | add, 254 | sqr, 255 | dec, 256 | sqr, 257 | sqr, 258 | add, 259 | sqr, 260 | dec, 261 | sqr, 262 | sqr, 263 | add, 264 | dec, 265 | sqr, 266 | sqr, 267 | add, 268 | sqr, 269 | dec, 270 | sqr, 271 | sqr, 272 | add, 273 | dec, 274 | sqr, 275 | sqr, 276 | add, 277 | sqr, 278 | dec, 279 | sqr, 280 | sqr, 281 | add, 282 | dec, 283 | sqr, 284 | sqr, 285 | add, 286 | sqr, 287 | dec, 288 | sqr, 289 | sqr, 290 | add, 291 | dec, 292 | sqr, 293 | sqr, 294 | add, 295 | sqr, 296 | dec, 297 | sqr, 298 | sqr, 299 | add, 300 | sqr, 301 | dec, 302 | sqr, 303 | sqr, 304 | add, 305 | dec, 306 | sqr, 307 | sqr, 308 | add, 309 | sqr, 310 | dec, 311 | sqr, 312 | sqr, 313 | add, 314 | dec, 315 | sqr, 316 | sqr, 317 | add, 318 | sqr, 319 | dec, 320 | sqr, 321 | sqr, 322 | add, 323 | dec, 324 | sqr, 325 | sqr, 326 | add, 327 | sqr, 328 | dec, 329 | sqr, 330 | sqr, 331 | add, 332 | dec, 333 | sqr, 334 | sqr, 335 | add, 336 | sqr, 337 | dec, 338 | sqr, 339 | sqr, 340 | add, 341 | sqr, 342 | dec, 343 | sqr, 344 | sqr, 345 | add, 346 | dec, 347 | sqr, 348 | sqr, 349 | add, 350 | sqr, 351 | dec, 352 | sqr, 353 | sqr, 354 | add, 355 | dec, 356 | sqr, 357 | sqr, 358 | add, 359 | sqr, 360 | dec, 361 | sqr, 362 | sqr, 363 | add, 364 | dec, 365 | sqr, 366 | sqr, 367 | add, 368 | sqr, 369 | dec, 370 | sqr, 371 | sqr, 372 | add, 373 | dec, 374 | sqr, 375 | sqr, 376 | add, 377 | sqr, 378 | dec, 379 | sqr, 380 | sqr, 381 | add, 382 | sqr, 383 | dec, 384 | sqr, 385 | sqr, 386 | add, 387 | dec, 388 | sqr, 389 | sqr, 390 | add, 391 | sqr, 392 | dec, 393 | sqr, 394 | sqr, 395 | add, 396 | dec, 397 | sqr, 398 | sqr, 399 | add, 400 | sqr, 401 | dec, 402 | sqr, 403 | sqr, 404 | add, 405 | dec, 406 | sqr, 407 | sqr, 408 | add, 409 | sqr, 410 | dec, 411 | sqr, 412 | sqr, 413 | add, 414 | dec, 415 | sqr, 416 | sqr, 417 | add, 418 | sqr, 419 | dec, 420 | sqr, 421 | sqr, 422 | add, 423 | sqr, 424 | dec, 425 | sqr, 426 | sqr, 427 | add, 428 | dec, 429 | sqr, 430 | sqr, 431 | add, 432 | sqr, 433 | dec, 434 | sqr, 435 | sqr, 436 | add, 437 | dec, 438 | sqr, 439 | sqr, 440 | add, 441 | sqr, 442 | dec, 443 | sqr, 444 | sqr, 445 | add, 446 | dec, 447 | sqr, 448 | sqr, 449 | add, 450 | sqr, 451 | dec, 452 | sqr, 453 | sqr, 454 | add, 455 | dec, 456 | sqr, 457 | sqr, 458 | add, 459 | sqr, 460 | dec, 461 | sqr, 462 | sqr, 463 | add, 464 | dec, 465 | sqr, 466 | sqr, 467 | add, 468 | sqr, 469 | dec, 470 | sqr, 471 | sqr, 472 | add, 473 | dec, 474 | sqr, 475 | sqr, 476 | add, 477 | sqr, 478 | dec, 479 | sqr, 480 | sqr, 481 | add, 482 | dec, 483 | sqr, 484 | sqr, 485 | add, 486 | sqr, 487 | dec, 488 | sqr, 489 | sqr, 490 | add, 491 | dec, 492 | sqr, 493 | sqr, 494 | add, 495 | sqr, 496 | dec, 497 | sqr, 498 | sqr, 499 | add, 500 | dec, 501 | sqr, 502 | sqr, 503 | add, 504 | sqr, 505 | dec, 506 | sqr, 507 | sqr, 508 | add, 509 | dec, 510 | sqr, 511 | sqr, 512 | add, 513 | sqr, 514 | dec, 515 | sqr, 516 | sqr, 517 | add, 518 | dec, 519 | sqr, 520 | sqr, 521 | add, 522 | sqr, 523 | dec, 524 | sqr, 525 | sqr, 526 | add, 527 | dec, 528 | sqr, 529 | sqr, 530 | add, 531 | sqr, 532 | dec, 533 | sqr, 534 | sqr, 535 | add, 536 | dec, 537 | sqr, 538 | sqr, 539 | add, 540 | sqr, 541 | dec, 542 | sqr, 543 | sqr, 544 | add, 545 | dec, 546 | sqr, 547 | sqr, 548 | add, 549 | sqr, 550 | dec, 551 | sqr, 552 | sqr, 553 | add, 554 | dec, 555 | sqr, 556 | sqr, 557 | add, 558 | sqr, 559 | dec, 560 | sqr, 561 | sqr, 562 | add, 563 | dec, 564 | sqr, 565 | sqr, 566 | add, 567 | sqr, 568 | dec, 569 | sqr, 570 | sqr, 571 | add, 572 | dec, 573 | sqr, 574 | sqr, 575 | add, 576 | sqr, 577 | dec, 578 | sqr, 579 | sqr, 580 | add, 581 | dec, 582 | sqr, 583 | sqr, 584 | add, 585 | sqr, 586 | dec, 587 | sqr, 588 | sqr, 589 | add, 590 | dec, 591 | sqr, 592 | sqr, 593 | add, 594 | sqr, 595 | dec, 596 | sqr, 597 | sqr, 598 | add, 599 | dec, 600 | sqr, 601 | sqr, 602 | add, 603 | sqr, 604 | dec, 605 | sqr, 606 | sqr, 607 | add, 608 | dec, 609 | sqr, 610 | sqr, 611 | add, 612 | sqr, 613 | dec, 614 | sqr, 615 | sqr, 616 | add, 617 | sqr, 618 | dec, 619 | sqr, 620 | sqr, 621 | add, 622 | sqr, 623 | dec, 624 | sqr, 625 | sqr, 626 | add, 627 | sqr, 628 | dec, 629 | sqr, 630 | sqr, 631 | add, 632 | sqr, 633 | dec, 634 | sqr, 635 | sqr, 636 | add, 637 | sqr, 638 | dec, 639 | sqr, 640 | sqr, 641 | add, 642 | sqr, 643 | dec, 644 | sqr, 645 | sqr, 646 | add, 647 | sqr, 648 | dec, 649 | sqr, 650 | sqr, 651 | add, 652 | sqr, 653 | dec, 654 | sqr, 655 | sqr, 656 | add, 657 | sqr, 658 | dec, 659 | sqr, 660 | sqr, 661 | add, 662 | sqr, 663 | dec, 664 | sqr, 665 | sqr, 666 | add, 667 | sqr, 668 | dec, 669 | sqr, 670 | sqr, 671 | add, 672 | sqr, 673 | dec, 674 | sqr, 675 | sqr, 676 | add, 677 | sqr, 678 | dec, 679 | sqr, 680 | sqr, 681 | add, 682 | sqr, 683 | dec, 684 | sqr, 685 | sqr, 686 | add, 687 | sqr, 688 | dec, 689 | sqr, 690 | sqr, 691 | add, 692 | sqr, 693 | dec, 694 | sqr, 695 | sqr, 696 | add, 697 | sqr, 698 | dec, 699 | sqr, 700 | sqr, 701 | add, 702 | sqr, 703 | dec, 704 | sqr, 705 | sqr, 706 | add, 707 | sqr, 708 | dec, 709 | sqr, 710 | sqr, 711 | add, 712 | sqr, 713 | dec, 714 | sqr, 715 | sqr, 716 | add, 717 | sqr, 718 | dec, 719 | sqr, 720 | sqr, 721 | add, 722 | sqr, 723 | dec, 724 | sqr, 725 | sqr, 726 | add, 727 | sqr, 728 | dec, 729 | sqr, 730 | sqr, 731 | add, 732 | sqr, 733 | dec, 734 | sqr, 735 | sqr, 736 | add, 737 | sqr, 738 | dec, 739 | sqr, 740 | sqr, 741 | add, 742 | sqr, 743 | dec, 744 | sqr, 745 | sqr, 746 | add, 747 | sqr, 748 | dec, 749 | sqr, 750 | sqr, 751 | add, 752 | sqr, 753 | dec, 754 | sqr, 755 | sqr, 756 | add, 757 | sqr, 758 | dec, 759 | sqr, 760 | sqr, 761 | add, 762 | sqr, 763 | dec, 764 | sqr, 765 | sqr, 766 | add, 767 | sqr, 768 | dec, 769 | sqr, 770 | sqr, 771 | add, 772 | sqr, 773 | dec, 774 | sqr, 775 | sqr, 776 | add, 777 | sqr, 778 | dec, 779 | sqr, 780 | sqr, 781 | add, 782 | sqr, 783 | dec, 784 | sqr, 785 | sqr, 786 | add, 787 | sqr, 788 | dec, 789 | sqr, 790 | sqr, 791 | add, 792 | sqr, 793 | dec, 794 | sqr, 795 | sqr, 796 | add, 797 | sqr, 798 | dec, 799 | sqr, 800 | sqr, 801 | add, 802 | sqr, 803 | dec, 804 | sqr, 805 | sqr, 806 | add, 807 | sqr, 808 | dec, 809 | sqr, 810 | sqr, 811 | add, 812 | sqr, 813 | dec, 814 | sqr, 815 | sqr, 816 | add, 817 | sqr, 818 | dec, 819 | sqr, 820 | sqr, 821 | add, 822 | sqr, 823 | dec, 824 | sqr, 825 | sqr, 826 | add, 827 | sqr, 828 | dec, 829 | sqr, 830 | sqr, 831 | add, 832 | sqr, 833 | dec, 834 | sqr, 835 | sqr, 836 | add, 837 | sqr, 838 | dec, 839 | sqr, 840 | sqr, 841 | add, 842 | sqr, 843 | dec, 844 | sqr, 845 | sqr, 846 | add, 847 | sqr, 848 | dec, 849 | sqr, 850 | sqr, 851 | add, 852 | sqr, 853 | dec, 854 | sqr, 855 | sqr, 856 | add, 857 | sqr, 858 | dec, 859 | sqr, 860 | sqr, 861 | add, 862 | sqr, 863 | dec, 864 | sqr, 865 | sqr, 866 | add, 867 | sqr, 868 | dec, 869 | sqr, 870 | sqr, 871 | add, 872 | sqr, 873 | dec, 874 | sqr, 875 | sqr, 876 | add, 877 | sqr, 878 | dec, 879 | sqr, 880 | sqr, 881 | add, 882 | sqr, 883 | dec, 884 | sqr, 885 | sqr, 886 | add, 887 | sqr, 888 | dec, 889 | sqr, 890 | sqr, 891 | add, 892 | sqr, 893 | dec, 894 | sqr, 895 | sqr, 896 | add, 897 | sqr, 898 | dec, 899 | sqr, 900 | sqr, 901 | add, 902 | sqr, 903 | dec, 904 | sqr, 905 | sqr, 906 | add, 907 | sqr, 908 | dec, 909 | sqr, 910 | sqr, 911 | add, 912 | sqr, 913 | dec, 914 | sqr, 915 | sqr, 916 | add, 917 | sqr, 918 | dec, 919 | sqr, 920 | sqr, 921 | add, 922 | sqr, 923 | dec, 924 | sqr, 925 | sqr, 926 | add 927 | )(input); 928 | --------------------------------------------------------------------------------