diff --git a/changelog.md b/changelog.md index 11b2a16..81519c4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +## `0.12.1` + +Add `isFunSync`, `isFunGen`, `isFunAsync`, `isFunAsyncGen`. + ## `0.12.0` Massive revision: diff --git a/doc/api/isFun.md b/doc/api/isFun.md index 6a2872c..f2d3281 100644 --- a/doc/api/isFun.md +++ b/doc/api/isFun.md @@ -1 +1 @@ -Same as `typeof val === 'function'`. True if value is a function. +Same as `typeof val === 'function'`. True if value is any function, regardless of its type (arrow, async, generator, etc.). diff --git a/doc/api/isFunAsync.md b/doc/api/isFunAsync.md new file mode 100644 index 0000000..d67ddff --- /dev/null +++ b/doc/api/isFunAsync.md @@ -0,0 +1 @@ +True if the input is an async non-generator function. False for sync functions, generator functions, or async generator functions. diff --git a/doc/api/isFunAsyncGen.md b/doc/api/isFunAsyncGen.md new file mode 100644 index 0000000..16c2786 --- /dev/null +++ b/doc/api/isFunAsyncGen.md @@ -0,0 +1 @@ +True if the input is an async generator function. False for sync functions and async non-generator functions. diff --git a/doc/api/isFunGen.md b/doc/api/isFunGen.md new file mode 100644 index 0000000..fd6b25e --- /dev/null +++ b/doc/api/isFunGen.md @@ -0,0 +1 @@ +True if the input is a sync generator function. False for normal sync functions and async functions. diff --git a/doc/api/isFunSync.md b/doc/api/isFunSync.md new file mode 100644 index 0000000..279dd92 --- /dev/null +++ b/doc/api/isFunSync.md @@ -0,0 +1 @@ +True if the input is a normal sync function. False for generator functions or async functions. diff --git a/doc/doc.mjs b/doc/doc.mjs index c217240..a2bc12a 100644 --- a/doc/doc.mjs +++ b/doc/doc.mjs @@ -19,8 +19,6 @@ const [ function main() { dat.reqTests() dat.reqDocs() - - const readme = new Templ(srcReadme, dat) Deno.writeTextFileSync(`readme.md`, readme.toString()) } diff --git a/fpx.mjs b/fpx.mjs index 2d80d18..efd6b0d 100644 --- a/fpx.mjs +++ b/fpx.mjs @@ -33,6 +33,10 @@ export function isJunk(val) {return isNil(val) || isNaN(val) || isInf(val)} export function isComp(val) {return isObj(val) || isFun(val)} export function isPrim(val) {return !isComp(val)} export function isFun(val) {return typeof val === `function`} +export function isFunSync(val) {return isFunType(val, `Function`)} +export function isFunGen(val) {return isFunType(val, `GeneratorFunction`)} +export function isFunAsync(val) {return isFunType(val, `AsyncFunction`)} +export function isFunAsyncGen(val) {return isFunType(val, `AsyncGeneratorFunction`)} export function isObj(val) {return val !== null && typeof val === `object`} export function isStruct(val) {return isObj(val) && !isIter(val) && !isIterAsync(val)} export function isArr(val) {return Array.isArray(val)} @@ -54,6 +58,7 @@ export function isList(val) {return isArr(val) || (isIter(val) && isNat(getLengt export function isSeq(val) {return isList(val) || isSet(val) || isIterator(val)} function isDictProto(val) {return val === null || val === Object.prototype} +function isFunType(val, name) {return isFun(val) && val.constructor.name === name} export function isInst(val, cls) { req(cls, isCls) diff --git a/makefile b/makefile index 90184ca..6b372f2 100644 --- a/makefile +++ b/makefile @@ -24,7 +24,7 @@ lint_w: watchexec -r -c -d=0 -e=mjs -n -- $(MAKE) lint lint: - deno lint --rules-exclude=no-empty,require-yield + deno lint --rules-exclude=no-empty,require-yield,require-await # TODO consider watching all related files. doc_w: diff --git a/package.json b/package.json index a1b3c8f..7b942c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fpx", - "version": "0.12.0", + "version": "0.12.1", "description": "Functional Programming eXtensions for JavaScript. Lightweight replacement for Lodash.", "type": "module", "main": "./fpx.mjs", diff --git a/readme.md b/readme.md index 91814db..0b6a464 100644 --- a/readme.md +++ b/readme.md @@ -51,6 +51,10 @@ Differences from Lodash: * [#`function isComp`](#function-iscomp) * [#`function isPrim`](#function-isprim) * [#`function isFun`](#function-isfun) + * [#`function isFunSync`](#function-isfunsync) + * [#`function isFunGen`](#function-isfungen) + * [#`function isFunAsync`](#function-isfunasync) + * [#`function isFunAsyncGen`](#function-isfunasyncgen) * [#`function isObj`](#function-isobj) * [#`function isStruct`](#function-isstruct) * [#`function isArr`](#function-isarr) @@ -184,7 +188,7 @@ Differences from Lodash: In browsers and Deno, import by URL: ```js -import * as f from 'https://cdn.jsdelivr.net/npm/fpx@0.12.0/fpx.mjs' +import * as f from 'https://cdn.jsdelivr.net/npm/fpx@0.12.1/fpx.mjs' ``` When using Node or NPM-oriented bundlers like Esbuild: @@ -326,7 +330,7 @@ Same as `!`. Sometimes useful with higher-order functions. ### `function isNil` -Links: [source](fpx.mjs#L15); [test/example](test/test.mjs#L128). +Links: [source](fpx.mjs#L15); [test/example](test/test.mjs#L116). True for `null` and `undefined`. Same as `value == null`. Incidentally, these are the only values that produce an exception when attempting to read a property: `null.someProperty`. @@ -346,19 +350,19 @@ f.isNil(false) ### `function isSome` -Links: [source](fpx.mjs#L16); [test/example](test/test.mjs#L136). +Links: [source](fpx.mjs#L16); [test/example](test/test.mjs#L124). Inverse of [#`isNil`](#function-isnil). False for `null` and `undefined`, true for other values. ### `function isBool` -Links: [source](fpx.mjs#L17); [test/example](test/test.mjs#L144). +Links: [source](fpx.mjs#L17); [test/example](test/test.mjs#L132). Same as `typeof val === 'boolean'`. ### `function isNum` -Links: [source](fpx.mjs#L18); [test/example](test/test.mjs#L153). +Links: [source](fpx.mjs#L18); [test/example](test/test.mjs#L141). Same as `typeof val === 'number'`. True if the value is a primitive number, _including_ `NaN` and `±Infinity`. In most cases you should use `isFin` instead. @@ -373,7 +377,7 @@ f.isNum(NaN) ### `function isFin` -Links: [source](fpx.mjs#L19); [test/example](test/test.mjs#L164). +Links: [source](fpx.mjs#L19); [test/example](test/test.mjs#L152). Same as ES2015's [`Number.isFinite`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite). True if `val` is a primitive number and is _not_ `NaN` or `±Infinity`. In most cases you should prefer `isFin` over `isNum`. @@ -388,85 +392,85 @@ f.isFin(NaN) ### `function isFinNeg` -Links: [source](fpx.mjs#L20); [test/example](test/test.mjs#L178). +Links: [source](fpx.mjs#L20); [test/example](test/test.mjs#L166). True if value is finite (via [#`isFin`](#function-isfin)) and < 0. ### `function isFinPos` -Links: [source](fpx.mjs#L21); [test/example](test/test.mjs#L197). +Links: [source](fpx.mjs#L21); [test/example](test/test.mjs#L185). True if value is finite (via [#`isFin`](#function-isfin)) and > 0. ### `function isInt` -Links: [source](fpx.mjs#L22); [test/example](test/test.mjs#L216). +Links: [source](fpx.mjs#L22); [test/example](test/test.mjs#L204). True if value is an integer: finite via [#`isFin`](#function-isfin), without a fractional part. ### `function isNat` -Links: [source](fpx.mjs#L23); [test/example](test/test.mjs#L234). +Links: [source](fpx.mjs#L23); [test/example](test/test.mjs#L222). True if value is a natural number: integer >= 0. Also see [#`isIntPos`](#function-isintpos). ### `function isIntNeg` -Links: [source](fpx.mjs#L24); [test/example](test/test.mjs#L252). +Links: [source](fpx.mjs#L24); [test/example](test/test.mjs#L240). True if value is integer < 0. Also see [#`isFinNeg`](#function-isfinneg). ### `function isIntPos` -Links: [source](fpx.mjs#L25); [test/example](test/test.mjs#L271). +Links: [source](fpx.mjs#L25); [test/example](test/test.mjs#L259). True if value is integer > 0. Also see [#`isNat`](#function-isnat), [#`isFinPos`](#function-isfinpos). ### `function isNaN` -Links: [source](fpx.mjs#L26); [test/example](test/test.mjs#L290). +Links: [source](fpx.mjs#L26); [test/example](test/test.mjs#L278). Same as ES2015's [`Number.isNaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN). True if value is _actually_ `NaN`. Doesn't coerce non-numbers to numbers, unlike global `isNaN`. ### `function isInf` -Links: [source](fpx.mjs#L27); [test/example](test/test.mjs#L305). +Links: [source](fpx.mjs#L27); [test/example](test/test.mjs#L293). True if value is `-Infinity` or `Infinity`. ### `function isBigInt` -Links: [source](fpx.mjs#L28); [test/example](test/test.mjs#L320). +Links: [source](fpx.mjs#L28); [test/example](test/test.mjs#L308). True if value is a primitive [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). False for all other inputs, including `BigInt` object wrappers. ### `function isStr` -Links: [source](fpx.mjs#L29); [test/example](test/test.mjs#L339). +Links: [source](fpx.mjs#L29); [test/example](test/test.mjs#L327). Same as `typeof val === 'string'`. True if value is a primitive string. ### `function isSym` -Links: [source](fpx.mjs#L30); [test/example](test/test.mjs#L346). +Links: [source](fpx.mjs#L30); [test/example](test/test.mjs#L334). Same as `typeof val === 'symbol'`. True if value is a primitive symbol. ### `function isKey` -Links: [source](fpx.mjs#L31); [test/example](test/test.mjs#L353). +Links: [source](fpx.mjs#L31); [test/example](test/test.mjs#L341). True if value qualifies as a dictionary key. True for all primitives excluding garbage values via [#`isJunk`](#function-isjunk). ### `function isJunk` -Links: [source](fpx.mjs#L32); [test/example](test/test.mjs#L373). +Links: [source](fpx.mjs#L32); [test/example](test/test.mjs#L361). True for garbage values: [#nil](#function-isnil), [#`NaN`](#function-isnan), [#`±Infinity`](#function-isinf). ### `function isComp` -Links: [source](fpx.mjs#L33); [test/example](test/test.mjs#L388). +Links: [source](fpx.mjs#L33); [test/example](test/test.mjs#L376). True if value is "composite" / "compound" / "complex". Opposite of [#`isPrim`](#function-isprim). Definition: @@ -476,19 +480,43 @@ function isComp(val) {return isObj(val) || isFun(val)} ### `function isPrim` -Links: [source](fpx.mjs#L34); [test/example](test/test.mjs#L402). +Links: [source](fpx.mjs#L34); [test/example](test/test.mjs#L390). True if value is a JS primitive: not an object, not a function. Opposite of [#`isComp`](#function-iscomp). ### `function isFun` -Links: [source](fpx.mjs#L35); [test/example](test/test.mjs#L416). +Links: [source](fpx.mjs#L35); [test/example](test/test.mjs#L404). -Same as `typeof val === 'function'`. True if value is a function. +Same as `typeof val === 'function'`. True if value is any function, regardless of its type (arrow, async, generator, etc.). + +### `function isFunSync` + +Links: [source](fpx.mjs#L36); [test/example](test/test.mjs#L428). + +True if the input is a normal sync function. False for generator functions or async functions. + +### `function isFunGen` + +Links: [source](fpx.mjs#L37); [test/example](test/test.mjs#L438). + +True if the input is a sync generator function. False for normal sync functions and async functions. + +### `function isFunAsync` + +Links: [source](fpx.mjs#L38); [test/example](test/test.mjs#L448). + +True if the input is an async non-generator function. False for sync functions, generator functions, or async generator functions. + +### `function isFunAsyncGen` + +Links: [source](fpx.mjs#L39); [test/example](test/test.mjs#L458). + +True if the input is an async generator function. False for sync functions and async non-generator functions. ### `function isObj` -Links: [source](fpx.mjs#L36); [test/example](test/test.mjs#L423). +Links: [source](fpx.mjs#L40); [test/example](test/test.mjs#L468). Same as `typeof val === 'object' && val !== null`. True for any JS object: plain dict, array, various other classes. Doesn't include functions, even though JS functions are extensible objects. @@ -498,13 +526,13 @@ For plain objects used as dictionaries, see [#`isDict`](#function-isdict). For f ### `function isStruct` -Links: [source](fpx.mjs#L37); [test/example](test/test.mjs#L439). +Links: [source](fpx.mjs#L41); [test/example](test/test.mjs#L484). True if value is a non-iterable object. Excludes both [#sync iterables](#function-isiter) and [#async iterables](#function-isiterasync). Note that [#dicts](#function-isdict) are automatically structs, but not all structs are dicts. ### `function isArr` -Links: [source](fpx.mjs#L38); [test/example](test/test.mjs#L456). +Links: [source](fpx.mjs#L42); [test/example](test/test.mjs#L501). Alias for [`Array.isArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray). Used internally for all array checks. @@ -512,85 +540,85 @@ True if value is an instance of [`Array`](https://developer.mozilla.org/en-US/do ### `function isReg` -Links: [source](fpx.mjs#L39); [test/example](test/test.mjs#L468). +Links: [source](fpx.mjs#L43); [test/example](test/test.mjs#L513). True if value is an instance of [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) or its subclass. ### `function isDate` -Links: [source](fpx.mjs#L40); [test/example](test/test.mjs#L476). +Links: [source](fpx.mjs#L44); [test/example](test/test.mjs#L521). True of value is an instance of [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). Most of the time you should prefer [#`isValidDate`](#function-isvaliddate). ### `function isValidDate` -Links: [source](fpx.mjs#L41); [test/example](test/test.mjs#L484). +Links: [source](fpx.mjs#L45); [test/example](test/test.mjs#L529). True of value is an instance of [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) and its timestamp is [#finite](#function-isfin) rather than `NaN`. ### `function isInvalidDate` -Links: [source](fpx.mjs#L42); [test/example](test/test.mjs#L491). +Links: [source](fpx.mjs#L46); [test/example](test/test.mjs#L536). True of value is an instance of [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) representing an invalid date whose timestamp is `NaN`. ### `function isSet` -Links: [source](fpx.mjs#L43); [test/example](test/test.mjs#L498). +Links: [source](fpx.mjs#L47); [test/example](test/test.mjs#L543). True if value is an instance of [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) or its subclass. ### `function isMap` -Links: [source](fpx.mjs#L44); [test/example](test/test.mjs#L508). +Links: [source](fpx.mjs#L48); [test/example](test/test.mjs#L553). True if value is an instance of [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) or its subclass. ### `function isPromise` -Links: [source](fpx.mjs#L45); [test/example](test/test.mjs#L518). +Links: [source](fpx.mjs#L49); [test/example](test/test.mjs#L563). True if the value satisfies the ES2015 [promise interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). ### `function isIter` -Links: [source](fpx.mjs#L46); [test/example](test/test.mjs#L527). +Links: [source](fpx.mjs#L50); [test/example](test/test.mjs#L572). True if the value satisfies the ES2015 [sync iterable interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols). For _iterator_ rather than _iterable_, use [#`isIterator`](#function-isiterator). ### `function isIterAsync` -Links: [source](fpx.mjs#L47); [test/example](test/test.mjs#L553). +Links: [source](fpx.mjs#L51); [test/example](test/test.mjs#L598). True if the value satisfies the ES2015 [async iterable interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of). For _iterator_ rather than _iterable_, use [#`isIteratorAsync`](#function-isiteratorasync). ### `function isIterator` -Links: [source](fpx.mjs#L48); [test/example](test/test.mjs#L570). +Links: [source](fpx.mjs#L52); [test/example](test/test.mjs#L615). True if the value satisfies the ES2015 [sync iterator interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols). For _iterable_ rather than _iterator_, use [#`isIter`](#function-isiter). ### `function isIteratorAsync` -Links: [source](fpx.mjs#L49); [test/example](test/test.mjs#L596). +Links: [source](fpx.mjs#L53); [test/example](test/test.mjs#L641). True if the value satisfies the ES2015 [async iterator interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of). For _iterable_ rather than _iterator_, use [#`isIterAsync`](#function-isiterasync). ### `function isGen` -Links: [source](fpx.mjs#L50); [test/example](test/test.mjs#L622). +Links: [source](fpx.mjs#L54); [test/example](test/test.mjs#L667). True if value is a [#sync iterator](#function-isiterator) created by calling a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator). ### `function isCls` -Links: [source](fpx.mjs#L51); [test/example](test/test.mjs#L682). +Links: [source](fpx.mjs#L55); [test/example](test/test.mjs#L727). True if the input is a function with a prototype, likely to be a class. False for arrow functions such as `() => {}`, which don't have a prototype. ### `function isDict` -Links: [source](fpx.mjs#L52); [test/example](test/test.mjs#L694). +Links: [source](fpx.mjs#L56); [test/example](test/test.mjs#L739). True for a "plain object" created via `{...}` or `Object.create(null)`. False for any other input, including instances of any class other than `Object`. Roughly equivalent to Lodash's `_.isPlainObject`. @@ -598,13 +626,13 @@ See [#`isStruct`](#function-isstruct) for a more general definition of a non-ite ### `function isList` -Links: [source](fpx.mjs#L53); [test/example](test/test.mjs#L707). +Links: [source](fpx.mjs#L57); [test/example](test/test.mjs#L752). True for any array-like such as: `[]`, `arguments`, `TypedArray`, `NodeList`, etc. Used internally for most list checks. Note that _primitive strings are not considered lists_. ### `function isSeq` -Links: [source](fpx.mjs#L54); [test/example](test/test.mjs#L722). +Links: [source](fpx.mjs#L58); [test/example](test/test.mjs#L767). True for any of: @@ -617,7 +645,7 @@ Many Fpx functions support arbitrary data structures compatible with [#`values`] ### `function isInst` -Links: [source](fpx.mjs#L58); [test/example](test/test.mjs#L739). +Links: [source](fpx.mjs#L63); [test/example](test/test.mjs#L784). Signature: `(val, Cls) => bool`. @@ -625,31 +653,31 @@ Same as `instanceof` but _does not_ implicitly convert the operand to an object. ### `function hasMeth` -Links: [source](fpx.mjs#L63); [test/example](test/test.mjs#L755). +Links: [source](fpx.mjs#L68); [test/example](test/test.mjs#L800). True if the the given value has the given named method. Safe to call on primitives such as `null`. Always false for primitives. ### `function isListOf` -Links: [source](fpx.mjs#L65); [test/example](test/test.mjs#L775). +Links: [source](fpx.mjs#L70); [test/example](test/test.mjs#L820). Shortcut for `isList(val) && every(val, fun)`. True if the input is a list of values that satisfy the given predicate function. ### `function isEmpty` -Links: [source](fpx.mjs#L70); [test/example](test/test.mjs#L794). +Links: [source](fpx.mjs#L75); [test/example](test/test.mjs#L839). True if the input is an empty collection such as list, set, map, or a primitive such as `null`. False for any other non-primitive. Treating primitives as "empty" is consistent with other Fpx functions that operate on collections. ### `function isVac` -Links: [source](fpx.mjs#L77); [test/example](test/test.mjs#L811). +Links: [source](fpx.mjs#L82); [test/example](test/test.mjs#L856). Short for "is vacuous" or "is vacated". Could also be called "is falsy deep". True if the input is [#falsy](#function-falsy) or a [#list](#function-islist) where all values are vacuous, recursively. Does not iterate non-lists. Also see complementary function [#`vac`](#function-vac). ### `function req` -Links: [source](fpx.mjs#L84); [test/example](test/test.mjs#L849). +Links: [source](fpx.mjs#L89); [test/example](test/test.mjs#L894). Signature: `(val, test) => val` where `test: val => bool`. @@ -665,13 +693,13 @@ f.req('str', f.isFun) ### `function opt` -Links: [source](fpx.mjs#L92); [test/example](test/test.mjs#L870). +Links: [source](fpx.mjs#L97); [test/example](test/test.mjs#L915). Short for "optional". If `val` is [#non-nil](#function-issome), uses [#`req`](#function-req) to validate it. Returns `val` as-is. ### `function reqInst` -Links: [source](fpx.mjs#L103); [test/example](test/test.mjs#L896). +Links: [source](fpx.mjs#L108); [test/example](test/test.mjs#L941). Signature: `(val, Cls) => val`. @@ -679,13 +707,13 @@ Short for "require instance". Asserts that `val` is an instance of the given cla ### `function optInst` -Links: [source](fpx.mjs#L111); [test/example](test/test.mjs#L918). +Links: [source](fpx.mjs#L116); [test/example](test/test.mjs#L963). Short for "optional instance". If `val` is [#non-nil](#function-issome), uses [#`reqInst`](#function-reqinst) to validate it. Returns `val` as-is. ### `function only` -Links: [source](fpx.mjs#L116); [test/example](test/test.mjs#L950). +Links: [source](fpx.mjs#L121); [test/example](test/test.mjs#L995). Signature: `(val, test) => val` where `test: val => bool`. @@ -693,7 +721,7 @@ Type filtering utility. If `val` satisfies the given test function, returns `val ### `function arrOf` -Links: [source](fpx.mjs#L118); [test/example](test/test.mjs#L977). +Links: [source](fpx.mjs#L123); [test/example](test/test.mjs#L1022). Signature: `(seq, test) => A[]` where `test: A => true`. @@ -701,61 +729,61 @@ Shortcut. Converts the input to an array via [#`arr`](#function-arr) and asserts ### `function prim` -Links: [source](fpx.mjs#L125); [test/example](test/test.mjs#L989). +Links: [source](fpx.mjs#L130); [test/example](test/test.mjs#L1034). Shortcut for asserting that the input is a primitive. Throws for non-primitive inputs. Returns the input as-is. ### `function bool` -Links: [source](fpx.mjs#L126); [test/example](test/test.mjs#L1006). +Links: [source](fpx.mjs#L131); [test/example](test/test.mjs#L1051). Similar to `val ?? false` but `val` must be [#nil](#function-isnil) or a [#boolean](#function-isbool), otherwise throws. ### `function num` -Links: [source](fpx.mjs#L127); [test/example](test/test.mjs#L1021). +Links: [source](fpx.mjs#L132); [test/example](test/test.mjs#L1066). Similar to `val ?? 0` but `val` must be [#nil](#function-isnil) or a [#number](#function-isnum), otherwise throws. ### `function fin` -Links: [source](fpx.mjs#L128); [test/example](test/test.mjs#L1037). +Links: [source](fpx.mjs#L133); [test/example](test/test.mjs#L1082). Similar to `val ?? 0` but `val` must be [#nil](#function-isnil) or a [#finite number](#function-isfin), otherwise throws. ### `function int` -Links: [source](fpx.mjs#L129); [test/example](test/test.mjs#L1053). +Links: [source](fpx.mjs#L134); [test/example](test/test.mjs#L1098). Similar to `val ?? 0` but `val` must be [#nil](#function-isnil) or an [#integer](#function-isint), otherwise throws. ### `function nat` -Links: [source](fpx.mjs#L130); [test/example](test/test.mjs#L1072). +Links: [source](fpx.mjs#L135); [test/example](test/test.mjs#L1117). Similar to `val ?? 0` but `val` must be [#nil](#function-isnil) or a [#natural number](#function-isnat), otherwise throws. ### `function intPos` -Links: [source](fpx.mjs#L131); [test/example](test/test.mjs#L1092). +Links: [source](fpx.mjs#L136); [test/example](test/test.mjs#L1137). Similar to `val ?? 0` but `val` must be [#nil](#function-isnil) or a [#positive integer](#function-isintpos), otherwise throws. ### `function str` -Links: [source](fpx.mjs#L132); [test/example](test/test.mjs#L1112). +Links: [source](fpx.mjs#L137); [test/example](test/test.mjs#L1157). Similar to `val ?? ''` but `val` must be [#nil](#function-isnil) or a [#string](#function-isstr), otherwise throws. ### `function dict` -Links: [source](fpx.mjs#L133); [test/example](test/test.mjs#L1125). +Links: [source](fpx.mjs#L138); [test/example](test/test.mjs#L1170). Similar to `val ?? Object.create(null)` but `val` must be [#nil](#function-isnil) or a [#dict](#function-isdict), otherwise throws. ### `function struct` -Links: [source](fpx.mjs#L134); [test/example](test/test.mjs#L1143). +Links: [source](fpx.mjs#L139); [test/example](test/test.mjs#L1188). Similar to `val ?? Object.create(null)` but `val` must be [#nil](#function-isnil) or a [#struct](#function-isstruct), otherwise throws. @@ -763,7 +791,7 @@ Most Fpx functions that operate on data structures, such as [#`filter`](#functio ### `function inst` -Links: [source](fpx.mjs#L135); [test/example](test/test.mjs#L1161). +Links: [source](fpx.mjs#L140); [test/example](test/test.mjs#L1206). Signature: `(any, typeof A) => A`. @@ -785,109 +813,109 @@ newInst === oldInst ### `function add` -Links: [source](fpx.mjs#L143); [test/example](test/test.mjs#L1194). +Links: [source](fpx.mjs#L148); [test/example](test/test.mjs#L1239). Same as `+`. ### `function sub` -Links: [source](fpx.mjs#L144); [test/example](test/test.mjs#L1200). +Links: [source](fpx.mjs#L149); [test/example](test/test.mjs#L1245). Same as `-`. ### `function mul` -Links: [source](fpx.mjs#L145); [test/example](test/test.mjs#L1206). +Links: [source](fpx.mjs#L150); [test/example](test/test.mjs#L1251). Same as `*`. ### `function div` -Links: [source](fpx.mjs#L146); [test/example](test/test.mjs#L1212). +Links: [source](fpx.mjs#L151); [test/example](test/test.mjs#L1257). Same as `/`. ### `function rem` -Links: [source](fpx.mjs#L147); [test/example](test/test.mjs#L1218). +Links: [source](fpx.mjs#L152); [test/example](test/test.mjs#L1263). Same as `%`. ### `function lt` -Links: [source](fpx.mjs#L148); [test/example](test/test.mjs#L1226). +Links: [source](fpx.mjs#L153); [test/example](test/test.mjs#L1271). Same as `<`. ### `function gt` -Links: [source](fpx.mjs#L149); [test/example](test/test.mjs#L1237). +Links: [source](fpx.mjs#L154); [test/example](test/test.mjs#L1282). Same as `>`. ### `function lte` -Links: [source](fpx.mjs#L150); [test/example](test/test.mjs#L1248). +Links: [source](fpx.mjs#L155); [test/example](test/test.mjs#L1293). Same as `<=`. ### `function gte` -Links: [source](fpx.mjs#L151); [test/example](test/test.mjs#L1259). +Links: [source](fpx.mjs#L156); [test/example](test/test.mjs#L1304). Same as `>=`. ### `function neg` -Links: [source](fpx.mjs#L152); [test/example](test/test.mjs#L1270). +Links: [source](fpx.mjs#L157); [test/example](test/test.mjs#L1315). Arithmetic negation. Same as unary `-`. ### `function inc` -Links: [source](fpx.mjs#L153); [test/example](test/test.mjs#L1282). +Links: [source](fpx.mjs#L158); [test/example](test/test.mjs#L1327). Increments by `1`. ### `function dec` -Links: [source](fpx.mjs#L154); [test/example](test/test.mjs#L1290). +Links: [source](fpx.mjs#L159); [test/example](test/test.mjs#L1335). Decrements by `1`. ### `function nop` -Links: [source](fpx.mjs#L158); [test/example](test/test.mjs#L1298). +Links: [source](fpx.mjs#L163); [test/example](test/test.mjs#L1343). Empty function. Functional equivalent of `;` or `undefined`. Sometimes useful with higher-order functions. ### `function True` -Links: [source](fpx.mjs#L159); [test/example](test/test.mjs#L1304). +Links: [source](fpx.mjs#L164); [test/example](test/test.mjs#L1349). Always returns `true`. Sometimes useful with higher order functions. ### `function False` -Links: [source](fpx.mjs#L160); [test/example](test/test.mjs#L1312). +Links: [source](fpx.mjs#L165); [test/example](test/test.mjs#L1357). Always returns `false`. Sometimes useful with higher order functions. ### `function id` -Links: [source](fpx.mjs#L161); [test/example](test/test.mjs#L1320). +Links: [source](fpx.mjs#L166); [test/example](test/test.mjs#L1365). Identity function: returns its first argument unchanged. Sometimes useful with higher-order functions. ### `function di` -Links: [source](fpx.mjs#L162); [test/example](test/test.mjs#L1327). +Links: [source](fpx.mjs#L167); [test/example](test/test.mjs#L1372). Returns its _second_ argument unchanged. Sometimes useful with higher-order functions. ### `function val` -Links: [source](fpx.mjs#L163); [test/example](test/test.mjs#L1334). +Links: [source](fpx.mjs#L168); [test/example](test/test.mjs#L1379). Takes a value and creates a function that always returns that value. Sometimes useful with higher order functions. @@ -903,7 +931,7 @@ constant(`this input is ignored`) ### `function panic` -Links: [source](fpx.mjs#L164); [test/example](test/test.mjs#L1348). +Links: [source](fpx.mjs#L169); [test/example](test/test.mjs#L1393). Same as `throw` but an expression rather than a statement. Also sometimes useful with higher-order functions. @@ -913,43 +941,43 @@ const x = someTest ? someValue : f.panic(Error(`unreachable`)) ### `function jsonDecode` -Links: [source](fpx.mjs#L165); [test/example](test/test.mjs#L1370). +Links: [source](fpx.mjs#L170); [test/example](test/test.mjs#L1415). Similar to [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) but sane rather than insane. If the input is [#nil](#function-isnil) or an empty string, returns `null`. Otherwise the input must be a primitive string. Throws on other inputs, without trying to stringify them. ### `function jsonEncode` -Links: [source](fpx.mjs#L166); [test/example](test/test.mjs#L1385). +Links: [source](fpx.mjs#L171); [test/example](test/test.mjs#L1430). Similar to [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) but sane rather than insane. Equivalent to `JSON.stringify(val ?? null)`. If the input is `undefined`, returns `'null'` (string) rather than `undefined` (nil). Output is _always_ a valid JSON string. ### `function show` -Links: [source](fpx.mjs#L168); [test/example](test/test.mjs#L44). +Links: [source](fpx.mjs#L173); [test/example](test/test.mjs#L44). Returns a string describing the value. When relevant, prints data as JSON to avoid the dreaded `[object Object]`. Prints functions as their names or source code. Convenient for interpolating things into error messages. Used internally in assertion functions such as [#`req`](#function-req). ### `function npo` -Links: [source](fpx.mjs#L177); [test/example](test/test.mjs#L1399). +Links: [source](fpx.mjs#L182); [test/example](test/test.mjs#L1444). Short for "null-prototype object". Syntactic shortcut for `Object.create(null)`. ### `function hasOwn` -Links: [source](fpx.mjs#L179); [test/example](test/test.mjs#L1405). +Links: [source](fpx.mjs#L184); [test/example](test/test.mjs#L1450). Same as [`Object.prototype.hasOwnProperty`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) but shorter and safe to call on primitives. Always false for primitives. ### `function hasOwnEnum` -Links: [source](fpx.mjs#L184); [test/example](test/test.mjs#L1419). +Links: [source](fpx.mjs#L189); [test/example](test/test.mjs#L1464). Same as [`Object.prototype.propertyIsEnumerable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable) but shorter and safe to call on primitives. Always false for primitives. ### `function mut` -Links: [source](fpx.mjs#L189); [test/example](test/test.mjs#L1434). +Links: [source](fpx.mjs#L194); [test/example](test/test.mjs#L1479). Signature: `(tar, src) => tar`. @@ -965,7 +993,7 @@ Similar to [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaSc ### `function mapDict` -Links: [source](fpx.mjs#L197); [test/example](test/test.mjs#L1557). +Links: [source](fpx.mjs#L202); [test/example](test/test.mjs#L1602). Signature: `({[Key: A]}, A => B) => {[Key: B]}`. @@ -973,7 +1001,7 @@ Similar to [#`map`](#function-map) but for dicts. Creates a version of the given ### `function pick` -Links: [source](fpx.mjs#L204); [test/example](test/test.mjs#L1572). +Links: [source](fpx.mjs#L209); [test/example](test/test.mjs#L1617). Signature: `({[Key: A]}, A => bool) => {[Key: A]}`. @@ -981,7 +1009,7 @@ Similar to [#`filter`](#function-filter) but for dicts. Returns a version of the ### `function omit` -Links: [source](fpx.mjs#L214); [test/example](test/test.mjs#L1582). +Links: [source](fpx.mjs#L219); [test/example](test/test.mjs#L1627). Signature: `({[Key: A]}, A => bool) => {[Key: A]}`. @@ -989,7 +1017,7 @@ Similar to [#`reject`](#function-reject) but for dicts. Returns a version of the ### `function pickKeys` -Links: [source](fpx.mjs#L216); [test/example](test/test.mjs#L1592). +Links: [source](fpx.mjs#L221); [test/example](test/test.mjs#L1637). Signature: `({[Key: A]}, keys) => {[Key: A]}`. @@ -997,7 +1025,7 @@ Returns a version of the given dict, keeping only the given properties. Keys can ### `function omitKeys` -Links: [source](fpx.mjs#L223); [test/example](test/test.mjs#L1610). +Links: [source](fpx.mjs#L228); [test/example](test/test.mjs#L1655). Signature: `({[Key: A]}, keys) => {[Key: A]}`. @@ -1005,19 +1033,19 @@ Returns a version of the given dict without the given properties. Keys must be a ### `function more` -Links: [source](fpx.mjs#L233); [test/example](test/test.mjs#L1628). +Links: [source](fpx.mjs#L238); [test/example](test/test.mjs#L1673). Takes an [#iterator](#function-isiterator), consumes one value, and returns true if the iterator is not yet finished. Shortcut for `val.next().done === false`. ### `function alloc` -Links: [source](fpx.mjs#L234); [test/example](test/test.mjs#L1638). +Links: [source](fpx.mjs#L239); [test/example](test/test.mjs#L1683). Shortcut for allocating an array with a sanity check. Same as `Array(N)` but ensures that the input is a [#natural number](#function-nat) suitable for array length. Avoids unintentionally passing any non-natural input such as `Array(-1)`. Allows [#nil](#function-isnil), replacing it with `0`. ### `function arr` -Links: [source](fpx.mjs#L235); [test/example](test/test.mjs#L1647). +Links: [source](fpx.mjs#L240); [test/example](test/test.mjs#L1692). Converts an arbitrary [#sequence](#function-isseq) to an array. Allows the following inputs: @@ -1030,19 +1058,19 @@ Unlike [#`values`](#function-values), `arr` rejects other inputs such as non-nil ### `function arrCopy` -Links: [source](fpx.mjs#L236); [test/example](test/test.mjs#L1679). +Links: [source](fpx.mjs#L241); [test/example](test/test.mjs#L1724). Like [#`arr`](#function-arr), converts an arbitrary sequence to an array. Unlike `arr,` always makes a copy. Mutating the output doesn't affect the original. ### `function slice` -Links: [source](fpx.mjs#L241); [test/example](test/test.mjs#L1693). +Links: [source](fpx.mjs#L246); [test/example](test/test.mjs#L1738). Like [`Array.prototype.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) but allows arbitrary [#sequences](#function-isseq) compatible with [#`arr`](#function-arr). ### `function keys` -Links: [source](fpx.mjs#L250); [test/example](test/test.mjs#L1725). +Links: [source](fpx.mjs#L255); [test/example](test/test.mjs#L1770). Takes an arbitrary input and returns an array of its keys: @@ -1055,7 +1083,7 @@ Takes an arbitrary input and returns an array of its keys: ### `function values` -Links: [source](fpx.mjs#L267); [test/example](test/test.mjs#L1748). +Links: [source](fpx.mjs#L272); [test/example](test/test.mjs#L1793). Takes an arbitrary input and returns an array of its values: @@ -1069,13 +1097,13 @@ Takes an arbitrary input and returns an array of its values: ### `function valuesCopy` -Links: [source](fpx.mjs#L290); [test/example](test/test.mjs#L1768). +Links: [source](fpx.mjs#L295); [test/example](test/test.mjs#L1813). Variant of [#`values`](#function-values) that always makes a copy. Mutating the output doesn't affect the original. ### `function entries` -Links: [source](fpx.mjs#L292); [test/example](test/test.mjs#L1790). +Links: [source](fpx.mjs#L297); [test/example](test/test.mjs#L1835). Takes an arbitrary input and returns an array of its entries (key-value tuples): @@ -1088,19 +1116,19 @@ Takes an arbitrary input and returns an array of its entries (key-value tuples): ### `function reify` -Links: [source](fpx.mjs#L318); [test/example](test/test.mjs#L1809). +Links: [source](fpx.mjs#L323); [test/example](test/test.mjs#L1854). Takes an arbitrary value and attempts to deeply materialize it. Any [#iterators](#function-iterator), or [#lists](#function-islist) that contain iterators, or lists that contain lists that contain iterators, etc., are converted to arrays. Does not inspect other data structures such as [#sets](#function-isset) or [#dicts](#function-isdict). ### `function vac` -Links: [source](fpx.mjs#L322); [test/example](test/test.mjs#L1834). +Links: [source](fpx.mjs#L327); [test/example](test/test.mjs#L1879). Complements [#`isVac`](#function-isvac). Returns `undefined` if the input is vacuous, otherwise returns the input as-is. ### `function indexOf` -Links: [source](fpx.mjs#L324); [test/example](test/test.mjs#L1841). +Links: [source](fpx.mjs#L329); [test/example](test/test.mjs#L1886). Like [`Array.prototype.indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf). Differences: @@ -1109,7 +1137,7 @@ Like [`Array.prototype.indexOf`](https://developer.mozilla.org/en-US/docs/Web/Ja ### `function includes` -Links: [source](fpx.mjs#L332); [test/example](test/test.mjs#L1862). +Links: [source](fpx.mjs#L337); [test/example](test/test.mjs#L1907). Like [`Array.prototype.includes`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes). Differences: @@ -1118,7 +1146,7 @@ Like [`Array.prototype.includes`](https://developer.mozilla.org/en-US/docs/Web/J ### `function concat` -Links: [source](fpx.mjs#L333); [test/example](test/test.mjs#L1881). +Links: [source](fpx.mjs#L338); [test/example](test/test.mjs#L1926). Like [`Array.prototype.concat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat). Differences: @@ -1131,19 +1159,19 @@ Note: for individual elements, use [#`append`](#function-append) and ### `function append` -Links: [source](fpx.mjs#L334); [test/example](test/test.mjs#L1899). +Links: [source](fpx.mjs#L339); [test/example](test/test.mjs#L1944). Takes an arbitrary iterable compatible with [#`values`](#function-values) and appends an arbitrary value, returning the resulting array. ### `function prepend` -Links: [source](fpx.mjs#L335); [test/example](test/test.mjs#L1914). +Links: [source](fpx.mjs#L340); [test/example](test/test.mjs#L1959). Takes an arbitrary iterable compatible with [#`values`](#function-values) and prepends an arbitrary value, returning the resulting array. ### `function len` -Links: [source](fpx.mjs#L337); [test/example](test/test.mjs#L1949). +Links: [source](fpx.mjs#L342); [test/example](test/test.mjs#L1994). Universal length measurement: @@ -1156,13 +1184,13 @@ Universal length measurement: ### `function hasLen` -Links: [source](fpx.mjs#L361); [test/example](test/test.mjs#L1953). +Links: [source](fpx.mjs#L366); [test/example](test/test.mjs#L1998). Shortcut for [#`len`](#function-len) > 0. ### `function each` -Links: [source](fpx.mjs#L363); [test/example](test/test.mjs#L1985). +Links: [source](fpx.mjs#L368); [test/example](test/test.mjs#L2030). Signature: `(Iter, A => void) => void`. @@ -1174,7 +1202,7 @@ Similar to `Array.prototype.forEach`, `Set.prototype.forEach`, `Map.prototype.fo ### `function map` -Links: [source](fpx.mjs#L368); [test/example](test/test.mjs#L2006). +Links: [source](fpx.mjs#L373); [test/example](test/test.mjs#L2051). Signature: `(Iter, A => B) => B[]`. @@ -1186,7 +1214,7 @@ Similar to [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/ ### `function mapMut` -Links: [source](fpx.mjs#L370); [test/example](test/test.mjs#L2039). +Links: [source](fpx.mjs#L375); [test/example](test/test.mjs#L2084). Similar to [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Differences: @@ -1197,13 +1225,13 @@ For a non-mutating version, see [#`map`](#function-map). ### `function mapCompact` -Links: [source](fpx.mjs#L378); [test/example](test/test.mjs#L2055). +Links: [source](fpx.mjs#L383); [test/example](test/test.mjs#L2100). Equivalent to `f.compact(f.map(val, fun))`. See [#`map`](#function-map) and [#`compact`](#function-compact). ### `function filter` -Links: [source](fpx.mjs#L380); [test/example](test/test.mjs#L2068). +Links: [source](fpx.mjs#L385); [test/example](test/test.mjs#L2113). Signature: `(Iter, A => bool) => A[]`. @@ -1215,19 +1243,19 @@ Similar to [`Array.prototype.filter`](https://developer.mozilla.org/en-US/docs/W ### `function reject` -Links: [source](fpx.mjs#L387); [test/example](test/test.mjs#L2084). +Links: [source](fpx.mjs#L392); [test/example](test/test.mjs#L2129). Opposite of [#`filter`](#function-filter). Equivalent to `f.filter(val, f.not(fun))`. ### `function compact` -Links: [source](fpx.mjs#L389); [test/example](test/test.mjs#L2100). +Links: [source](fpx.mjs#L394); [test/example](test/test.mjs#L2145). Equivalent to `f.filter(val, f.id)`. Takes an arbitrary iterable and returns an array of its truthy [#`values`](#function-values), discarding falsy values. ### `function remove` -Links: [source](fpx.mjs#L395); [test/example](test/test.mjs#L2112). +Links: [source](fpx.mjs#L400); [test/example](test/test.mjs#L2157). Signature: `(Iter, A) => A[]`. @@ -1235,7 +1263,7 @@ Takes an arbitrary iterable and an element to remove. Returns an array of the it ### `function fold` -Links: [source](fpx.mjs#L399); [test/example](test/test.mjs#L2129). +Links: [source](fpx.mjs#L404); [test/example](test/test.mjs#L2174). Signature: `(src: Iter, acc: B, fun: (B, A) => B) => B`. @@ -1250,7 +1278,7 @@ Similar to [`Array.prototype.reduce`](https://developer.mozilla.org/en-US/docs/W ### `function find` -Links: [source](fpx.mjs#L405); [test/example](test/test.mjs#L2145). +Links: [source](fpx.mjs#L410); [test/example](test/test.mjs#L2190). Signature: `(Iter, A => bool) => A`. @@ -1262,7 +1290,7 @@ Similar to [`Array.prototype.find`](https://developer.mozilla.org/en-US/docs/Web ### `function procure` -Links: [source](fpx.mjs#L411); [test/example](test/test.mjs#L2160). +Links: [source](fpx.mjs#L416); [test/example](test/test.mjs#L2205). Signature: `(src: Iter, fun: A => B) => B`. @@ -1270,7 +1298,7 @@ Similar to [#`find`](#function-find), but returns the first truthy result of cal ### `function every` -Links: [source](fpx.mjs#L417); [test/example](test/test.mjs#L2177). +Links: [source](fpx.mjs#L422); [test/example](test/test.mjs#L2222). Signature: `(Iter, A => bool) => bool`. @@ -1282,7 +1310,7 @@ Similar to [`Array.prototype.every`](https://developer.mozilla.org/en-US/docs/We ### `function some` -Links: [source](fpx.mjs#L423); [test/example](test/test.mjs#L2196). +Links: [source](fpx.mjs#L428); [test/example](test/test.mjs#L2241). Signature: `(Iter, A => bool) => bool`. @@ -1294,37 +1322,37 @@ Similar to [`Array.prototype.some`](https://developer.mozilla.org/en-US/docs/Web ### `function head` -Links: [source](fpx.mjs#L429); [test/example](test/test.mjs#L2215). +Links: [source](fpx.mjs#L434); [test/example](test/test.mjs#L2260). Takes an arbitrary iterable compatible with [#`values`](#function-values) and returns its first element or `undefined`. ### `function last` -Links: [source](fpx.mjs#L430); [test/example](test/test.mjs#L2225). +Links: [source](fpx.mjs#L435); [test/example](test/test.mjs#L2270). Takes an arbitrary iterable compatible with [#`values`](#function-values) and returns its last element or `undefined`. ### `function init` -Links: [source](fpx.mjs#L431); [test/example](test/test.mjs#L2235). +Links: [source](fpx.mjs#L436); [test/example](test/test.mjs#L2280). Short for "initial". Takes an arbitrary iterable compatible with [#`values`](#function-values) and returns an array of all its values except last. ### `function tail` -Links: [source](fpx.mjs#L432); [test/example](test/test.mjs#L2245). +Links: [source](fpx.mjs#L437); [test/example](test/test.mjs#L2290). Takes an arbitrary iterable compatible with [#`values`](#function-values) and returns an array of all its values except first. ### `function take` -Links: [source](fpx.mjs#L433); [test/example](test/test.mjs#L2255). +Links: [source](fpx.mjs#L438); [test/example](test/test.mjs#L2300). Takes an arbitrary iterable compatible with [#`values`](#function-values) and returns N values from the start. ### `function count` -Links: [source](fpx.mjs#L435); [test/example](test/test.mjs#L2287). +Links: [source](fpx.mjs#L440); [test/example](test/test.mjs#L2332). Signature: `(src: Iter, fun: A => B) => nat`. @@ -1332,7 +1360,7 @@ Takes an arbitrary iterable compatible with [#`values`](#function-values), calls ### `function compare` -Links: [source](fpx.mjs#L443); [test/example](test/test.mjs#L2302). +Links: [source](fpx.mjs#L448); [test/example](test/test.mjs#L2347). Signature: `(a, b) => -1 | 0 | 1`. @@ -1340,7 +1368,7 @@ Equivalent to the [default JS sort comparison algorithm](https://tc39.github.io/ ### `function compareFin` -Links: [source](fpx.mjs#L454); [test/example](test/test.mjs#L2312). +Links: [source](fpx.mjs#L459); [test/example](test/test.mjs#L2357). Signature: `(a, b) => -1 | 0 | 1` where arguments are [#nil](#function-isnil) or [#finite](#function-isfin). @@ -1348,7 +1376,7 @@ Sort comparison for finite numbers. Usable for [`Array.prototype.sort`](https:// ### `function sort` -Links: [source](fpx.mjs#L462); [test/example](test/test.mjs#L2324). +Links: [source](fpx.mjs#L467); [test/example](test/test.mjs#L2369). Signature: `(src: Iter, fun?: (prev: A, next: A) => -1 | 0 | 1) => A[]`. @@ -1362,7 +1390,7 @@ The comparison function is optional. If omitted, default JS sorting is used. ### `function reverse` -Links: [source](fpx.mjs#L463); [test/example](test/test.mjs#L2356). +Links: [source](fpx.mjs#L468); [test/example](test/test.mjs#L2401). Similar to [`Array.prototype.reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse). Differences: @@ -1372,7 +1400,7 @@ Similar to [`Array.prototype.reverse`](https://developer.mozilla.org/en-US/docs/ ### `function index` -Links: [source](fpx.mjs#L465); [test/example](test/test.mjs#L2374). +Links: [source](fpx.mjs#L470); [test/example](test/test.mjs#L2419). Signature: `(Iter, A => Key | any) => {[Key: A]}`. @@ -1382,7 +1410,7 @@ Similar to Lodash's `_.keyBy`. Compare [#`group`](#function-group) which keeps a ### `function group` -Links: [source](fpx.mjs#L475); [test/example](test/test.mjs#L2419). +Links: [source](fpx.mjs#L480); [test/example](test/test.mjs#L2464). Signature: `(Iter, A => Key | any) => {[Key: A[]]}`. @@ -1392,7 +1420,7 @@ Compare [#`index`](#function-index), which keeps only the last value for each gr ### `function partition` -Links: [source](fpx.mjs#L485); [test/example](test/test.mjs#L2445). +Links: [source](fpx.mjs#L490); [test/example](test/test.mjs#L2490). Signature: `(Iter, A => bool) => [A[], A[]]`. @@ -1400,7 +1428,7 @@ Partitions the [#`values`](#function-values) of a given iterable, returning a tu ### `function sum` -Links: [source](fpx.mjs#L493); [test/example](test/test.mjs#L2462). +Links: [source](fpx.mjs#L498); [test/example](test/test.mjs#L2507). Signature: `(Iter) => fin`. @@ -1408,7 +1436,7 @@ Sums all finite [#`values`](#function-values) of an arbitrary iterable, ignoring ### `function zip` -Links: [source](fpx.mjs#L498); [test/example](test/test.mjs#L2473). +Links: [source](fpx.mjs#L503); [test/example](test/test.mjs#L2518). Signature: `(Iter<[Key, A]>) => {[Key: A]}`. @@ -1422,13 +1450,13 @@ Similar to [`Object.fromEntries`](https://developer.mozilla.org/en-US/docs/Web/J ### `function mapFrom` -Links: [source](fpx.mjs#L504); [test/example](test/test.mjs#L2490). +Links: [source](fpx.mjs#L509); [test/example](test/test.mjs#L2535). Syntactic shortcut for creating a `Map` with inline keys and values. Shorter and less noisy than either `new Map` with an array of entries or chained `.set` calls. ### `function range` -Links: [source](fpx.mjs#L511); [test/example](test/test.mjs#L2497). +Links: [source](fpx.mjs#L516); [test/example](test/test.mjs#L2542). Signature: `(min: int, max: int) => int[]`. @@ -1436,7 +1464,7 @@ Returns an array of contiguous integers in the range of `[min, max)`. The first ### `function span` -Links: [source](fpx.mjs#L522); [test/example](test/test.mjs#L2512). +Links: [source](fpx.mjs#L527); [test/example](test/test.mjs#L2557). Signature: `nat => nat[]`. @@ -1444,7 +1472,7 @@ Returns an array of the given length, where values are integers from 0. Shortcut ### `function times` -Links: [source](fpx.mjs#L523); [test/example](test/test.mjs#L2523). +Links: [source](fpx.mjs#L528); [test/example](test/test.mjs#L2568). Signature: `(len: nat, fun: nat => A) => A[]`. @@ -1452,7 +1480,7 @@ Takes an array length and a mapping function. Returns an array of the given leng ### `function repeat` -Links: [source](fpx.mjs#L524); [test/example](test/test.mjs#L2544). +Links: [source](fpx.mjs#L529); [test/example](test/test.mjs#L2589). Signature: `(len: nat, val: A) => A[]`. @@ -1460,7 +1488,7 @@ Returns an array of the given length where each element is the given value. Equi ### `function set` -Links: [source](fpx.mjs#L525); [test/example](test/test.mjs#L2556). +Links: [source](fpx.mjs#L530); [test/example](test/test.mjs#L2601). Converts an arbitrary input to a native [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). Similar to `new Set`. Differences: @@ -1470,7 +1498,7 @@ Converts an arbitrary input to a native [`Set`](https://developer.mozilla.org/en ### `function setCopy` -Links: [source](fpx.mjs#L526); [test/example](test/test.mjs#L2580). +Links: [source](fpx.mjs#L531); [test/example](test/test.mjs#L2625). Similar to [#`set`](#function-set): converts an arbitrary input to a set. Difference: always makes a copy. If the original was a set, it's unaffected by mutations of the output. diff --git a/test/test.mjs b/test/test.mjs index c78a72b..1bfa857 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -11,7 +11,7 @@ if (cli.bool(`v`)) t.conf.testRep = t.conf.benchRep function args() {return arguments} function arrgs(...args) {return args} function toArgs(val) {return args(...(val ?? []))} -function* gen() {} +function* gen() {throw Error(`unreachable`)} async function* agen() {throw Error(`unreachable`)} function* copygen(iter) {for (const val of iter) yield val} const inherit = Object.create @@ -113,18 +113,6 @@ t.test(function test_is() { t.ok(f.is(`one`, `one`)) }) -/* -t.example(function example_is() { - console.log(f.is(10, 20)) - console.log(f.is(10, 10)) - console.log(f.is(NaN, NaN)) -}, ` -false -true -true -`) -*/ - t.test(function test_isNil() { t.no(f.isNil(false)) @@ -415,9 +403,66 @@ t.test(function test_isPrim() { t.test(function test_isFun() { t.no(f.isFun()) - t.no(f.isFun(inherit(f.id))) - - t.ok(f.isFun(f.id)) + t.no(f.isFun(true)) + t.no(f.isFun(10)) + t.no(f.isFun(`str`)) + t.no(f.isFun([])) + t.no(f.isFun({})) + + // `val instanceof Function` would have returned `true` here. + t.no(f.isFun(inherit(() => {}))) + t.no(f.isFun(inherit(function() {}))) + t.no(f.isFun(inherit(function*() {}))) + t.no(f.isFun(inherit(async () => {}))) + t.no(f.isFun(inherit(async function() {}))) + t.no(f.isFun(inherit(async function*() {}))) + + t.ok(f.isFun(() => {})) + t.ok(f.isFun(function() {})) + t.ok(f.isFun(function*() {})) + t.ok(f.isFun(async () => {})) + t.ok(f.isFun(async function() {})) + t.ok(f.isFun(async function*() {})) +}) + +t.test(function test_isFunSync() { + t.no(f.isFunSync(function*() {})) + t.no(f.isFunSync(async () => {})) + t.no(f.isFunSync(async function() {})) + t.no(f.isFunSync(async function*() {})) + + t.ok(f.isFunSync(() => {})) + t.ok(f.isFunSync(function() {})) +}) + +t.test(function test_isFunGen() { + t.no(f.isFunGen(() => {})) + t.no(f.isFunGen(function() {})) + t.no(f.isFunGen(async () => {})) + t.no(f.isFunGen(async function() {})) + t.no(f.isFunGen(async function*() {})) + + t.ok(f.isFunGen(function*() {})) +}) + +t.test(function test_isFunAsync() { + t.no(f.isFunAsync(() => {})) + t.no(f.isFunAsync(function() {})) + t.no(f.isFunAsync(function*() {})) + t.no(f.isFunAsync(async function*() {})) + + t.ok(f.isFunAsync(async () => {})) + t.ok(f.isFunAsync(async function() {})) +}) + +t.test(function test_isFunAsyncGen() { + t.no(f.isFunAsyncGen(() => {})) + t.no(f.isFunAsyncGen(function() {})) + t.no(f.isFunAsyncGen(function*() {})) + t.no(f.isFunAsyncGen(async () => {})) + t.no(f.isFunAsyncGen(async function() {})) + + t.ok(f.isFunAsyncGen(async function*() {})) }) t.test(function test_isObj() {