Skip to content

Commit

Permalink
Update docs and benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
mobily committed Dec 5, 2021
1 parent 8d78b83 commit 23615a5
Show file tree
Hide file tree
Showing 19 changed files with 905 additions and 63 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</p>

<p align="center">
<strong>Belt (<code>ReScript</code>) implementation in TypeScript.</strong>
<strong>Fast, modern and practical utility library for FP in TypeScript.</strong>
</p>

## Features
Expand Down
28 changes: 28 additions & 0 deletions __tests__/Array/dropWhile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { expectType } from 'ts-expect'

import { A, pipe } from '../..'

const xs = [1, 2, 3, 4, 5, 6, 7]

// TODO: expectType
describe('dropWhile', () => {
it('drops elements from the beginning of the array until an element is reached which does not satisfy the given predicate', () => {
const result = A.dropWhile(xs, x => x < 4)
expect(result).toEqual([4, 5, 6, 7])
})

it('returns correct array elements if either true or false', () => {
expect(A.dropWhile(xs, _x => true)).toEqual([])
expect(A.dropWhile(xs, _x => false)).toEqual([1, 2, 3, 4, 5, 6, 7])
})
})

describe('dropWhile (pipe)', () => {
it('drops elements from the beginning of the array until an element is reached which does not satisfy the given predicate', () => {
const result = pipe(
xs,
A.dropWhile(x => x < 4),
)
expect(result).toEqual([4, 5, 6, 7])
})
})
25 changes: 25 additions & 0 deletions __tests__/Array/splitEvery.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { expectType } from 'ts-expect'

import { A, pipe } from '../..'

const xs = [1, 2, 3, 4, 5, 6, 7]

// TODO: expectType
describe('splitEvery', () => {
it('returns an array of arrays, where each of the inner arrays has length equal to `n`', () => {
const result = A.splitEvery(xs, 3)
expect(result).toEqual([[1, 2, 3], [4, 5, 6], [7]])
})

it('returns the original array inside a new array if n is out of range', () => {
expect(A.splitEvery(xs, 0)).toEqual([[1, 2, 3, 4, 5, 6, 7]])
expect(A.splitEvery(xs, 8)).toEqual([[1, 2, 3, 4, 5, 6, 7]])
})
})

describe('splitEvery (pipe)', () => {
it('returns an array of arrays, where each of the inner arrays has length equal to `n`', () => {
const result = pipe(xs, A.splitEvery(3))
expect(result).toEqual([[1, 2, 3], [4, 5, 6], [7]])
})
})
28 changes: 28 additions & 0 deletions __tests__/Array/takeWhile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { expectType } from 'ts-expect'

import { A, pipe } from '../..'

const xs = [1, 2, 3, 4, 5, 6, 7]

// TODO: expectType
describe('takeWhile', () => {
it('returns a new array, filled with elements from the provided array until an element does not pass the provided predicate', () => {
const result = A.takeWhile(xs, x => x < 4)
expect(result).toEqual([1, 2, 3])
})

it('returns correct array elements if either true or false', () => {
expect(A.takeWhile(xs, _x => true)).toEqual([1, 2, 3, 4, 5, 6, 7])
expect(A.takeWhile(xs, _x => false)).toEqual([])
})
})

describe('takeWhile (pipe)', () => {
it('returns a new array, filled with elements from the provided array until an element does not pass the provided predicate', () => {
const result = pipe(
xs,
A.takeWhile(x => x < 4),
)
expect(result).toEqual([1, 2, 3])
})
})
14 changes: 14 additions & 0 deletions benchmarks/index.markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const fs = require('fs')
const path = require('path')
const Benchr = require('benchr')

const files = process.argv.slice(2)

const runner = new Benchr(
{
reporter: './reporter.markdown.js',
},
files,
)

runner.run()
5 changes: 3 additions & 2 deletions benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "bash ./scripts/run.sh"
"start": "bash ./scripts/run.sh",
"generate": "bash ./scripts/generate.sh"
},
"devDependencies": {
"benchr": "^4.3.0"
Expand All @@ -14,6 +15,6 @@
"lodash": "^4.17.21",
"rambda": "^6.9.0",
"ramda": "^0.27.1",
"remeda": "^0.0.30"
"remeda": "^0.0.32"
}
}
70 changes: 70 additions & 0 deletions benchmarks/reporter.markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// https://github.com/robertklep/node-benchr/blob/master/lib/reporters/console.js

const Table = require('easy-table')
const path = require('path')

