functionalscript 0.0.306 → 0.0.310
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/README.md +12 -4
- package/commonjs/path/index.js +5 -5
- package/package.json +1 -1
- package/test.js +1 -0
- package/types/btree/find/index.js +13 -5
- package/types/btree/index.js +15 -6
- package/types/btree/remove/index.js +9 -4
- package/types/btree/remove/test.js +1 -1
- package/types/btree/set/index.js +5 -2
- package/types/function/index.js +9 -4
- package/types/list/index.js +31 -35
- package/types/map/index.js +17 -29
- package/types/map/test.js +3 -1
- package/types/stringSet/index.js +36 -0
- package/types/stringSet/test.js +33 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# FunctionalScript
|
|
2
2
|
|
|
3
|
-
FunctionalScript is a
|
|
3
|
+
FunctionalScript is a purely functional programming language and a strict subset of
|
|
4
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.
|
|
@@ -16,6 +16,14 @@ Create a new FunctionalScript repository on GitHub [here](https://github.com/fun
|
|
|
16
16
|
In FunctionalScript:
|
|
17
17
|
|
|
18
18
|
- Any module is a valid JavaScript module. No additional build steps are required.
|
|
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.
|
|
20
|
-
- A module can't depend on non FunctionalScript module.
|
|
21
|
-
- It also has no standard library
|
|
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.
|
|
20
|
+
- A module can't depend on a non FunctionalScript module.
|
|
21
|
+
- It also has no standard library. Only a safe subset of standard JavaScript API can be used without referencing other modules.
|
|
22
|
+
|
|
23
|
+
## Applications
|
|
24
|
+
|
|
25
|
+
FunctionalScript code can be used
|
|
26
|
+
|
|
27
|
+
- in any JavaScript/TypeScript application,
|
|
28
|
+
- as a JSON with expressions,
|
|
29
|
+
- as a query language.
|
package/commonjs/path/index.js
CHANGED
|
@@ -21,18 +21,18 @@ const split = path => path.split('/')
|
|
|
21
21
|
/** @typedef {readonly[list.List<string>] | undefined} OptionList */
|
|
22
22
|
|
|
23
23
|
/** @type {(s: OptionList) => (items: string) => OptionList} */
|
|
24
|
-
const normItemsOp = prior =>
|
|
24
|
+
const normItemsOp = prior => first => {
|
|
25
25
|
if (prior === undefined) { return undefined }
|
|
26
|
-
const
|
|
27
|
-
switch (
|
|
26
|
+
const tail = prior[0]
|
|
27
|
+
switch (first) {
|
|
28
28
|
case '': case '.': { return prior }
|
|
29
29
|
case '..': {
|
|
30
|
-
const result = list.next(
|
|
30
|
+
const result = list.next(tail)
|
|
31
31
|
if (result === undefined) { return undefined }
|
|
32
32
|
return [result.tail]
|
|
33
33
|
}
|
|
34
34
|
default: {
|
|
35
|
-
return [
|
|
35
|
+
return [{ first, tail }]
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -11,6 +11,7 @@ require('./commonjs/package/dependencies/test')
|
|
|
11
11
|
require('./commonjs/package/test')
|
|
12
12
|
require('./commonjs/path/test')
|
|
13
13
|
require('./types/function/compare/test')
|
|
14
|
+
require('./types/stringSet/test')
|
|
14
15
|
|
|
15
16
|
/** @type {() => never} */
|
|
16
17
|
const assert = () => { throw 'assert' }
|
|
@@ -44,10 +44,8 @@ const array = require('../../array')
|
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
46
|
/** @type {<T>(item: PathItem<T>) => _.Node<T>} */
|
|
47
|
-
const child = item =>
|
|
48
|
-
/** @
|
|
49
|
-
return /** @type {_.Node<T>} */(item[1][item[0]])
|
|
50
|
-
}
|
|
47
|
+
const child = item =>
|
|
48
|
+
/** @type {typeof item extends PathItem<infer T> ? _.Node<T> : never} */(item[1][item[0]])
|
|
51
49
|
|
|
52
50
|
/**
|
|
53
51
|
* @template T
|
|
@@ -98,6 +96,14 @@ const find = c => {
|
|
|
98
96
|
return f(undefined)
|
|
99
97
|
}
|
|
100
98
|
|
|
99
|
+
/** @type {<T>(first: First<T>) => boolean} */
|
|
100
|
+
const isFound = first => {
|
|
101
|
+
switch (first[0]) {
|
|
102
|
+
case 1: case 3: { return true }
|
|
103
|
+
default: { return false }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
101
107
|
/** @type {<T>(first: First<T>) => T | undefined} */
|
|
102
108
|
const value = first => {
|
|
103
109
|
switch (first[0]) {
|
|
@@ -123,4 +129,6 @@ module.exports = {
|
|
|
123
129
|
find,
|
|
124
130
|
/** @readonly */
|
|
125
131
|
value,
|
|
126
|
-
|
|
132
|
+
/** @readonly */
|
|
133
|
+
isFound,
|
|
134
|
+
}
|
package/types/btree/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const seq = require('../list')
|
|
2
|
+
const option = require('../option')
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @template T
|
|
@@ -48,24 +49,29 @@ const seq = require('../list')
|
|
|
48
49
|
* @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} Node
|
|
49
50
|
*/
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @template T
|
|
54
|
+
* @typedef {Node<T> | undefined} Tree
|
|
55
|
+
*/
|
|
56
|
+
|
|
51
57
|
/** @type {<T>(node: Node<T>) => seq.Thunk<T>} */
|
|
52
|
-
const
|
|
58
|
+
const nodeValues = node => () => {
|
|
53
59
|
switch (node.length) {
|
|
54
60
|
case 1: case 2: { return node }
|
|
55
61
|
case 3: {
|
|
56
62
|
return seq.flat([
|
|
57
|
-
|
|
63
|
+
nodeValues(node[0]),
|
|
58
64
|
[node[1]],
|
|
59
|
-
|
|
65
|
+
nodeValues(node[2])
|
|
60
66
|
])
|
|
61
67
|
}
|
|
62
68
|
default: {
|
|
63
69
|
return seq.flat([
|
|
64
|
-
|
|
70
|
+
nodeValues(node[0]),
|
|
65
71
|
[node[1]],
|
|
66
|
-
|
|
72
|
+
nodeValues(node[2]),
|
|
67
73
|
[node[3]],
|
|
68
|
-
|
|
74
|
+
nodeValues(node[4])
|
|
69
75
|
])
|
|
70
76
|
}
|
|
71
77
|
}
|
|
@@ -81,6 +87,9 @@ const values = node => () => {
|
|
|
81
87
|
* @typedef { readonly[...Branch5<T>, T, Node<T>] } Branch7
|
|
82
88
|
*/
|
|
83
89
|
|
|
90
|
+
/** @type {<T>(tree: Tree<T>) => seq.List<T>} */
|
|
91
|
+
const values = option.map(nodeValues)
|
|
92
|
+
|
|
84
93
|
module.exports = {
|
|
85
94
|
/** @readonly */
|
|
86
95
|
values,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const _ = require('..')
|
|
2
|
-
const { todo } = require('../../../dev')
|
|
3
2
|
const cmp = require('../../function/compare')
|
|
4
3
|
const find = require('../find')
|
|
5
4
|
const list = require('../../list')
|
|
6
5
|
const array = require('../../array')
|
|
6
|
+
const option = require('../../option')
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @template T
|
|
@@ -118,8 +118,8 @@ const reduce = list.reduce(reduceX([reduceValue0, reduceValue2]))
|
|
|
118
118
|
|
|
119
119
|
const initReduce = reduceX([initValue0, initValue1])
|
|
120
120
|
|
|
121
|
-
/** @type {<T>(c: cmp.Compare<T>) => (node: _.Node<T>) =>
|
|
122
|
-
const
|
|
121
|
+
/** @type {<T>(c: cmp.Compare<T>) => (node: _.Node<T>) => _.Tree<T>} */
|
|
122
|
+
const nodeRemove = c => node => {
|
|
123
123
|
/** @typedef {typeof c extends cmp.Compare<infer T> ? T : never} T */
|
|
124
124
|
/** @type {() => undefined | RemovePath<T>} */
|
|
125
125
|
const f = () => {
|
|
@@ -159,7 +159,12 @@ const remove = c => node => {
|
|
|
159
159
|
return result.length === 1 ? result[0] : result
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
/** @type {<T>(c: cmp.Compare<T>) => (tree: _.Tree<T>) => _.Tree<T>} */
|
|
163
|
+
const remove = c => option.map(nodeRemove(c))
|
|
164
|
+
|
|
162
165
|
module.exports = {
|
|
166
|
+
/** @readonly */
|
|
167
|
+
nodeRemove,
|
|
163
168
|
/** @readonly */
|
|
164
169
|
remove,
|
|
165
|
-
}
|
|
170
|
+
}
|
|
@@ -9,7 +9,7 @@ const { sort } = require('../../object')
|
|
|
9
9
|
const set = node => value => s.set(stringCmp(value))(value)(node)
|
|
10
10
|
|
|
11
11
|
/** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string> | undefined} */
|
|
12
|
-
const remove = node => value => _.
|
|
12
|
+
const remove = node => value => _.nodeRemove(stringCmp(value))(node)
|
|
13
13
|
|
|
14
14
|
const jsonStr = json.stringify(sort)
|
|
15
15
|
|
package/types/btree/set/index.js
CHANGED
|
@@ -36,7 +36,7 @@ const reduce = a => i => {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/** @type {<T>(c: cmp.Compare<T>) => (value: T) => (node: _.Node<T>) => _.Node<T>} */
|
|
39
|
-
const
|
|
39
|
+
const nodeSet = c => value => node => {
|
|
40
40
|
const { first, tail } = find.find(c)(node)
|
|
41
41
|
/** @typedef {typeof value} T */
|
|
42
42
|
/** @type {() => Bracnh1To3<T>} */
|
|
@@ -87,7 +87,10 @@ const set = c => value => node => {
|
|
|
87
87
|
return r.length === 1 ? r[0] : r
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/** @type {<T>(c: cmp.Compare<T>) => (value: T) => (tree: _.Tree<T>) => _.Node<T>} */
|
|
91
|
+
const set = c => value => tree => tree === undefined ? [value] : nodeSet(c)(value)(tree)
|
|
92
|
+
|
|
90
93
|
module.exports = {
|
|
91
94
|
/** @readonly */
|
|
92
95
|
set,
|
|
93
|
-
}
|
|
96
|
+
}
|
package/types/function/index.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
2
|
* @template I
|
|
3
3
|
* @template O
|
|
4
|
-
* @typedef {(_: I) => O} Func
|
|
4
|
+
* @typedef {(_: I) => O} Func
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
8
|
* Postfix Compose function.
|
|
9
9
|
*
|
|
10
|
-
* @type {<I, X>(g: Func<I, X>) => <O>(f: Func<X, O>) => Func<I, O>}
|
|
10
|
+
* @type {<I, X>(g: Func<I, X>) => <O>(f: Func<X, O>) => Func<I, O>}
|
|
11
11
|
*/
|
|
12
12
|
const compose = g => f => x => f(g(x))
|
|
13
13
|
|
|
14
14
|
/** @type {<T>(value: T) => T} */
|
|
15
15
|
const identity = value => value
|
|
16
16
|
|
|
17
|
+
/** @type {<A, B, C>(f: (a: A) => (b: B) => C) => (b: B) => (a: A) => C} */
|
|
18
|
+
const flip = f => b => a => f(a)(b)
|
|
19
|
+
|
|
17
20
|
module.exports = {
|
|
18
21
|
/** @readonly */
|
|
19
22
|
identity,
|
|
20
23
|
/** @readonly */
|
|
21
24
|
compose,
|
|
25
|
+
/** @reeadonly */
|
|
26
|
+
flip,
|
|
22
27
|
}
|
package/types/list/index.js
CHANGED
|
@@ -44,14 +44,13 @@ const { logicalNot, strictEqual, stateScanToScan, reduceToScan, foldToScan } = r
|
|
|
44
44
|
* }} Concat
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
-
/** @type {<T>(first: T) => (tail: List<T>) => NonEmpty<T>} */
|
|
48
|
-
const nonEmpty = first => tail => ({ first, tail })
|
|
49
|
-
|
|
50
|
-
/** @type {(i: number) => <T>(array: readonly T[]) => Result<T>} */
|
|
51
|
-
const fromArrayAt = i => array => i < array.length ? nonEmpty(array[i])(() => fromArrayAt(i + 1)(array)) : undefined
|
|
52
|
-
|
|
53
47
|
/** @type {<T>(array: readonly T[]) => Result<T>} */
|
|
54
|
-
const fromArray =
|
|
48
|
+
const fromArray = array => {
|
|
49
|
+
/** @typedef {typeof array extends readonly (infer T)[] ? T : never} T */
|
|
50
|
+
/** @type {(i: number) => Result<T>} */
|
|
51
|
+
const at = i => i < array.length ? { first: array[i], tail: () => at(i + 1) } : undefined
|
|
52
|
+
return at(0)
|
|
53
|
+
}
|
|
55
54
|
|
|
56
55
|
/** @type {<T>(a: List<T>) => (b: List<T>) => List<T>} */
|
|
57
56
|
const concat = a => b => b === undefined ? a : ({ isConcat: true, a, b })
|
|
@@ -78,7 +77,7 @@ const next = list => {
|
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
if (a !== undefined) {
|
|
81
|
-
return
|
|
80
|
+
return { first: a.first, tail: concat(a.tail)(b) }
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
if (b === undefined) { return undefined }
|
|
@@ -120,7 +119,7 @@ const flatStep = n => concat(n.first)(flat(n.tail))
|
|
|
120
119
|
const flat = apply(flatStep)
|
|
121
120
|
|
|
122
121
|
/** @type {<I, O>(f: (value: I) => O) => (n: NonEmpty<I>) => List<O>} */
|
|
123
|
-
const mapStep = f => n =>
|
|
122
|
+
const mapStep = f => n => ({ first: f(n.first), tail: map(f)(n.tail) })
|
|
124
123
|
|
|
125
124
|
/** @type {<I, O>(f: (value: I) => O) => (input: List<I>) => List<O>} */
|
|
126
125
|
const map = f => apply(mapStep(f))
|
|
@@ -131,7 +130,7 @@ const flatMap = f => compose(map(f))(flat)
|
|
|
131
130
|
/** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
|
|
132
131
|
const filterStep = f => n => {
|
|
133
132
|
const tail = filter(f)(n.tail)
|
|
134
|
-
return f(n.first) ?
|
|
133
|
+
return f(n.first) ? { first: n.first, tail } : tail
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => List<T>} */
|
|
@@ -140,20 +139,20 @@ const filter = f => apply(filterStep(f))
|
|
|
140
139
|
/** @type {<I, O>(f: (value: I) => O|undefined) => (n: NonEmpty<I>) => List<O>} */
|
|
141
140
|
const filterMapStep = f => n => {
|
|
142
141
|
const [first, tail] = [f(n.first), filterMap(f)(n.tail)]
|
|
143
|
-
return first === undefined ? tail :
|
|
142
|
+
return first === undefined ? tail : { first, tail }
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
/** @type {<I, O>(f: (value: I) => O|undefined) => (input: List<I>) => List<O>} */
|
|
147
146
|
const filterMap = f => apply(filterMapStep(f))
|
|
148
147
|
|
|
149
148
|
/** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
|
|
150
|
-
const takeWhileStep = f => n => f(n.first) ?
|
|
149
|
+
const takeWhileStep = f => n => f(n.first) ? { first: n.first, tail: takeWhile(f)(n.tail) } : undefined
|
|
151
150
|
|
|
152
151
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => List<T>} */
|
|
153
152
|
const takeWhile = f => apply(takeWhileStep(f))
|
|
154
153
|
|
|
155
154
|
/** @type {(n: number) => <T>(result: NonEmpty<T>) => List<T>} */
|
|
156
|
-
const takeStep = n => ne => 0 < n ?
|
|
155
|
+
const takeStep = n => ne => 0 < n ? { first: ne.first, tail: take(n - 1)(ne.tail) } : undefined
|
|
157
156
|
|
|
158
157
|
/** @type {(n: number) => <T>(input: List<T>) => List<T>} */
|
|
159
158
|
const take = n => apply(takeStep(n))
|
|
@@ -177,10 +176,11 @@ const first = def => input => {
|
|
|
177
176
|
return result.first
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
/** @type {<D>(
|
|
181
|
-
const last =
|
|
182
|
-
/** @typedef {typeof
|
|
183
|
-
|
|
179
|
+
/** @type {<D>(first: D) => <T>(tail: List<T>) => D|T} */
|
|
180
|
+
const last = first => tail => {
|
|
181
|
+
/** @typedef {typeof tail extends List<infer T> ? T : never} T */
|
|
182
|
+
/** @type {NonEmpty<typeof first|T>} */
|
|
183
|
+
let i = { first, tail }
|
|
184
184
|
while (true) {
|
|
185
185
|
const result = next(i.tail)
|
|
186
186
|
if (result === undefined) {
|
|
@@ -212,19 +212,19 @@ const includes = value => input => some(map(strictEqual(value))(input))
|
|
|
212
212
|
const countdown = count => () => {
|
|
213
213
|
if (count <= 0) { return undefined }
|
|
214
214
|
const first = count - 1
|
|
215
|
-
return
|
|
215
|
+
return { first, tail: countdown(first) }
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
/** @type {<T>(list: List<T>) => List<T>} */
|
|
219
219
|
const cycle = list => () => {
|
|
220
220
|
const i = next(list)
|
|
221
|
-
return i === undefined ? undefined :
|
|
221
|
+
return i === undefined ? undefined : { first: i.first, tail: concat(i.tail)(cycle(list)) }
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
/** @type {<I, O>(op: operator.Scan<I, O>) => (ne: NonEmpty<I>) => List<O>} */
|
|
225
225
|
const scanStep = op => ne => {
|
|
226
|
-
const [
|
|
227
|
-
return
|
|
226
|
+
const [first, newOp] = op(ne.first)
|
|
227
|
+
return { first, tail: scan(newOp)(ne.tail) }
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/** @type {<I, O>(op: operator.Scan<I, O>) => (input: List<I>) => List<O>} */
|
|
@@ -263,13 +263,13 @@ const length = reduce(operator.counter)(0)
|
|
|
263
263
|
const entryOperator = index => value => [[index, value], index + 1]
|
|
264
264
|
|
|
265
265
|
/** @type {<T>(input: List<T>) => List<Entry<T>>} */
|
|
266
|
-
const entries =
|
|
266
|
+
const entries = input => {
|
|
267
267
|
/** @typedef {typeof input extends List<infer T> ? T : never} T */
|
|
268
268
|
return stateScan(/** @type {operator.StateScan<T, Number, Entry<T>>} */(entryOperator))(0)(input)
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/** @type {<T>(prior: List<T>) => (value: T) => List<T>} */
|
|
272
|
-
const reverseOperator =
|
|
272
|
+
const reverseOperator = tail => first => ({ first, tail })
|
|
273
273
|
|
|
274
274
|
/** @type {<T>(input: List<T>) => List<T>} */
|
|
275
275
|
const reverse = reduce(reverseOperator)(undefined)
|
|
@@ -283,15 +283,15 @@ const zip = a => b => () => {
|
|
|
283
283
|
if (aResult === undefined) { return undefined }
|
|
284
284
|
const bResult = next(b)
|
|
285
285
|
if (bResult === undefined) { return undefined }
|
|
286
|
-
return
|
|
286
|
+
return { first: tuple2(aResult.first)(bResult.first), tail: zip(aResult.tail)(bResult.tail) }
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => List<boolean>} */
|
|
290
290
|
const equalZip = e => a => b => () => {
|
|
291
291
|
const [aResult, bResult] = [next(a), next(b)]
|
|
292
292
|
return aResult === undefined || bResult === undefined
|
|
293
|
-
?
|
|
294
|
-
:
|
|
293
|
+
? { first: aResult === bResult, tail: undefined }
|
|
294
|
+
: { first: e(aResult.first)(bResult.first), tail: equalZip(e)(aResult.tail)(bResult.tail) }
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
/** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => boolean} */
|
|
@@ -299,24 +299,20 @@ const equal = e => a => b => every(equalZip(e)(a)(b))
|
|
|
299
299
|
|
|
300
300
|
/** @type {(s: string) => List<number>} */
|
|
301
301
|
const toCharCodes = s => {
|
|
302
|
-
/** @type {(i: number) =>
|
|
303
|
-
const at = i =>
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
return { first: r, tail: at(i + 1) }
|
|
302
|
+
/** @type {(i: number) => Result<number>} */
|
|
303
|
+
const at = i => {
|
|
304
|
+
const first = s.charCodeAt(i)
|
|
305
|
+
return isNaN(first) ? undefined : { first, tail: () => at(i + 1) }
|
|
307
306
|
}
|
|
308
307
|
return at(0)
|
|
309
308
|
}
|
|
310
309
|
|
|
311
|
-
|
|
312
|
-
const fromCharCodes = x => fold(operator.concat)('')(map(String.fromCharCode)(x))
|
|
310
|
+
const fromCharCodes = compose(map(String.fromCharCode))(fold(operator.concat)(''))
|
|
313
311
|
|
|
314
312
|
module.exports = {
|
|
315
313
|
/** @readonly */
|
|
316
314
|
empty: undefined,
|
|
317
315
|
/** @readonly */
|
|
318
|
-
nonEmpty,
|
|
319
|
-
/** @readonly */
|
|
320
316
|
concat,
|
|
321
317
|
/** @readonly */
|
|
322
318
|
next,
|
package/types/map/index.js
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
const option = require("../option")
|
|
2
1
|
const btree = require('../btree')
|
|
3
2
|
const { values } = require("../btree")
|
|
4
3
|
const find = require('../btree/find')
|
|
5
4
|
const s = require('../btree/set')
|
|
6
|
-
const compare = require(
|
|
7
|
-
const { stringCmp } = require(
|
|
8
|
-
const list = require(
|
|
5
|
+
const compare = require('../function/compare')
|
|
6
|
+
const { stringCmp } = require('../function/compare')
|
|
7
|
+
const list = require('../list')
|
|
8
|
+
const btRemove = require('../btree/remove')
|
|
9
|
+
const { flip } = require('../function')
|
|
9
10
|
|
|
10
11
|
/** @typedef {compare.Sign} Sign */
|
|
11
12
|
|
|
12
|
-
/**
|
|
13
|
-
* @template T
|
|
14
|
-
* @typedef {btree.Leaf1<T>} Leaf1
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @template T
|
|
19
|
-
* @typedef {btree.Node<T>} TNode
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
13
|
/**
|
|
23
14
|
* @template T
|
|
24
15
|
* @typedef {compare.Compare<T>} Cmp
|
|
@@ -31,7 +22,7 @@ const list = require("../list")
|
|
|
31
22
|
|
|
32
23
|
/**
|
|
33
24
|
* @template T
|
|
34
|
-
* @typedef {
|
|
25
|
+
* @typedef {btree.Tree<Entry<T>>} Map
|
|
35
26
|
*/
|
|
36
27
|
|
|
37
28
|
/** @type {(a: string) => <T>(b: Entry<T>) => Sign} */
|
|
@@ -44,25 +35,20 @@ const at = name => map => {
|
|
|
44
35
|
return result === undefined ? undefined : result[1]
|
|
45
36
|
}
|
|
46
37
|
|
|
38
|
+
/** @type {<T>(entry: Entry<T>) => (map: Map<T>) => Map<T>} */
|
|
39
|
+
const setEntry = entry => s.set(keyCmp(entry[0]))(entry)
|
|
40
|
+
|
|
47
41
|
/** @type {(name: string) => <T>(value: T) => (map: Map<T>) => Map<T>} */
|
|
48
|
-
const set = name => value =>
|
|
49
|
-
/** @type {Entry<typeof value>} */
|
|
50
|
-
const entry = [name, value]
|
|
51
|
-
if (map === undefined) { return [entry] }
|
|
52
|
-
return s.set(keyCmp(name))(entry)(map)
|
|
53
|
-
}
|
|
42
|
+
const set = name => value => setEntry([name, value])
|
|
54
43
|
|
|
55
44
|
/** @type {<T>(map: Map<T>) => list.List<Entry<T>>} */
|
|
56
|
-
const entries =
|
|
57
|
-
|
|
58
|
-
/** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
|
|
59
|
-
const setOp = map => ([name, value]) => set(name)(value)(map)
|
|
45
|
+
const entries = values
|
|
60
46
|
|
|
61
47
|
/** @type {<T>(entries: list.List<Entry<T>>) => Map<T>} */
|
|
62
|
-
const fromEntries =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
const fromEntries = list.reduce(flip(setEntry))(undefined)
|
|
49
|
+
|
|
50
|
+
/** @type {(name: string) => <T>(map: Map<T>) => Map<T>} */
|
|
51
|
+
const remove = name => btRemove.remove(keyCmp(name))
|
|
66
52
|
|
|
67
53
|
module.exports = {
|
|
68
54
|
/** @readonly */
|
|
@@ -75,4 +61,6 @@ module.exports = {
|
|
|
75
61
|
entries,
|
|
76
62
|
/** @readonly */
|
|
77
63
|
fromEntries,
|
|
64
|
+
/** @readonly */
|
|
65
|
+
remove,
|
|
78
66
|
}
|
package/types/map/test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { at, set, empty, entries } = require('.')
|
|
1
|
+
const { at, set, empty, entries, remove } = require('.')
|
|
2
2
|
const seq = require('../list')
|
|
3
3
|
|
|
4
4
|
{
|
|
@@ -38,6 +38,8 @@ const seq = require('../list')
|
|
|
38
38
|
if (at('x')(m) !== undefined) { throw 'error' }
|
|
39
39
|
|
|
40
40
|
// console.log(Array.from(m.entries()))
|
|
41
|
+
m = remove('Hello world!')(m)
|
|
42
|
+
if (at('Hello world!')(m) !== undefined) { throw m }
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
{
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const btree = require('../btree')
|
|
2
|
+
const find = require('../btree/find')
|
|
3
|
+
const btSet = require('../btree/set')
|
|
4
|
+
const btRemove = require('../btree/remove')
|
|
5
|
+
const { stringCmp } = require("../function/compare")
|
|
6
|
+
const list = require('../list')
|
|
7
|
+
const { flip, compose } = require('../function')
|
|
8
|
+
|
|
9
|
+
/** @typedef {btree.Tree<string>} StringSet */
|
|
10
|
+
|
|
11
|
+
/** @type {(value: string) => (set: StringSet) => boolean} */
|
|
12
|
+
const contains = value => s => s !== undefined && find.isFound(find.find(stringCmp(value))(s).first)
|
|
13
|
+
|
|
14
|
+
/** @type {(value: string) => (s: StringSet) => StringSet} */
|
|
15
|
+
const set = value => btSet.set(stringCmp(value))(value)
|
|
16
|
+
|
|
17
|
+
/** @type {(s: StringSet) => list.List<string>} */
|
|
18
|
+
const values = btree.values
|
|
19
|
+
|
|
20
|
+
const fromValues = list.reduce(flip(set))(undefined)
|
|
21
|
+
|
|
22
|
+
/** @type {(value: string) => (s: StringSet) => StringSet} */
|
|
23
|
+
const remove = compose(stringCmp)(btRemove.remove)
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
/** @readonly */
|
|
27
|
+
contains,
|
|
28
|
+
/** @readonly */
|
|
29
|
+
set,
|
|
30
|
+
/** @readonly */
|
|
31
|
+
values,
|
|
32
|
+
/** @readonly */
|
|
33
|
+
fromValues,
|
|
34
|
+
/** @readonly */
|
|
35
|
+
remove,
|
|
36
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
const r = _.set('hello')(undefined)
|
|
5
|
+
if (!_.contains('hello')(r)) { throw r }
|
|
6
|
+
if (_.contains('hello1')(r)) { throw r }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
let r = _.set('hello')(undefined)
|
|
11
|
+
r = _.set('world')(r)
|
|
12
|
+
r = _.set('HELLO')(r)
|
|
13
|
+
r = _.set('WORLD!')(r)
|
|
14
|
+
if (!_.contains('hello')(r)) { throw r }
|
|
15
|
+
if (_.contains('hello1')(r)) { throw r }
|
|
16
|
+
if (!_.contains('HELLO')(r)) { throw r }
|
|
17
|
+
if (_.contains('WORLD')(r)) { throw r }
|
|
18
|
+
if (!_.contains('world')(r)) { throw r }
|
|
19
|
+
if (_.contains('world!')(r)) { throw r }
|
|
20
|
+
if (!_.contains('WORLD!')(r)) { throw r }
|
|
21
|
+
//
|
|
22
|
+
r = _.remove('hello')(r)
|
|
23
|
+
if (_.contains('hello')(r)) { throw r }
|
|
24
|
+
if (!_.contains('world')(r)) { throw r }
|
|
25
|
+
r = _.remove('world')(r)
|
|
26
|
+
if (_.contains('world')(r)) { throw r }
|
|
27
|
+
if (!_.contains('HELLO')(r)) { throw r }
|
|
28
|
+
r = _.remove('HELLO')(r)
|
|
29
|
+
if (_.contains('HELLO')(r)) { throw r }
|
|
30
|
+
if (!_.contains('WORLD!')(r)) { throw r }
|
|
31
|
+
r = _.remove('WORLD!')(r)
|
|
32
|
+
if (r !== undefined) { throw r }
|
|
33
|
+
}
|