functionalscript
Advanced tools
Comparing version 0.0.144 to 0.0.146
@@ -41,3 +41,3 @@ # Documentation | ||
```js | ||
module.exports = 'Hello world! | ||
module.exports = 'Hello world!' | ||
``` | ||
@@ -63,6 +63,6 @@ | ||
Run `npm install -D github:REPO/PACKAGE` | ||
Run `npm install -D github:USER/REPO` | ||
```js | ||
const x = require(`PACKAGE/DIR/FILE.js`) | ||
const x = require(`REPO/DIR/FILE.js`) | ||
``` | ||
@@ -82,1 +82,14 @@ | ||
``` | ||
## 3. Advanced | ||
### 3.1. Generators | ||
```js | ||
const range5 = {*[System.iterator]() { | ||
yield 0 | ||
yield 1 | ||
yield 2 | ||
yield 3 | ||
}} | ||
``` |
const lib = require('../') | ||
/** @type {<T, R>(_: lib.Reduce<T, R>) => (_: Iterable<T>) => R} */ | ||
const reduce = ({merge, init}) => c => { | ||
const reduce = ({ merge, init }) => c => { | ||
let result = init | ||
for (let i of c) { | ||
for (const i of c) { | ||
result = merge(result)(i) | ||
@@ -13,9 +13,18 @@ } | ||
module.exports = { | ||
/** @readonly */ | ||
reduce, | ||
/** @readonly */ | ||
join: lib.pipe(lib.join)(reduce), | ||
/** @readonly */ | ||
sum: reduce(lib.sum), | ||
/** @type {<T, R>(_: (_: T) => R) => (_: Iterable<T>) => Iterable<R>} */ | ||
/** | ||
* @readonly | ||
* @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} | ||
*/ | ||
map: f => c => ({ | ||
*[Symbol.iterator]() { | ||
for (let i of c) { | ||
for (const i of c) { | ||
yield f(i) | ||
@@ -25,5 +34,21 @@ } | ||
}), | ||
/** @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined} */ | ||
/** | ||
* @readonly | ||
* @type {<T, R>(f: (value: T) => Promise<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} | ||
*/ | ||
asyncMap: f => c => ({ | ||
async *[Symbol.asyncIterator]() { | ||
for await (const i of c) { | ||
yield* [f(i)] | ||
} | ||
} | ||
}), | ||
/** | ||
* @readonly | ||
* @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined} | ||
*/ | ||
find: f => c => { | ||
for (let i of c) { | ||
for (const i of c) { | ||
if (f(i)) { | ||
@@ -30,0 +55,0 @@ return i |
const lib = require('./index') | ||
require('./iterable/test') | ||
require('./map/test') | ||
@@ -5,0 +6,0 @@ { |
@@ -1,2 +0,1 @@ | ||
const { todo } = require('..') | ||
const { index3, index5 } = require('./cmp') | ||
@@ -151,72 +150,74 @@ | ||
/** @type {(visitor: Visitor) => <T>(init: Lazy<T>) => (cmp: Cmp<T>) => (node: TNode<T>) => Result<T>} */ | ||
const visit = ({ found, notFound }) => init => cmp => { | ||
/** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (init: Lazy<T>) => (node: TNode<T>) => Result<T>} */ | ||
const visit = ({ found, notFound }) => cmp => { | ||
const i3 = index3(cmp) | ||
const i5 = index5(cmp) | ||
/** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/ | ||
/** @type {(node: TNode<T>) => Result<T>} */ | ||
const f = node => { | ||
switch (node.length) { | ||
case 1: { | ||
switch (i3(node[0])) { | ||
case 0: { return notFound.leaf1_left(init)(node) } | ||
case 1: { return found.leaf1(init)(node) } | ||
default: { return notFound.leaf1_right(init)(node) } | ||
return init => { | ||
/** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/ | ||
/** @type {(node: TNode<T>) => Result<T>} */ | ||
const f = node => { | ||
switch (node.length) { | ||
case 1: { | ||
switch (i3(node[0])) { | ||
case 0: { return notFound.leaf1_left(init)(node) } | ||
case 1: { return found.leaf1(init)(node) } | ||
default: { return notFound.leaf1_right(init)(node) } | ||
} | ||
} | ||
} | ||
case 2: { | ||
switch (i5(node)) { | ||
case 0: { return notFound.leaf2_left(init)(node) } | ||
case 1: { return found.leaf2_left(init)(node) } | ||
case 2: { return notFound.leaf2_middle(init)(node) } | ||
case 3: { return found.leaf2_right(init)(node) } | ||
default: { return notFound.leaf2_right(init)(node) } | ||
case 2: { | ||
switch (i5(node)) { | ||
case 0: { return notFound.leaf2_left(init)(node) } | ||
case 1: { return found.leaf2_left(init)(node) } | ||
case 2: { return notFound.leaf2_middle(init)(node) } | ||
case 3: { return found.leaf2_right(init)(node) } | ||
default: { return notFound.leaf2_right(init)(node) } | ||
} | ||
} | ||
} | ||
case 3: { | ||
const [n0, v1, n2] = node | ||
switch (i3(v1)) { | ||
case 0: { | ||
return merge2 | ||
(o => [...o, v1, n2]) | ||
(r => [r, v1, n2]) | ||
(f(n0)) | ||
case 3: { | ||
const [n0, v1, n2] = node | ||
switch (i3(v1)) { | ||
case 0: { | ||
return merge2 | ||
(o => [...o, v1, n2]) | ||
(r => [r, v1, n2]) | ||
(f(n0)) | ||
} | ||
case 1: { return found.branch3(init)(node) } | ||
default: { | ||
return merge2 | ||
(o => [n0, v1, ...o]) | ||
(r => [n0, v1, r]) | ||
(f(n2)) | ||
} | ||
} | ||
case 1: { return found.branch3(init)(node) } | ||
default: { | ||
return merge2 | ||
(o => [n0, v1, ...o]) | ||
(r => [n0, v1, r]) | ||
(f(n2)) | ||
} | ||
} | ||
} | ||
default: { | ||
const [n0, v1, n2, v3, n4] = node | ||
switch (i5([v1, v3])) { | ||
case 0: { | ||
return merge3 | ||
(o => [...o, v1, n2, v3, n4]) | ||
(r => [r, v1, n2, v3, n4]) | ||
(f(n0)) | ||
default: { | ||
const [n0, v1, n2, v3, n4] = node | ||
switch (i5([v1, v3])) { | ||
case 0: { | ||
return merge3 | ||
(o => [...o, v1, n2, v3, n4]) | ||
(r => [r, v1, n2, v3, n4]) | ||
(f(n0)) | ||
} | ||
case 1: { return found.branch5_left(init)(node) } | ||
case 2: { | ||
return merge3 | ||
(o => [n0, v1, ...o, v3, n4]) | ||
(r => [n0, v1, r, v3, n4]) | ||
(f(n2)) | ||
} | ||
case 3: { return found.branch5_right(init)(node) } | ||
default: { | ||
return merge3 | ||
(o => [n0, v1, n2, v3, ...o]) | ||
(r => [n0, v1, n2, v3, r]) | ||
(f(n4)) | ||
} | ||
} | ||
case 1: { return found.branch5_left(init)(node) } | ||
case 2: { | ||
return merge3 | ||
(o => [n0, v1, ...o, v3, n4]) | ||
(r => [n0, v1, r, v3, n4]) | ||
(f(n2)) | ||
} | ||
case 3: { return found.branch5_right(init)(node) } | ||
default: { | ||
return merge3 | ||
(o => [n0, v1, n2, v3, ...o]) | ||
(r => [n0, v1, n2, v3, r]) | ||
(f(n4)) | ||
} | ||
} | ||
} | ||
} | ||
return f | ||
} | ||
return f | ||
} | ||
@@ -231,6 +232,6 @@ | ||
leaf2_left: () => ([value]) => found(value), | ||
leaf2_right: () => ([,value]) => found(value), | ||
branch3: () => ([,value]) => found(value), | ||
branch5_left: () => ([,value]) => found(value), | ||
branch5_right: () => ([,,,value]) => found(value), | ||
leaf2_right: () => ([, value]) => found(value), | ||
branch3: () => ([, value]) => found(value), | ||
branch5_left: () => ([, value]) => found(value), | ||
branch5_right: () => ([, , , value]) => found(value), | ||
} | ||
@@ -255,7 +256,7 @@ /** @type {() => () => { done: false }} */ | ||
leaf1: f => () => replace([f()]), | ||
leaf2_left: f => ([,v1]) => replace([f(), v1]), | ||
leaf2_left: f => ([, v1]) => replace([f(), v1]), | ||
leaf2_right: f => ([v0,]) => replace([v0, f()]), | ||
branch3: f => ([n0,,n2]) => replace([n0, f(), n2]), | ||
branch5_left: f => ([n0,,n2,v3,n4]) => replace([n0, f(), n2, v3, n4]), | ||
branch5_right: f => ([n0,v1,n2,,n4]) => replace([n0, v1, n2, f(), n4]) | ||
branch3: f => ([n0, , n2]) => replace([n0, f(), n2]), | ||
branch5_left: f => ([n0, , n2, v3, n4]) => replace([n0, f(), n2, v3, n4]), | ||
branch5_right: f => ([n0, v1, n2, , n4]) => replace([n0, v1, n2, f(), n4]) | ||
} | ||
@@ -272,3 +273,3 @@ | ||
leaf2_middle: f => ([v0, v1]) => overflow([v0, f(), v1]), | ||
leaf2_right: f => ([v0, v1]) => overflow([v0, v1, f()]), | ||
leaf2_right: f => ([v0, v1]) => overflow([v0, v1, f()]), | ||
} | ||
@@ -299,13 +300,46 @@ | ||
/** @type {<T>(_: TNode<T>) => Iterable<T>} */ | ||
const values = node => ({ | ||
*[Symbol.iterator]() { | ||
switch (node.length) { | ||
case 1: case 2: { | ||
yield* node | ||
return | ||
} | ||
case 3: { | ||
yield* values(node[0]) | ||
yield node[1] | ||
yield* values(node[2]) | ||
return | ||
} | ||
default: { | ||
yield* values(node[0]) | ||
yield node[1] | ||
yield* values(node[2]) | ||
yield node[3] | ||
yield* values(node[4]) | ||
return | ||
} | ||
} | ||
} | ||
}) | ||
module.exports = { | ||
/** @readonly */ | ||
visit, | ||
values, | ||
/** | ||
* @readonly | ||
* @type {<T>(cmp: Cmp<T>) => (node: TNode<T>) => T|undefined} | ||
*/ | ||
getVisitor: cmp => node => { | ||
const result = visit(getVisitor)(cmp)(() => { throw ''})(node) | ||
if ('done' in result && result.done) { return result.value } | ||
return undefined | ||
}, | ||
/** @readonly */ | ||
getVisitor, | ||
setVisitor: visit(setVisitor), | ||
/** @readonly */ | ||
setVisitor, | ||
getOrInsertVisitor: visit(getOrInsertVisitor), | ||
/** @readonly */ | ||
getOrInsertVisitor, | ||
/** @readonly */ | ||
replaceVisitor, | ||
replaceVisitor: visit(replaceVisitor) | ||
} |
@@ -18,4 +18,4 @@ # B-tree | ||
- { found: `true`, value: `T`, } | | ||
{ found: `false` } | ||
- { done: `true`, value: `T`, } | | ||
{ done: `false` } | ||
- { replace: `Node<T>` } | ||
@@ -49,6 +49,6 @@ - { overflow: `Branch3<T>` } | ||
- found. It can return: | ||
- get: { found: `true` ... } | ||
- get: { done: `true` ... } | ||
- replace: { replace: ... } | ||
- notFound: | ||
- none: { found: `false` } | ||
- none: { done: `false` } | ||
- insert: { replace: ... } | { overflow: ... } | ||
@@ -55,0 +55,0 @@ |
{ | ||
"name": "functionalscript", | ||
"version": "0.0.144", | ||
"version": "0.0.146", | ||
"description": "FunctionalScript is a functional subset of JavaScript", | ||
@@ -8,3 +8,4 @@ "main": "index.js", | ||
"tsc": "tsc", | ||
"test": "tsc && node --trace-uncaught ./test" | ||
"test": "tsc && npm run test-only", | ||
"test-only": "node --trace-uncaught ./test" | ||
}, | ||
@@ -11,0 +12,0 @@ "repository": { |
73583
28
1210