functionalscript 0.0.293 → 0.0.297
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LANGUAGE.md +208 -0
- package/README.md +6 -224
- package/package.json +1 -1
- package/types/btree/find/index.js +22 -0
- package/types/btree/find/test.js +2 -7
- package/types/btree/index.js +1 -373
- package/types/btree/remove/test.js +78 -0
- package/types/btree/set/index.js +4 -4
- package/types/btree/test.js +7 -53
- package/types/map/index.js +5 -7
package/LANGUAGE.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# FunctionaScript Programming Language
|
|
2
|
+
|
|
3
|
+
## 1. Module Ecosystem
|
|
4
|
+
|
|
5
|
+
FunctionalScript uses [CommonJS](https://en.wikipedia.org/wiki/CommonJS) conventions as a module ecosystem. For example,
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
const thirdPartyModule = require('third-party-package/module')
|
|
9
|
+
|
|
10
|
+
const result = thirdPartyModule.someFunction('hello')
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 2. Packages
|
|
14
|
+
|
|
15
|
+
FunctionalScript uses a `package.json` file to define a package. This file is compatible with [Node.js `package.json`](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/).
|
|
16
|
+
The prefered way to refence dependencies is to use a GitHub URL. These dependencies in a `package.json` file could look like this,
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
// ...
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"third-party-package": "github:exampleorg/thirdpartypackage"
|
|
23
|
+
}
|
|
24
|
+
// ...
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Note:** this repository is also a FunctionalScript package, and it can be used as a library. To install this package, use
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
npm install -S github:functionalscript/functionalscript
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 3. Module Structure
|
|
35
|
+
|
|
36
|
+
A module is a file with the `.js` extention. It contains three parts: references to other modules, definitions, and exports. For example
|
|
37
|
+
|
|
38
|
+
`./first.js`
|
|
39
|
+
```js
|
|
40
|
+
// 1. references
|
|
41
|
+
const math = require('math')
|
|
42
|
+
|
|
43
|
+
// 2. definitions
|
|
44
|
+
const myConst = 42
|
|
45
|
+
// addition(a)(b) = a + b
|
|
46
|
+
const addition = a => b => a + b
|
|
47
|
+
const add42 = addition(42)
|
|
48
|
+
const _10digitsOfPi = math.calculatePi(10)
|
|
49
|
+
|
|
50
|
+
// 3. exports
|
|
51
|
+
module.exports = {
|
|
52
|
+
addition,
|
|
53
|
+
add42,
|
|
54
|
+
_10digitsOfPi,
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`./second.js`
|
|
59
|
+
```js
|
|
60
|
+
// 1. references
|
|
61
|
+
const first = require('./first.js')
|
|
62
|
+
|
|
63
|
+
// 2. definitions
|
|
64
|
+
const _42plus7 = first.add42(7)
|
|
65
|
+
|
|
66
|
+
// 3. exports
|
|
67
|
+
module.exports = {
|
|
68
|
+
_42plus7,
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 4. References To Other Modules
|
|
73
|
+
|
|
74
|
+
The format of references is `const ANYNAME = require('PATH_TO_A_MODULE')`. For example,
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
const math = require('math')
|
|
78
|
+
const algebra = require('math/algebra')
|
|
79
|
+
const localFile = require('../some-directory/some-file.js')
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 5. Definitions
|
|
83
|
+
|
|
84
|
+
The format of defintions is `const NAME = EXPRESSION`, where the `EXPRESSION` is a subset of [JavaScript expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators).
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
const myConst = 42
|
|
88
|
+
const functionDouble = a => a * 2
|
|
89
|
+
const structure = { name: "John", surname: "Smith" }
|
|
90
|
+
const array = [1, 2, 3]
|
|
91
|
+
const nestedStructure = {
|
|
92
|
+
address: undefined,
|
|
93
|
+
serialNumber: "123-45-78",
|
|
94
|
+
sum: 14 + myConst + functionDouble(4),
|
|
95
|
+
moreInfo: {
|
|
96
|
+
name: "Ivan",
|
|
97
|
+
surname: "Terrible",
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
See [Expressions](#7-Expressions).
|
|
103
|
+
|
|
104
|
+
### 6. Exports
|
|
105
|
+
|
|
106
|
+
The format of exports is `module.exports = { A_LIST_OF_EXPORTED_DEFINITIONS }`. There should be only one `module.exports` at
|
|
107
|
+
the end of a FunctionalScript file. For example,
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
module.exports = {
|
|
111
|
+
nestedStructure,
|
|
112
|
+
array,
|
|
113
|
+
structure,
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 7. Expressions
|
|
118
|
+
|
|
119
|
+
Expressions could fall under these categories:
|
|
120
|
+
|
|
121
|
+
- Literals:
|
|
122
|
+
- Number Literals, e.g. `0`, `3.14`, `4e8`
|
|
123
|
+
- Boolean Literals: `true` or `false`
|
|
124
|
+
- A `null` Literal
|
|
125
|
+
- An `undefined` Literal
|
|
126
|
+
- String Literals, e.g. `"Hello world!"`
|
|
127
|
+
- Complex Structures
|
|
128
|
+
- Arrays, e.g. `[2, 5]`
|
|
129
|
+
- Objects, e.g. `{ a: "Hello", b: "world!" }`
|
|
130
|
+
- Arrow functions, e.g. `x => x * 2`
|
|
131
|
+
- Operators
|
|
132
|
+
- Comparison Operators: `===`, `!==`, `>`, `>=`, `<`, `<=`
|
|
133
|
+
- Arithmetic Operators: `+`, `-`, `*`, `/`, `%`, `**`
|
|
134
|
+
- Bitwise Operators: `&`, `|`, `^`, `~`, `<<`, `>>`, `>>>`
|
|
135
|
+
- Logical Operators: `&&`, `||`, `!`, `??`
|
|
136
|
+
- Conditional Operator, e.g. `condition ? val1 : val2`
|
|
137
|
+
- Template Literals, e.g. `string ${expression}`
|
|
138
|
+
- `typeof`
|
|
139
|
+
- Relations Operators: `in`, `instanceof`.
|
|
140
|
+
- Member Operators: `.`, `[]`.
|
|
141
|
+
|
|
142
|
+
Note: the `.` member operator has prohibitted property names, such as `constructor` and `push`. To access such properties, it's recommeded to use the [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor) function.
|
|
143
|
+
|
|
144
|
+
## 8. Arrow Functions
|
|
145
|
+
|
|
146
|
+
An arrow function is also known as [a lambda function](https://en.wikipedia.org/wiki/Anonymous_function).
|
|
147
|
+
The format of an arrow function is `ARGUMENT_NAME => FUNCTION_BODY`. An arrow function must have either a single argument or no arguments at all. For example
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
x => x * 2
|
|
151
|
+
a => a + 4
|
|
152
|
+
s => `template literal ${s}`
|
|
153
|
+
a => b => a + b // an arrow functions that returns another arrow functions.
|
|
154
|
+
() => 'hello' // an arrow function with no arguments
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
A function body is either an expression or a block statement. A block statement format is `{ A_LIST_OF_STATEMENTS }`. For example
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
// a function with one argument and a block statement
|
|
161
|
+
const f = x => {
|
|
162
|
+
const a = 2 + x
|
|
163
|
+
const r = a + 4
|
|
164
|
+
return r
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 9. Statements
|
|
169
|
+
|
|
170
|
+
`{ A_LIST_OF_STATEMENTS }` is one or many statements seperated by the newline control character. One of these statements mentioned earlier was [definition](#5-Definitions), also known as a [const](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) statement. The other statements are described below.
|
|
171
|
+
|
|
172
|
+
### 9.1. Let
|
|
173
|
+
|
|
174
|
+
[Let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) declares a local mutable alias for immutable objects. For example
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
let x = [5]
|
|
178
|
+
// you can assign another immutable object to the alias at any time.
|
|
179
|
+
x = [3, 4]
|
|
180
|
+
//but you can't change the properties of the immutable object.
|
|
181
|
+
x[0] = 3 // < invalid
|
|
182
|
+
//let aliases can not be referenced from another arrow function.
|
|
183
|
+
const f = () => x // < invalid
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 9.2. Return
|
|
187
|
+
|
|
188
|
+
[Return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)
|
|
189
|
+
|
|
190
|
+
### 9.3. If...Else
|
|
191
|
+
|
|
192
|
+
[If...Else](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else)
|
|
193
|
+
|
|
194
|
+
### 9.4. Switch
|
|
195
|
+
|
|
196
|
+
[Switch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)
|
|
197
|
+
|
|
198
|
+
### 9.5. Throw
|
|
199
|
+
|
|
200
|
+
[Throw](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw). FunctionalScript allows to throw exceptions but it doesn't catch them. You should only be using Statement throw in non-recoverable situations. It could be compared to [panic in Rust](https://doc.rust-lang.org/std/macro.panic.html).
|
|
201
|
+
|
|
202
|
+
### 9.6. While
|
|
203
|
+
|
|
204
|
+
[While](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while)
|
|
205
|
+
|
|
206
|
+
### 9.7. Block
|
|
207
|
+
|
|
208
|
+
[Block](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block)
|
package/README.md
CHANGED
|
@@ -1,239 +1,21 @@
|
|
|
1
1
|
# FunctionalScript
|
|
2
2
|
|
|
3
|
-
FunctionalScript is a pure functional programming language and a strict subset of
|
|
4
|
-
[ECMAScript](https://en.wikipedia.org/wiki/ECMAScript)/[JavaScript](https://en.wikipedia.org/wiki/JavaScript). It's inspired by
|
|
3
|
+
FunctionalScript is a pure functional programming language and a strict subset of
|
|
4
|
+
[ECMAScript](https://en.wikipedia.org/wiki/ECMAScript)/[JavaScript](https://en.wikipedia.org/wiki/JavaScript). It's inspired by
|
|
5
5
|
|
|
6
6
|
- [JSON](https://en.wikipedia.org/wiki/JSON) as a subset of JavaScript. JSON is also a subset of FunctionalScript.
|
|
7
7
|
- [asm.JS](https://en.wikipedia.org/wiki/Asm.js)/[WebAssembly](https://en.wikipedia.org/wiki/WebAssembly), as a subset of JavaScript.
|
|
8
8
|
- [TypeScript](https://en.wikipedia.org/wiki/TypeScript), as a superset of JavaScript.
|
|
9
9
|
|
|
10
|
+
[A brief description of FunctionalScript Programming Language](./LANGUAGE.md).
|
|
11
|
+
|
|
10
12
|
Create a new FunctionalScript repository on GitHub [here](https://github.com/functionalscript/template/generate).
|
|
11
13
|
|
|
12
|
-
##
|
|
14
|
+
## Design Principles
|
|
13
15
|
|
|
14
16
|
In FunctionalScript:
|
|
15
17
|
|
|
16
18
|
- Any module is a valid JavaScript module. No additional build steps are required.
|
|
17
19
|
- Code should not have [side-effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)). Any JavaScript statement, expression, or function which has a side effect is not allowed in FunctionalScript. There are no exceptions to this rule, such as `unsafe` code which can be found in Rust, C#, and other languages.
|
|
18
|
-
- A module can't depend on non FunctionalScript module.
|
|
20
|
+
- A module can't depend on non FunctionalScript module.
|
|
19
21
|
- It also has no standard library, only a safe subset of standard JavaScript API can be used without referencing other modules.
|
|
20
|
-
|
|
21
|
-
## 2. Outlines
|
|
22
|
-
|
|
23
|
-
### 2.1. Module Ecosystem
|
|
24
|
-
|
|
25
|
-
FunctionalScript uses [CommonJS](https://en.wikipedia.org/wiki/CommonJS) conventions as a module ecosystem. For example,
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
const thirdPartyModule = require('third-party-package/module')
|
|
29
|
-
|
|
30
|
-
const result = thirdPartyModule.someFunction('hello')
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 2.2. Packages
|
|
34
|
-
|
|
35
|
-
FunctionalScript uses a `package.json` file to define a package. This file is compatible with [Node.js `package.json`](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/).
|
|
36
|
-
The prefered way to refence dependencies is to use a GitHub URL. These dependencies in a `package.json` file could look like this,
|
|
37
|
-
|
|
38
|
-
```json
|
|
39
|
-
{
|
|
40
|
-
// ...
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"third-party-package": "github:exampleorg/thirdpartypackage"
|
|
43
|
-
}
|
|
44
|
-
// ...
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**Note:** this repository is also a FunctionalScript package, and it can be used as a library. To install this package, use
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
npm install -S github:functionalscript/functionalscript
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 2.3. Module Structure
|
|
55
|
-
|
|
56
|
-
A module is a file with the `.js` extention. It contains three parts: references to other modules, definitions, and exports. For example
|
|
57
|
-
|
|
58
|
-
`./first.js`
|
|
59
|
-
```js
|
|
60
|
-
// 1. references
|
|
61
|
-
const math = require('math')
|
|
62
|
-
|
|
63
|
-
// 2. definitions
|
|
64
|
-
const myConst = 42
|
|
65
|
-
// addition(a)(b) = a + b
|
|
66
|
-
const addition = a => b => a + b
|
|
67
|
-
const add42 = addition(42)
|
|
68
|
-
const _10digitsOfPi = math.calculatePi(10)
|
|
69
|
-
|
|
70
|
-
// 3. exports
|
|
71
|
-
module.exports = {
|
|
72
|
-
addition,
|
|
73
|
-
add42,
|
|
74
|
-
_10digitsOfPi,
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
`./second.js`
|
|
79
|
-
```js
|
|
80
|
-
// 1. references
|
|
81
|
-
const first = require('./first.js')
|
|
82
|
-
|
|
83
|
-
// 2. definitions
|
|
84
|
-
const _42plus7 = first.add42(7)
|
|
85
|
-
|
|
86
|
-
// 3. exports
|
|
87
|
-
module.exports = {
|
|
88
|
-
_42plus7,
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 2.4. References To Other Modules
|
|
93
|
-
|
|
94
|
-
The format of references is `const ANYNAME = require('PATH_TO_A_MODULE')`. For example,
|
|
95
|
-
|
|
96
|
-
```js
|
|
97
|
-
const math = require('math')
|
|
98
|
-
const algebra = require('math/algebra')
|
|
99
|
-
const localFile = require('../some-directory/some-file.js')
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 2.5. Definitions
|
|
103
|
-
|
|
104
|
-
The format of defintions is `const NAME = EXPRESSION`, where the `EXPRESSION` is a subset of [JavaScript expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators).
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
const myConst = 42
|
|
108
|
-
const functionDouble = a => a * 2
|
|
109
|
-
const structure = { name: "John", surname: "Smith" }
|
|
110
|
-
const array = [1, 2, 3]
|
|
111
|
-
const nestedStructure = {
|
|
112
|
-
address: undefined,
|
|
113
|
-
serialNumber: "123-45-78",
|
|
114
|
-
sum: 14 + myConst + functionDouble(4),
|
|
115
|
-
moreInfo: {
|
|
116
|
-
name: "Ivan",
|
|
117
|
-
surname: "Terrible",
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
See [3. Expressions](#3-Expressions).
|
|
123
|
-
|
|
124
|
-
### 2.6. Exports
|
|
125
|
-
|
|
126
|
-
The format of exports is `module.exports = { A_LIST_OF_EXPORTED_DEFINITIONS }`. There should be only one `module.exports` at
|
|
127
|
-
the end of a FunctionalScript file. For example,
|
|
128
|
-
|
|
129
|
-
```js
|
|
130
|
-
module.exports = {
|
|
131
|
-
nestedStructure,
|
|
132
|
-
array,
|
|
133
|
-
structure,
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## 3. Expressions
|
|
138
|
-
|
|
139
|
-
Expressions could fall under these categories:
|
|
140
|
-
|
|
141
|
-
- Literals:
|
|
142
|
-
- Number Literals, e.g. `0`, `3.14`, `4e8`
|
|
143
|
-
- Boolean Literals: `true` or `false`
|
|
144
|
-
- A `null` Literal
|
|
145
|
-
- An `undefined` Literal
|
|
146
|
-
- String Literals, e.g. `"Hello world!"`
|
|
147
|
-
- Complex Structures
|
|
148
|
-
- Arrays, e.g. `[2, 5]`
|
|
149
|
-
- Objects, e.g. `{ a: "Hello", b: "world!" }`
|
|
150
|
-
- Arrow functions, e.g. `x => x * 2`
|
|
151
|
-
- Operators
|
|
152
|
-
- Comparison Operators: `===`, `!==`, `>`, `>=`, `<`, `<=`
|
|
153
|
-
- Arithmetic Operators: `+`, `-`, `*`, `/`, `%`, `**`
|
|
154
|
-
- Bitwise Operators: `&`, `|`, `^`, `~`, `<<`, `>>`, `>>>`
|
|
155
|
-
- Logical Operators: `&&`, `||`, `!`, `??`
|
|
156
|
-
- Conditional Operator, e.g. `condition ? val1 : val2`
|
|
157
|
-
- Template Literals, e.g. `string ${expression}`
|
|
158
|
-
- `typeof`
|
|
159
|
-
- Relations Operators: `in`, `instanceof`.
|
|
160
|
-
- Member Operators: `.`, `[]`.
|
|
161
|
-
|
|
162
|
-
Note: the `.` member operator has prohibitted property names, such as `constructor` and `push`. To access such properties, it's recommeded to use the [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor) function.
|
|
163
|
-
|
|
164
|
-
## 4. Arrow Functions
|
|
165
|
-
|
|
166
|
-
An arrow function is also known as [a lambda function](https://en.wikipedia.org/wiki/Anonymous_function).
|
|
167
|
-
The format of an arrow function is `ARGUMENT_NAME => FUNCTION_BODY`. An arrow function must have either a single argument or no arguments at all. For example
|
|
168
|
-
|
|
169
|
-
```js
|
|
170
|
-
x => x * 2
|
|
171
|
-
a => a + 4
|
|
172
|
-
s => `template literal ${s}`
|
|
173
|
-
a => b => a + b // an arrow functions that returns another arrow functions.
|
|
174
|
-
() => 'hello' // an arrow function with no arguments
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
A function body is either an expression or a block statement. A block statement format is `{ A_LIST_OF_STATEMENTS }`. For example
|
|
178
|
-
|
|
179
|
-
```js
|
|
180
|
-
// a function with one argument and a block statement
|
|
181
|
-
const f = x => {
|
|
182
|
-
const a = 2 + x
|
|
183
|
-
const r = a + 4
|
|
184
|
-
return r
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
## 5. Statements
|
|
189
|
-
|
|
190
|
-
`{ A_LIST_OF_STATEMENTS }` is one or many statements seperated by the newline control character. One of these statements mentioned earlier was [definition](#25-Definitions), also known as a [const](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) statement. The other statements are described below.
|
|
191
|
-
|
|
192
|
-
### 5.1 Let
|
|
193
|
-
|
|
194
|
-
[Let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) declares a local mutable alias for immutable objects. For example
|
|
195
|
-
|
|
196
|
-
```js
|
|
197
|
-
let x = [5]
|
|
198
|
-
// you can assign another immutable object to the alias at any time.
|
|
199
|
-
x = [3, 4]
|
|
200
|
-
//but you can't change the properties of the immutable object.
|
|
201
|
-
x[0] = 3 // < invalid
|
|
202
|
-
//let aliases can not be referenced from another arrow function.
|
|
203
|
-
const f = () => x // < invalid
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
This mutable object cannot be used in [closures](https://en.wikipedia.org/wiki/Closure_(computer_programming)) or nested functions.
|
|
209
|
-
|
|
210
|
-
An example of incorrect code would look like this:
|
|
211
|
-
|
|
212
|
-
```js
|
|
213
|
-
let x = 5
|
|
214
|
-
const f = () => x
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### 5.2 Return
|
|
218
|
-
|
|
219
|
-
[Return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)
|
|
220
|
-
|
|
221
|
-
### 5.3 If...Else
|
|
222
|
-
|
|
223
|
-
[If...Else](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else)
|
|
224
|
-
|
|
225
|
-
### 5.4 Switch
|
|
226
|
-
|
|
227
|
-
[Switch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)
|
|
228
|
-
|
|
229
|
-
### 5.5 Throw
|
|
230
|
-
|
|
231
|
-
[Throw](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw). FunctionalScript allows to throw exceptions but it doesn't catch them. You should only be using Statement throw in non-recoverable situations. It could be compared to [panic in Rust](https://doc.rust-lang.org/std/macro.panic.html).
|
|
232
|
-
|
|
233
|
-
### 5.6 While
|
|
234
|
-
|
|
235
|
-
[While](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while)
|
|
236
|
-
|
|
237
|
-
### 5.7 Block
|
|
238
|
-
|
|
239
|
-
[Block](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block)
|
package/package.json
CHANGED
|
@@ -98,7 +98,29 @@ const find = c => {
|
|
|
98
98
|
return f(undefined)
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/** @type {<T>(first: First<T>) => T | undefined} */
|
|
102
|
+
const value = first => {
|
|
103
|
+
switch (first[0]) {
|
|
104
|
+
case 1: {
|
|
105
|
+
const x = first[1]
|
|
106
|
+
switch (x.length) {
|
|
107
|
+
case 1: case 2: { return x[0] }
|
|
108
|
+
default: { return x[1] }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
case 3: {
|
|
112
|
+
const x = first[1]
|
|
113
|
+
return x.length === 2 ? x[1] : x[3]
|
|
114
|
+
}
|
|
115
|
+
default: {
|
|
116
|
+
return undefined
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
101
121
|
module.exports = {
|
|
102
122
|
/** @readonly */
|
|
103
123
|
find,
|
|
124
|
+
/** @readonly */
|
|
125
|
+
value,
|
|
104
126
|
}
|
package/types/btree/find/test.js
CHANGED
|
@@ -4,17 +4,12 @@ const json = require('../../../json')
|
|
|
4
4
|
const { sort } = require('../../object')
|
|
5
5
|
const btree = require('..')
|
|
6
6
|
const { stringCmp } = require('../../function/compare')
|
|
7
|
+
const s = require('../set')
|
|
7
8
|
|
|
8
9
|
const jsonStr = json.stringify(sort)
|
|
9
10
|
|
|
10
11
|
/** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
|
|
11
|
-
const set = node => value =>
|
|
12
|
-
const result = btree.setVisitor(stringCmp(value))(node)(() => value)
|
|
13
|
-
switch (result[0]) {
|
|
14
|
-
case 'replace': case 'overflow': { return result[1] }
|
|
15
|
-
default: { return node }
|
|
16
|
-
}
|
|
17
|
-
}
|
|
12
|
+
const set = node => value => s.set(stringCmp(value))(value)(node)
|
|
18
13
|
|
|
19
14
|
/** @type {(r: _.Result<json.Unknown>) => string} */
|
|
20
15
|
const str = r => jsonStr(list.toArray(list.map(x => x[0])(r)))
|
package/types/btree/index.js
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
const { todo } = require('../../dev')
|
|
2
|
-
const cmp = require('../function/compare')
|
|
3
|
-
const { index3, index5 } = cmp
|
|
4
1
|
const seq = require('../list')
|
|
5
2
|
|
|
6
|
-
/**
|
|
7
|
-
* @template T
|
|
8
|
-
* @typedef {() => T} Lazy
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @template T
|
|
13
|
-
* @typedef {cmp.Compare<T>} Cmp
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
3
|
/**
|
|
17
4
|
* @template T
|
|
18
5
|
* @typedef {readonly[T]} Array1
|
|
@@ -61,268 +48,6 @@ const seq = require('../list')
|
|
|
61
48
|
* @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} Node
|
|
62
49
|
*/
|
|
63
50
|
|
|
64
|
-
/** @typedef {readonly['done']} NotFoundDone */
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* @template T
|
|
68
|
-
* @typedef {readonly['done', T]} FoundDone
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @template T
|
|
73
|
-
* @typedef { NotFoundDone | FoundDone<T> } Done
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @template T
|
|
78
|
-
* @typedef {readonly['replace', Node<T>]} Replace
|
|
79
|
-
*/
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @template T
|
|
83
|
-
* @typedef {readonly['overflow', Branch3<T>]} Overflow
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @template T
|
|
88
|
-
* @typedef { Done<T> | Replace<T> | Overflow<T> } Result
|
|
89
|
-
*/
|
|
90
|
-
|
|
91
|
-
/** @typedef {<T>(_: Leaf1<T>) => LazyResult<T>} InLeaf1 */
|
|
92
|
-
/** @typedef {<T>(_: Leaf2<T>) => LazyResult<T>} InLeaf2 */
|
|
93
|
-
/** @typedef {<T>(_: Branch3<T>) => LazyResult<T>} InBranch3 */
|
|
94
|
-
/** @typedef {<T>(_: Branch5<T>) => LazyResult<T>} InBranch5 */
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @typedef {{
|
|
98
|
-
* readonly leaf1: InLeaf1
|
|
99
|
-
* readonly leaf2_left: InLeaf2
|
|
100
|
-
* readonly leaf2_right: InLeaf2
|
|
101
|
-
* readonly branch3: InBranch3
|
|
102
|
-
* readonly branch5_left: InBranch5
|
|
103
|
-
* readonly branch5_right: InBranch5
|
|
104
|
-
* }} Found
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @typedef {{
|
|
109
|
-
* readonly leaf1_left: InLeaf1
|
|
110
|
-
* readonly leaf1_right: InLeaf1
|
|
111
|
-
* readonly leaf2_left: InLeaf2
|
|
112
|
-
* readonly leaf2_middle: InLeaf2
|
|
113
|
-
* readonly leaf2_right: InLeaf2
|
|
114
|
-
* }} NotFound
|
|
115
|
-
*/
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @template T
|
|
119
|
-
* @typedef {(f: (_: Node<T>) => LazyResult<T>) => LazyResult<T>} FResult<T>
|
|
120
|
-
*/
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @typedef {{
|
|
124
|
-
* readonly branch3_left: <T>(branch3: Branch3<T>) => FResult<T>
|
|
125
|
-
* readonly branch3_right: <T>(branch3: Branch3<T>) => FResult<T>
|
|
126
|
-
* readonly branch5_left: <T>(branch5: Branch5<T>) => FResult<T>
|
|
127
|
-
* readonly branch5_middle: <T>(branch5: Branch5<T>) => FResult<T>
|
|
128
|
-
* readonly branch5_right: <T>(branch5: Branch5<T>) => FResult<T>
|
|
129
|
-
* }} Continue
|
|
130
|
-
*/
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* @typedef {{
|
|
134
|
-
* readonly found: Found
|
|
135
|
-
* readonly notFound: NotFound
|
|
136
|
-
* }} Visitor
|
|
137
|
-
*/
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* @template T
|
|
141
|
-
* @typedef { readonly[...Branch5<T>, T, Node<T>] } Branch7
|
|
142
|
-
*/
|
|
143
|
-
|
|
144
|
-
/** @type {<T>(n: Branch7<T>) => Branch3<T>} */
|
|
145
|
-
const split = ([n0, v1, n2, v3, n4, v5, n6]) => [[n0, v1, n2], v3, [n4, v5, n6]]
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* @template T
|
|
149
|
-
* @typedef {(init: Lazy<T>) => Result<T>} LazyResult
|
|
150
|
-
*/
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* @type {<T>(extend: (o: Branch3<T>) => Result<T>) =>
|
|
154
|
-
* (replace: (r: Node<T>) => Node<T>) =>
|
|
155
|
-
* (result: LazyResult<T>) =>
|
|
156
|
-
* LazyResult<T>}
|
|
157
|
-
*/
|
|
158
|
-
const merge = extend => replace => lazyResult => init => {
|
|
159
|
-
const result = lazyResult(init)
|
|
160
|
-
switch (result[0]) {
|
|
161
|
-
case 'done': { return result }
|
|
162
|
-
case 'replace': { return ['replace', replace(result[1])] }
|
|
163
|
-
default: { return extend(result[1]) }
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (node: Node<T>) => LazyResult<T>} */
|
|
168
|
-
const visit = ({ found, notFound }) => cmp => {
|
|
169
|
-
const i3 = index3(cmp)
|
|
170
|
-
const i5 = index5(cmp)
|
|
171
|
-
/** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T */
|
|
172
|
-
/**
|
|
173
|
-
* @type {(extend: (o: Branch3<T>) => Branch5<T>) =>
|
|
174
|
-
* (replace: (r: Node<T>) => Branch3<T>) =>
|
|
175
|
-
* (result: LazyResult<T>) =>
|
|
176
|
-
* LazyResult<T>}
|
|
177
|
-
*/
|
|
178
|
-
const merge2 = extend => merge(o => ['replace', extend(o)])
|
|
179
|
-
/**
|
|
180
|
-
* @type {(extend: (o: Branch3<T>) => Branch7<T>) =>
|
|
181
|
-
* (replace: (r: Node<T>) => Branch5<T>) =>
|
|
182
|
-
* (result: LazyResult<T>) =>
|
|
183
|
-
* LazyResult<T>}
|
|
184
|
-
*/
|
|
185
|
-
const merge3 = extend => merge(o => ['overflow', split(extend(o))])
|
|
186
|
-
/** @type {(node: Node<T>) => LazyResult<T>} */
|
|
187
|
-
const f = node => {
|
|
188
|
-
switch (node.length) {
|
|
189
|
-
case 1: {
|
|
190
|
-
switch (i3(node[0])) {
|
|
191
|
-
case 0: { return notFound.leaf1_left(node) }
|
|
192
|
-
case 1: { return found.leaf1(node) }
|
|
193
|
-
default: { return notFound.leaf1_right(node) }
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
case 2: {
|
|
197
|
-
switch (i5(node)) {
|
|
198
|
-
case 0: { return notFound.leaf2_left(node) }
|
|
199
|
-
case 1: { return found.leaf2_left(node) }
|
|
200
|
-
case 2: { return notFound.leaf2_middle(node) }
|
|
201
|
-
case 3: { return found.leaf2_right(node) }
|
|
202
|
-
default: { return notFound.leaf2_right(node) }
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
case 3: {
|
|
206
|
-
const [n0, v1, n2] = node
|
|
207
|
-
switch (i3(v1)) {
|
|
208
|
-
case 0: {
|
|
209
|
-
return merge2
|
|
210
|
-
(e => [...e, v1, n2])
|
|
211
|
-
(r => [r, v1, n2])
|
|
212
|
-
(f(n0))
|
|
213
|
-
}
|
|
214
|
-
case 1: { return found.branch3(node) }
|
|
215
|
-
default: {
|
|
216
|
-
return merge2
|
|
217
|
-
(e => [n0, v1, ...e])
|
|
218
|
-
(r => [n0, v1, r])
|
|
219
|
-
(f(n2))
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
default: {
|
|
224
|
-
const [n0, v1, n2, v3, n4] = node
|
|
225
|
-
switch (i5([v1, v3])) {
|
|
226
|
-
case 0: {
|
|
227
|
-
return merge3
|
|
228
|
-
(o => [...o, v1, n2, v3, n4])
|
|
229
|
-
(r => [r, v1, n2, v3, n4])
|
|
230
|
-
(f(n0))
|
|
231
|
-
}
|
|
232
|
-
case 1: { return found.branch5_left(node) }
|
|
233
|
-
case 2: {
|
|
234
|
-
return merge3
|
|
235
|
-
(o => [n0, v1, ...o, v3, n4])
|
|
236
|
-
(r => [n0, v1, r, v3, n4])
|
|
237
|
-
(f(n2))
|
|
238
|
-
}
|
|
239
|
-
case 3: { return found.branch5_right(node) }
|
|
240
|
-
default: {
|
|
241
|
-
return merge3
|
|
242
|
-
(o => [n0, v1, n2, v3, ...o])
|
|
243
|
-
(r => [n0, v1, n2, v3, r])
|
|
244
|
-
(f(n4))
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return f
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/** @type { <T>(_: T) => Done<T> } */
|
|
254
|
-
const found = value => ['done', value]
|
|
255
|
-
|
|
256
|
-
/** @type {Found} */
|
|
257
|
-
const foundGet = {
|
|
258
|
-
leaf1: ([value]) => () => found(value),
|
|
259
|
-
leaf2_left: ([value]) => () => found(value),
|
|
260
|
-
leaf2_right: ([, value]) => () => found(value),
|
|
261
|
-
branch3: ([, value]) => () => found(value),
|
|
262
|
-
branch5_left: ([, value]) => () => found(value),
|
|
263
|
-
branch5_right: ([, , , value]) => () => found(value),
|
|
264
|
-
}
|
|
265
|
-
/** @type { () => () => NotFoundDone } */
|
|
266
|
-
const notFound = () => () => ['done']
|
|
267
|
-
|
|
268
|
-
/** @type {NotFound} */
|
|
269
|
-
const notFoundGet = {
|
|
270
|
-
leaf1_left: notFound,
|
|
271
|
-
leaf1_right: notFound,
|
|
272
|
-
leaf2_left: notFound,
|
|
273
|
-
leaf2_middle: notFound,
|
|
274
|
-
leaf2_right: notFound,
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/** @type { <T>(_: Node<T>) => Replace<T> } */
|
|
278
|
-
const replace = node => ['replace', node]
|
|
279
|
-
|
|
280
|
-
/** @type {Found} */
|
|
281
|
-
const foundReplace = {
|
|
282
|
-
leaf1: () => f => replace([f()]),
|
|
283
|
-
leaf2_left: ([, v1]) => f => replace([f(), v1]),
|
|
284
|
-
leaf2_right: ([v0,]) => f => replace([v0, f()]),
|
|
285
|
-
branch3: ([n0, , n2]) => f => replace([n0, f(), n2]),
|
|
286
|
-
branch5_left: ([n0, , n2, v3, n4]) => f => replace([n0, f(), n2, v3, n4]),
|
|
287
|
-
branch5_right: ([n0, v1, n2, , n4]) => f => replace([n0, v1, n2, f(), n4])
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** @type {<T>(leaf3: Array3<T>) => Result<T>} */
|
|
291
|
-
const overflow = ([v0, v1, v2]) => ['overflow', [[v0], v1, [v2]]]
|
|
292
|
-
|
|
293
|
-
/** @type {NotFound} */
|
|
294
|
-
const notFoundInsert = {
|
|
295
|
-
leaf1_left: ([v]) => f => replace([f(), v]),
|
|
296
|
-
leaf1_right: ([v]) => f => replace([v, f()]),
|
|
297
|
-
leaf2_left: ([v0, v1]) => f => overflow([f(), v0, v1]),
|
|
298
|
-
leaf2_middle: ([v0, v1]) => f => overflow([v0, f(), v1]),
|
|
299
|
-
leaf2_right: ([v0, v1]) => f => overflow([v0, v1, f()]),
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** @type {Visitor} */
|
|
303
|
-
const getVisitor = {
|
|
304
|
-
found: foundGet,
|
|
305
|
-
notFound: notFoundGet,
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** @type {Visitor} */
|
|
309
|
-
const setVisitor = {
|
|
310
|
-
found: foundReplace,
|
|
311
|
-
notFound: notFoundInsert,
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/** @type {Visitor} */
|
|
315
|
-
const getOrInsertVisitor = {
|
|
316
|
-
found: foundGet,
|
|
317
|
-
notFound: notFoundInsert,
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/** @type {Visitor} */
|
|
321
|
-
const replaceVisitor = {
|
|
322
|
-
found: foundReplace,
|
|
323
|
-
notFound: notFoundGet,
|
|
324
|
-
}
|
|
325
|
-
|
|
326
51
|
/** @type {<T>(node: Node<T>) => seq.Thunk<T>} */
|
|
327
52
|
const values = node => () => {
|
|
328
53
|
switch (node.length) {
|
|
@@ -353,107 +78,10 @@ const values = node => () => {
|
|
|
353
78
|
|
|
354
79
|
/**
|
|
355
80
|
* @template T
|
|
356
|
-
* @typedef {
|
|
357
|
-
*/
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* @template T
|
|
361
|
-
* @typedef {readonly[...Branch7<T>,T,Node<T>]} Branch9
|
|
362
|
-
*/
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* @template T
|
|
366
|
-
* @typedef {readonly[...Branch9<T>,T,Node<T>]} Branch11
|
|
367
|
-
*/
|
|
368
|
-
|
|
369
|
-
/** @type {<T>(n: Branch5<T> | Branch7<T> | Branch9<T> | Branch11<T>) => Branch1<T> | Branch3<T>} */
|
|
370
|
-
const up = n => {
|
|
371
|
-
switch (n.length) {
|
|
372
|
-
case 5: { return [n] }
|
|
373
|
-
case 7: {
|
|
374
|
-
const [n0, v1, n2, v3, n4, v5, n6] = n
|
|
375
|
-
return [[n0, v1, n2], v3, [n4, v5, n6]]
|
|
376
|
-
}
|
|
377
|
-
case 9: {
|
|
378
|
-
const [n0, v1, n2, v3, n4, v5, n6, v7, n8] = n
|
|
379
|
-
return [[n0, v1, n2], v3, [n4, v5, n6, v7, n8]]
|
|
380
|
-
}
|
|
381
|
-
case 11: {
|
|
382
|
-
const [n0, v1, n2, v3, n4, v5, n6, v7, n8, v9, n10] = n
|
|
383
|
-
return [[n0, v1, n2, v3, n4], v5, [n6, v7, n8, v9, n10]]
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* @template T
|
|
390
|
-
* @typedef {readonly[Node<T>,T]} Head2
|
|
391
|
-
*/
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* @template T
|
|
395
|
-
* @typedef {readonly[...Head2<T>, ...Head2<T>]} Head4
|
|
396
|
-
*/
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* @template T
|
|
400
|
-
* @typedef {Head2<T>|Head4<T>} Head
|
|
81
|
+
* @typedef { readonly[...Branch5<T>, T, Node<T>] } Branch7
|
|
401
82
|
*/
|
|
402
83
|
|
|
403
|
-
/** @type {<T>(n: Branch3<T> | Branch5<T>) => readonly[Head<T>, Node<T>]} */
|
|
404
|
-
const headLast = n => {
|
|
405
|
-
if (n.length === 3) {
|
|
406
|
-
const [n0, v1, n2] = n
|
|
407
|
-
return [[n0, v1], n2]
|
|
408
|
-
} else {
|
|
409
|
-
const [n0, v1, n2, v3, n4] = n
|
|
410
|
-
return [[n0, v1, n2, v3], n4]
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/** @type {<T>(a: Node<T>) => (b: Node<T>) => ConcatResult<T>} */
|
|
415
|
-
const concat = a => b => {
|
|
416
|
-
/** @typedef {typeof a extends Node<infer T> ? T : never} T */
|
|
417
|
-
switch (a.length) {
|
|
418
|
-
case 1: {
|
|
419
|
-
switch (b.length) {
|
|
420
|
-
case 1: { return [[a[0], b[0]]] }
|
|
421
|
-
case 2: { return [a, b[0], [b[1]]] }
|
|
422
|
-
default: { throw 'invalid b node' }
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
case 2: { return [[a[0]], a[1], b] }
|
|
426
|
-
default: {
|
|
427
|
-
switch (b.length) {
|
|
428
|
-
case 3: case 5: {
|
|
429
|
-
const [aHead, aLast] = headLast(a)
|
|
430
|
-
const [bFirst, ...bTail] = b
|
|
431
|
-
return up([...aHead, ...concat(aLast)(bFirst), ...bTail])
|
|
432
|
-
}
|
|
433
|
-
default: { throw 'invalid b node' }
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
84
|
module.exports = {
|
|
440
85
|
/** @readonly */
|
|
441
86
|
values,
|
|
442
|
-
/**
|
|
443
|
-
* @readonly
|
|
444
|
-
* @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
|
|
445
|
-
*/
|
|
446
|
-
getVisitor: cmp => node => {
|
|
447
|
-
const result = visit(getVisitor)(cmp)(node)(() => { throw 'getVisitor' })
|
|
448
|
-
if (result[0] !== 'done') { throw 'getVisitor result' }
|
|
449
|
-
return result[1]
|
|
450
|
-
},
|
|
451
|
-
/** @readonly */
|
|
452
|
-
setVisitor: visit(setVisitor),
|
|
453
|
-
/** @readonly */
|
|
454
|
-
getOrInsertVisitor: visit(getOrInsertVisitor),
|
|
455
|
-
/** @readonly */
|
|
456
|
-
replaceVisitor: visit(replaceVisitor),
|
|
457
|
-
/** @readonly */
|
|
458
|
-
concat,
|
|
459
87
|
}
|
|
@@ -407,3 +407,81 @@ const jsonStr = json.stringify(sort)
|
|
|
407
407
|
if (_map !== undefined) { throw _map }
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
+
|
|
411
|
+
{
|
|
412
|
+
/** @type {btree.Node<string>|undefined} */
|
|
413
|
+
let _map = ['1']
|
|
414
|
+
for (let i = 2; i <= 10; i++)
|
|
415
|
+
_map = set(_map)((i * i).toString())
|
|
416
|
+
if (_map.length !== 3) { throw _map }
|
|
417
|
+
let _s = jsonStr(_map)
|
|
418
|
+
if (_s !== '[[["1","100"],"16",["25","36"]],"4",[["49"],"64",["81","9"]]]') { throw _s }
|
|
419
|
+
|
|
420
|
+
{
|
|
421
|
+
_map = remove(_map)("4")
|
|
422
|
+
if (_map === undefined) { throw _map }
|
|
423
|
+
_s = jsonStr(_map);
|
|
424
|
+
if (_s !== '[[["1","100"],"16",["25","36"]],"49",[["64"],"81",["9"]]]') { throw _s }
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
{
|
|
428
|
+
_map = remove(_map)("49")
|
|
429
|
+
if (_map === undefined) { throw _map }
|
|
430
|
+
_s = jsonStr(_map);
|
|
431
|
+
if (_s !== '[["1","100"],"16",["25","36"],"64",["81","9"]]') { throw _s }
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
{
|
|
435
|
+
_map = remove(_map)("64")
|
|
436
|
+
if (_map === undefined) { throw _map }
|
|
437
|
+
_s = jsonStr(_map);
|
|
438
|
+
if (_s !== '[["1","100"],"16",["25","36"],"81",["9"]]') { throw _s }
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
{
|
|
442
|
+
_map = remove(_map)("81")
|
|
443
|
+
if (_map === undefined) { throw _map }
|
|
444
|
+
_s = jsonStr(_map);
|
|
445
|
+
if (_s !== '[["1","100"],"16",["25"],"36",["9"]]') { throw _s }
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
{
|
|
449
|
+
_map = remove(_map)("36")
|
|
450
|
+
if (_map === undefined) { throw _map }
|
|
451
|
+
_s = jsonStr(_map);
|
|
452
|
+
if (_s !== '[["1","100"],"16",["25","9"]]') { throw _s }
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
{
|
|
456
|
+
_map = remove(_map)("16")
|
|
457
|
+
if (_map === undefined) { throw _map }
|
|
458
|
+
_s = jsonStr(_map);
|
|
459
|
+
if (_s !== '[["1","100"],"25",["9"]]') { throw _s }
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
{
|
|
463
|
+
_map = remove(_map)("25")
|
|
464
|
+
if (_map === undefined) { throw _map }
|
|
465
|
+
_s = jsonStr(_map);
|
|
466
|
+
if (_s !== '[["1"],"100",["9"]]') { throw _s }
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
{
|
|
470
|
+
_map = remove(_map)("100")
|
|
471
|
+
if (_map === undefined) { throw _map }
|
|
472
|
+
_s = jsonStr(_map);
|
|
473
|
+
if (_s !== '["1","9"]') { throw _s }
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
{
|
|
477
|
+
_map = remove(_map)("9")
|
|
478
|
+
if (_map === undefined) { throw _map }
|
|
479
|
+
_s = jsonStr(_map);
|
|
480
|
+
if (_s !== '["1"]') { throw _s }
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
{
|
|
484
|
+
_map = remove(_map)("1")
|
|
485
|
+
if (_map !== undefined) { throw _map }
|
|
486
|
+
}
|
|
487
|
+
}
|
package/types/btree/set/index.js
CHANGED
|
@@ -5,13 +5,13 @@ const list = require('../../list')
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @template T
|
|
8
|
-
* @typedef {_.Branch1<T> | _.Branch3<T>}
|
|
8
|
+
* @typedef {_.Branch1<T> | _.Branch3<T>} Bracnh1To3
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
/** @type {<T>(b: _.Branch5<T> | _.Branch7<T>) =>
|
|
11
|
+
/** @type {<T>(b: _.Branch5<T> | _.Branch7<T>) => Bracnh1To3<T>} */
|
|
12
12
|
const b57 = b => b.length === 5 ? [b] : [[b[0], b[1], b[2]], b[3], [b[4], b[5], b[6]]]
|
|
13
13
|
|
|
14
|
-
/** @type {<T>(a:
|
|
14
|
+
/** @type {<T>(a: Bracnh1To3<T>) => (i: find.PathItem<T>) => Bracnh1To3<T>} */
|
|
15
15
|
const reduce = a => i => {
|
|
16
16
|
switch (i[0]) {
|
|
17
17
|
case 0: {
|
|
@@ -39,7 +39,7 @@ const reduce = a => i => {
|
|
|
39
39
|
const set = c => value => node => {
|
|
40
40
|
const { first, tail } = find.find(c)(node)
|
|
41
41
|
/** @typedef {typeof value} T */
|
|
42
|
-
/** @type {() =>
|
|
42
|
+
/** @type {() => Bracnh1To3<T>} */
|
|
43
43
|
const f = () => {
|
|
44
44
|
switch (first[0]) {
|
|
45
45
|
case 0: {
|
package/types/btree/test.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const btree = require('.')
|
|
2
|
-
const {
|
|
2
|
+
const { values } = btree
|
|
3
3
|
const json = require('../../json')
|
|
4
4
|
const { sort } = require('../object')
|
|
5
5
|
const { stringCmp } = require('../function/compare')
|
|
6
6
|
const list = require('../list')
|
|
7
|
+
const s = require('./set')
|
|
8
|
+
const f = require('./find')
|
|
7
9
|
|
|
8
10
|
require('./find/test')
|
|
9
11
|
require('./set/test')
|
|
@@ -15,13 +17,7 @@ const jsonStr = json.stringify(sort)
|
|
|
15
17
|
const stringify = sequence => jsonStr(list.toArray(sequence))
|
|
16
18
|
|
|
17
19
|
/** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
|
|
18
|
-
const set = node => value =>
|
|
19
|
-
const result = setVisitor(stringCmp(value))(node)(() => value)
|
|
20
|
-
switch (result[0]) {
|
|
21
|
-
case 'replace': case 'overflow': { return result[1] }
|
|
22
|
-
default: { return node }
|
|
23
|
-
}
|
|
24
|
-
}
|
|
20
|
+
const set = node => value => s.set(stringCmp(value))(value)(node)
|
|
25
21
|
|
|
26
22
|
{
|
|
27
23
|
/** @type {btree.Node<string>} */
|
|
@@ -49,8 +45,8 @@ const set = node => value => {
|
|
|
49
45
|
let _map = ['a']
|
|
50
46
|
_map = set(_map)('b')
|
|
51
47
|
_map = set(_map)('c')
|
|
52
|
-
const result =
|
|
53
|
-
if (result
|
|
48
|
+
const result = f.value(f.find(stringCmp('b'))(_map).first)
|
|
49
|
+
if (result !== 'b') { throw result }
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
{
|
|
@@ -58,52 +54,10 @@ const set = node => value => {
|
|
|
58
54
|
let _map = ['a']
|
|
59
55
|
_map = set(_map)('b')
|
|
60
56
|
_map = set(_map)('c')
|
|
61
|
-
const result =
|
|
57
|
+
const result = f.value(f.find(stringCmp('e'))(_map).first)
|
|
62
58
|
if (result !== undefined) { throw result }
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
{
|
|
66
|
-
/** @type {btree.Node<string>} */
|
|
67
|
-
let _map = ['1']
|
|
68
|
-
for (let i = 2; i <= 10; i++)
|
|
69
|
-
_map = set(_map)((i * i).toString())
|
|
70
|
-
if (_map.length !== 3) { throw _map }
|
|
71
|
-
let _s = jsonStr(_map)
|
|
72
|
-
if (_s !== '[[["1","100"],"16",["25","36"]],"4",[["49"],"64",["81","9"]]]') { throw _s }
|
|
73
|
-
|
|
74
|
-
let [a,,b] = _map
|
|
75
|
-
let _c = concat(a)(b)
|
|
76
|
-
if (_c.length !== 3) { throw _c }
|
|
77
|
-
_s =jsonStr(_c);
|
|
78
|
-
if (_s !== '[[["1","100"],"16",["25"]],"36",[["49"],"64",["81","9"]]]') { throw _s }
|
|
79
|
-
|
|
80
|
-
[a,,b] = _c
|
|
81
|
-
_c = concat(a)(b)
|
|
82
|
-
if (_c.length !== 1) { throw _c }
|
|
83
|
-
_s = jsonStr(_c);
|
|
84
|
-
if (_s !== '[[["1","100"],"16",["25","49"],"64",["81","9"]]]') { throw _s }
|
|
85
|
-
|
|
86
|
-
let [_r] = _c
|
|
87
|
-
if (_r.length !== 5) { throw _r }
|
|
88
|
-
[a,,b] = _r
|
|
89
|
-
_c = concat(a)(b)
|
|
90
|
-
if (_c.length !== 3) { throw _c }
|
|
91
|
-
_s = jsonStr(_c);
|
|
92
|
-
if (_s !== '[["1"],"100",["25","49"]]') { throw _s }
|
|
93
|
-
|
|
94
|
-
[a,,b] = _c
|
|
95
|
-
_c = concat(a)(b)
|
|
96
|
-
if (_c.length !== 3) { throw _c }
|
|
97
|
-
_s = jsonStr(_c);
|
|
98
|
-
if (_s !== '[["1"],"25",["49"]]') { throw _s }
|
|
99
|
-
|
|
100
|
-
[a,,b] = _c
|
|
101
|
-
_c = concat(a)(b)
|
|
102
|
-
if (_c.length !== 1) { throw _c }
|
|
103
|
-
_s = jsonStr(_c);
|
|
104
|
-
if (_s !== '[["1","49"]]') { throw _s }
|
|
105
|
-
}
|
|
106
|
-
|
|
107
61
|
const test = () => {
|
|
108
62
|
/** @type {btree.Node<string>} */
|
|
109
63
|
let _map = ['a']
|
package/types/map/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const option = require("../option")
|
|
2
2
|
const btree = require('../btree')
|
|
3
|
-
const {
|
|
3
|
+
const { values } = require("../btree")
|
|
4
|
+
const find = require('../btree/find')
|
|
5
|
+
const s = require('../btree/set')
|
|
4
6
|
const compare = require("../function/compare")
|
|
5
7
|
const { stringCmp } = require("../function/compare")
|
|
6
8
|
const list = require("../list")
|
|
@@ -38,7 +40,7 @@ const keyCmp = a => ([b]) => stringCmp(a)(b)
|
|
|
38
40
|
/** @type {(name: string) => <T>(map: Map<T>) => T|undefined} */
|
|
39
41
|
const at = name => map => {
|
|
40
42
|
if (map === undefined) { return undefined }
|
|
41
|
-
const result =
|
|
43
|
+
const result = find.value(find.find(keyCmp(name))(map).first)
|
|
42
44
|
return result === undefined ? undefined : result[1]
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -47,11 +49,7 @@ const set = name => value => map => {
|
|
|
47
49
|
/** @type {Entry<typeof value>} */
|
|
48
50
|
const entry = [name, value]
|
|
49
51
|
if (map === undefined) { return [entry] }
|
|
50
|
-
|
|
51
|
-
switch (result[0]) {
|
|
52
|
-
case 'replace': case 'overflow': { return result[1] }
|
|
53
|
-
default: { throw 'invalid BTree operation' }
|
|
54
|
-
}
|
|
52
|
+
return s.set(keyCmp(name))(entry)(map)
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
/** @type {<T>(map: Map<T>) => list.List<Entry<T>>} */
|