module.exports = runner => {
runner
.on('run.start', file => {})
.on('run.complete', file => {})
.on('file.start', file => {
const basename = path.basename(file, '.js')
process.stdout.write(`### ${basename}\n\n`)
})
.on('file.complete', file => {})
.on('suite.start', suite => {
console.log(`_${suite.name.trim()}_`)
})
.on('suite.cycle', suite => {})
.on('error', err => {
console.error(err)
})
.on('suite.complete', suite => {
const fastest = suite.filter('fastest')
const successful = suite.filter('successful')
const table = new Table()

suite.forEach(function (bench) {
if (bench.aborted) {
table.cell('status', '×')
} else {
table.cell('status', '✔')
}
table.cell('name', bench.name)
if (bench.aborted) {
table.cell('hz', 'ABORTED')
} else {
table.cell(
'hz',
bench.hz
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+\b)/g, ','),
Table.padLeft,
)
table.cell('label', 'ops/sec')
table.cell('rme', '±' + bench.stats.rme.toFixed(2) + '%')
table.cell('runs', '(' + bench.stats.sample.length + ' runs)')

// Show percentual difference between this benchmark and the fastest.
if (fastest.length !== successful.length) {
let diff = 'fastest'
if (bench !== fastest[0]) {
diff =
'-' + ((1.0 - bench.hz / fastest[0].hz) * 100).toFixed(2) + '%'
}
table.cell('diff', diff)
}
}
table.newRow()
})
console.log('\n```bash\n' + table.print() + '```\n')
if (successful.length > 1) {
if (fastest.length === successful.length) {
console.log('→ No discernible winner\n')
} else {
console.log('→ Fastest is **' + fastest.map('name') + '**\n')
}
}
})
}
23 changes: 23 additions & 0 deletions benchmarks/scripts/generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env sh

mkdir -p ./.results

results_file="./.results/results.md"

rm -f $results_file

glob_files=".*"

complex=($(grep -HRl "$glob_files" ./complex))

for i in "${complex[@]}"
do
node "./index.markdown.js" "$i" 2>&1 | tee -a $results_file
done

simple=($(grep -HRl "$glob_files" ./simple))

for i in "${simple[@]}"
do
node "./index.markdown.js" "$i" 2>&1 | tee -a $results_file
done
73 changes: 73 additions & 0 deletions benchmarks/simple/dropWhile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const {
makeBenchmark,
addTsBelt,
addLodashFp,
addRambda,
addRamda,
addRemeda,
} = require('../utils')

const input = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const fn = x => x < 5

module.exports = makeBenchmark(
'dropWhile',
addTsBelt(tsBelt => {
const { A, pipe } = tsBelt

return [
() => {
return A.dropWhile(input, fn)
},
() => {
return pipe(input, A.dropWhile(fn))
},
]
}),
// addRemeda(remeda => {
// const { pipe, dropWhile } = remeda

// return [
// () => {
// return dropWhile(input, fn)
// },
// () => {
// return pipe(input, dropWhile(fn))
// },
// ]
// }),
addRamda(ramda => {
const { pipe, dropWhile } = ramda

return [
() => {
return dropWhile(fn, input)
},
() => {
return pipe(dropWhile(fn))(input)
},
]
}),
addRambda(rambda => {
const { pipe, dropWhile } = rambda

return [
() => {
return dropWhile(fn, input)
},
() => {
return pipe(dropWhile(fn))(input)
},
]
}),
addLodashFp(_ => {
return [
() => {
return _.dropWhile(fn, input)
},
() => {
return _.pipe(_.dropWhile(fn))(input)
},
]
}),
)
6 changes: 3 additions & 3 deletions benchmarks/simple/flat.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ module.exports = makeBenchmark(
]
}),
addRamda(ramda => {
const { pipe, flatten } = ramda
const { pipe, unnest } = ramda

return [
() => {
return flatten(input)
return unnest(input)
},
() => {
return pipe(flatten)(input)
return pipe(unnest)(input)
},
]
}),
Expand Down
15 changes: 9 additions & 6 deletions benchmarks/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ const remeda = require('remeda')
const belt = require('..')

exports.makeBenchmark = (title, ...rest) => {
suite(`${title} (single function call)`, () => {
rest.forEach(test => {
benchmark(test.label, test.rawFn)
})
})
suite(
`${title} ${title.includes('→') ? '' : '(single function call)'}`,
() => {
rest.forEach(test => {
benchmark(test.label, test.rawFn)
})
},
)

suite(`${title} (function call within a pipeline)`, () => {
suite(`${title} (function call inside \`pipe\`)`, () => {
rest.forEach(test => {
benchmark(test.label, test.pipeFn)
})
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ ramda@^0.27.1:
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9"
integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==

remeda@^0.0.30:
version "0.0.30"
resolved "https://registry.yarnpkg.com/remeda/-/remeda-0.0.30.tgz#34a80efdab9053df2d59ed10cac20c4ca5bb1270"
integrity sha512-ygbf/pXioUbbNOYSRFu6oUEa72HiIcsiS6CFuhWEwoIByoyNzzofm/cVgHEnfQVeSkwTGHceuDOEHo5hHFv9Uw==
remeda@^0.0.32:
version "0.0.32"
resolved "https://registry.yarnpkg.com/remeda/-/remeda-0.0.32.tgz#668e5d3b8a5c9edb1a19f33d5df805dd1e7d299c"
integrity sha512-FEdl8ONpqY7AvvMHG5WYdomc0mGf2khHPUDu6QvNkOq4Wjkw5BvzWM4QyksAQ/US1sFIIRG8TVBn6iJx6HbRrA==

require-all@^2.2.0:
version "2.2.0"
Expand Down
Loading

0 comments on commit 23615a5

Please sign in to comment.