functionalscript 0.0.238 → 0.0.242

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/types/map/test.js CHANGED
@@ -1,59 +1,60 @@
1
- const { empty } = require('.')
2
- const list = require('../sequence')
1
+ const { at, set, empty, entries } = require('.')
2
+ const seq = require('../list')
3
3
 
4
4
  {
5
- let m = empty.set('a')(1)
5
+ let m = set('a')(1)(undefined)
6
6
 
7
- if (m.get('a') !== 1) { throw 'error' }
8
- if (m.get('b') !== undefined) { throw 'error' }
7
+ if (at('a')(m) !== 1) { throw 'error' }
8
+ if (at('b')(m) !== undefined) { throw 'error' }
9
9
 
10
- m = m.set('b')(2)
10
+ m = set('b')(2)(m)
11
11
 
12
- if (m.get('a') !== 1) { throw 'error' }
13
- if (m.get('b') !== 2) { throw 'error' }
14
- if (m.get('c') !== undefined) { throw 'error' }
12
+ if (at('a')(m) !== 1) { throw 'error' }
13
+ if (at('b')(m) !== 2) { throw 'error' }
14
+ if (at('c')(m) !== undefined) { throw 'error' }
15
15
 
16
- m = m.set('z')(3)
16
+ m = set('z')(3)(m)
17
17
 
18
- if (m.get('a') !== 1) { throw 'error' }
19
- if (m.get('b') !== 2) { throw 'error' }
20
- if (m.get('z') !== 3) { throw 'error' }
21
- if (m.get('') !== undefined) { throw 'error' }
18
+ if (at('a')(m) !== 1) { throw 'error' }
19
+ if (at('b')(m) !== 2) { throw 'error' }
20
+ if (at('z')(m) !== 3) { throw 'error' }
21
+ if (at('')(m) !== undefined) { throw 'error' }
22
22
 
23
- m = m.set('')(4)
23
+ m = set('')(4)(m)
24
24
 
25
- if (m.get('a') !== 1) { throw 'error' }
26
- if (m.get('b') !== 2) { throw 'error' }
27
- if (m.get('z') !== 3) { throw 'error' }
28
- if (m.get('') !== 4) { throw 'error' }
29
- if (m.get('Hello world!') !== undefined) { throw 'error' }
25
+ if (at('a')(m) !== 1) { throw 'error' }
26
+ if (at('b')(m) !== 2) { throw 'error' }
27
+ if (at('z')(m) !== 3) { throw 'error' }
28
+ if (at('')(m) !== 4) { throw 'error' }
29
+ if (at('Hello world!')(m) !== undefined) { throw 'error' }
30
30
 
31
- m = m.set('Hello world!')(42)
31
+ m = set('Hello world!')(42)(m)
32
32
 
33
- if (m.get('a') !== 1) { throw 'error' }
34
- if (m.get('b') !== 2) { throw 'error' }
35
- if (m.get('z') !== 3) { throw 'error' }
36
- if (m.get('') !== 4) { throw 'error' }
37
- if (m.get('Hello world!') !== 42) { throw 'error' }
38
- if (m.get('x') !== undefined) { throw 'error' }
33
+ if (at('a')(m) !== 1) { throw 'error' }
34
+ if (at('b')(m) !== 2) { throw 'error' }
35
+ if (at('z')(m) !== 3) { throw 'error' }
36
+ if (at('')(m) !== 4) { throw 'error' }
37
+ if (at('Hello world!')(m) !== 42) { throw 'error' }
38
+ if (at('x')(m) !== undefined) { throw 'error' }
39
39
 
40
40
  // console.log(Array.from(m.entries()))
41
41
  }
42
42
 
43
43
  {
44
- const m = empty.set('x')(12).set('y')(44)
45
- if (m.get('x') !== 12) { throw 'error' }
46
- if (m.get('y') !== 44) { throw 'error' }
47
- if (m.get('a') !== undefined) { throw 'error' }
48
- const entries = Array.from(list.iterable(m.entries))
49
- if (entries.length !== 2) { throw 'error' }
44
+ let m = set('x')(12)(undefined)
45
+ m = set('y')(44)(m)
46
+ if (at('x')(m) !== 12) { throw 'error' }
47
+ if (at('y')(m) !== 44) { throw 'error' }
48
+ if (at('a')(m) !== undefined) { throw 'error' }
49
+ const e = seq.toArray(entries(m))
50
+ if (e.length !== 2) { throw 'error' }
50
51
  }
51
52
 
52
53
  {
53
54
  /** @type {import('.').Map<number>} */
54
55
  let m = empty
55
56
  for (let i = 0; i < 100_000; ++i) {
56
- m = m.set((i*i).toString())(i)
57
+ m = set((i * i).toString())(i)(m)
57
58
  /*
58
59
  console.log()
59
60
  console.log(`# ${i}`)
@@ -1,4 +1,4 @@
1
- const seq = require('../sequence')
1
+ const seq = require('../list')
2
2
  const map = require('../map')
3
3
 
4
4
  /**
@@ -16,8 +16,8 @@ const map = require('../map')
16
16
  /** @type {(name: string) => <T>(object: Map<T>) => T|undefined} */
17
17
  const at = name => object => Object.getOwnPropertyDescriptor(object, name)?.value
18
18
 
19
- /** @type {<T>(entries: seq.Sequence<Entry<T>>) => seq.Sequence<Entry<T>>} */
20
- const sort = entries => map.fromEntries(entries).entries
19
+ /** @type {<T>(entries: seq.List<Entry<T>>) => seq.List<Entry<T>>} */
20
+ const sort = entries => map.entries(map.fromEntries(entries))
21
21
 
22
22
  module.exports = {
23
23
  /** @readonly */
@@ -1,68 +0,0 @@
1
- # Sequences
2
-
3
- Sequence types:
4
-
5
- - Sequence
6
- - Array
7
- - Iterable
8
- - AsyncIterable
9
-
10
- # Sequence Types
11
-
12
- ```ts
13
- type Sequence<T> =
14
- readonly T[] |
15
- Thunk<T> |
16
-
17
- type Thunk<T> = () => Node<T>
18
-
19
- type Node<T> =
20
- undefined |
21
- { readonly first: T, readonly tail: Sequence<T> } |
22
- readonly[Sequence<T>, Sequence<T>]
23
- ```
24
-
25
- ## Functions
26
-
27
- See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
28
-
29
- - `length: Sequence<infer T> => number`
30
- - `at: number => Sequence<infer T> = T|undefined`
31
- - `concat: Sequence<infer T> => Sequence<T> => Sequence<T>`
32
- - `entries: Sequence<infer T> => Sequence<[number, T]>`
33
- - `every: (infer T => boolean) => Sequence<T> => boolean`
34
- - `filter: (infer T => boolean) => Sequence<T> => Sequence<T>`
35
- - `find: (infer T => boolean) => Sequence<T> => T`
36
- - `findIndex: (infer T => boolean) => Sequence<T> => number`
37
- - `flat: Sequence<Sequence<T>> => Sequence<T>`
38
- - `flatMap: (infer T => Sequence<infer R>) => Sequence<T> => Sequence<R>`
39
- - `includes: infer T => Sequence<T> => boolean`
40
- - `indexOf: infer T => Sequence<T> => number`
41
- - `join: string => Sequence<string> => string`
42
- - `lastIndexOf: infer T => Sequence<T> => number`
43
- - `map: (infer T => infer R) => Sequence<T> => Sequence<R>`
44
- - `reduce: ...Scan<T, R> => Sequence<T> => R`
45
- - `some: (infer T => boolean) => Sequence<T> => boolean`
46
-
47
- ### Priority 2.
48
-
49
- - `slice: number => number => Sequence<T> => Sequence<T>`
50
- - `reduceRight: ...Scan<T, R> => Sequence<T> => R`
51
- - `toLocalString: Locales => Sequence<T> => string`
52
-
53
- ### Priority 3.
54
-
55
- - `keys: Sequence<T> => Sequence<string>`
56
- - `values: Sequence<infer T> => Sequence<T>`
57
-
58
- ## Prohibited Array Operations
59
-
60
- - `copyWithin`
61
- - `fill`
62
- - `pop`
63
- - `push`
64
- - `reverse`
65
- - `shift`
66
- - `sort`
67
- - `splice`
68
- - `unshift`
@@ -1,382 +0,0 @@
1
- const { compose, identity } = require('../function')
2
- const { logicalNot, strictEqual, addition } = require('../function/operator')
3
- const op = require('../function/operator')
4
-
5
- /**
6
- * @template T
7
- * @typedef { readonly T[] | Thunk<T> } Sequence<T>
8
- */
9
-
10
- /**
11
- * @template T
12
- * @typedef { () => Node<T> } Thunk
13
- */
14
-
15
- /**
16
- * @template T
17
- * @typedef { Result<T> | Concat<T> } Node<T>
18
- */
19
-
20
- /**
21
- * @template T
22
- * @typedef { readonly[Sequence<T>, Sequence<T>] } Concat<T>
23
- */
24
-
25
- /**
26
- * @template T
27
- * @typedef { undefined | ResultOne<T> } Result
28
- */
29
-
30
- /**
31
- * @template T
32
- * @typedef {{ readonly first: T, readonly tail: Sequence<T> }} ResultOne
33
- */
34
-
35
- const empty = () => undefined
36
-
37
- /** @type {<T>(first: T) => (tail: Sequence<T>) => Sequence<T>} */
38
- const sequence = first => tail => () => ({ first, tail })
39
-
40
- /** @type {<T>(sequence: Sequence<T>) => Node<T>} */
41
- const nodeOne = sequence => [empty, sequence]
42
-
43
- /** @type {<T>(array: readonly T[]) => Result<T>} */
44
- const fromArray = array => {
45
- /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
46
- /** @type {(index: number) => Result<T>} */
47
- const at = index => {
48
- if (array.length <= index) { return undefined }
49
- return { first: array[index], tail: () => at(index + 1) }
50
- }
51
- return at(0)
52
- }
53
-
54
- /** @type {<T>(sequence: Sequence<T>) => Node<T>} */
55
- const node = sequence => sequence instanceof Array ? fromArray(sequence) : sequence()
56
-
57
- /** @type {<T>(a: Sequence<T>) => (b: Sequence<T>) => Thunk<T>} */
58
- const concat = a => b => () => [a, b]
59
-
60
- /** @type {<T>(sequence: Sequence<T>) => Result<T>} */
61
- const next = sequence => {
62
- let i = sequence
63
- while (true) {
64
- const n = node(i)
65
- if (!(n instanceof Array)) { return n }
66
- const [a, b] = n
67
- const aNode = node(a)
68
- if (aNode === undefined) {
69
- i = b
70
- } else if (aNode instanceof Array) {
71
- const [aa, ab] = aNode
72
- i = concat(aa)(concat(ab)(b))
73
- } else {
74
- const { first, tail } = aNode
75
- return { first, tail: concat(tail)(b) }
76
- }
77
- }
78
- }
79
-
80
- /** @type {<T>(sequence: Sequence<T>) => Iterable<T>} */
81
- const iterable = sequence => ({
82
- *[Symbol.iterator]() {
83
- let i = sequence
84
- while (true) {
85
- const n = next(i)
86
- if (n === undefined) { return }
87
- const { first, tail } = n
88
- yield first
89
- i = tail
90
- }
91
- }
92
- })
93
-
94
- /** @type {<T>(sequence: Sequence<T>) => readonly T[]} */
95
- const toArray = sequence => {
96
- if (sequence instanceof Array) { return sequence }
97
- return Array.from(iterable(sequence))
98
- }
99
-
100
- /** @type {<I, O>(step: (result: ResultOne<I>) => Node<O>) => (input: Sequence<I>) => Thunk<O>} */
101
- const apply = f => input => () => {
102
- const n = next(input)
103
- if (n === undefined) { return undefined }
104
- return f(n)
105
- }
106
-
107
- /** @type {<T>(result: ResultOne<Sequence<T>>) => Node<T>} */
108
- const flatStep = ({first, tail}) => [first, flat(tail)]
109
-
110
- /** @type {<T>(sequence: Sequence<Sequence<T>>) => Thunk<T>} */
111
- const flat = apply(flatStep)
112
-
113
- /** @type {<I, O>(f: (value: I) => O) => (result: ResultOne<I>) => Node<O>} */
114
- const mapStep = f => ({ first, tail }) => ({ first: f(first), tail: map(f)(tail) })
115
-
116
- /** @type {<I, O>(f: (value: I) => O) => (input: Sequence<I>) => Thunk<O>} */
117
- const map = f => apply(mapStep(f))
118
-
119
- /** @type {<I, O>(f: (value: I) => Sequence<O>) => (input: Sequence<I>) => Thunk<O>} */
120
- const flatMap = f => compose(map(f))(flat)
121
-
122
- /** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
123
- const filterStep = f => ({ first, tail }) => {
124
- const fTail = filter(f)(tail)
125
- return f(first) ? { first, tail: fTail } : nodeOne(fTail)
126
- }
127
-
128
- /** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
129
- const filter = f => apply(filterStep(f))
130
-
131
- /** @type {<I, O>(f: (value: I) => O|undefined) => (result: ResultOne<I>) => Node<O>} */
132
- const filterMapStep = f => ({first, tail}) => {
133
- const fFirst = f(first)
134
- const fTail = filterMap(f)(tail)
135
- return fFirst === undefined ? nodeOne(fTail) : { first: fFirst, tail: fTail }
136
- }
137
-
138
- /** @type {<I, O>(f: (value: I) => O|undefined) => (input: Sequence<I>) => Thunk<O>} */
139
- const filterMap = f => apply(filterMapStep(f))
140
-
141
- /** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
142
- const takeWhileStep = f => ({ first, tail }) => f(first) ? { first, tail: takeWhile(f)(tail) } :undefined
143
-
144
- /** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
145
- const takeWhile = f => apply(takeWhileStep(f))
146
-
147
- /** @type {(n: number) => <T>(result: ResultOne<T>) => Node<T>} */
148
- const takeStep = n => ({ first, tail }) => 0 < n ? { first, tail: take(n - 1)(tail) } : undefined
149
-
150
- /** @type {(n: number) => <T>(result: Sequence<T>) => Sequence<T>} */
151
- const take = n => apply(takeStep(n))
152
-
153
- /** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
154
- const dropWhileStep = f => result => {
155
- const { first, tail } = result
156
- return f(first) ? nodeOne(dropWhile(f)(tail)) : result
157
- }
158
-
159
- /** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
160
- const dropWhile = f => apply(dropWhileStep(f))
161
-
162
- /** @type {(n: number) => <T>(result: ResultOne<T>) => Node<T>} */
163
- const dropFn = n => result => 0 < n ? nodeOne(drop(n - 1)(result.tail)) : result
164
-
165
- /** @type {(n: number) => <T>(result: Sequence<T>) => Sequence<T>} */
166
- const drop = n => apply(dropFn(n))
167
-
168
- /** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
169
- const first = def => input => {
170
- const result = next(input)
171
- if (result === undefined) { return def }
172
- return result.first
173
- }
174
-
175
- /** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
176
- const last = def => input => {
177
- /** @typedef {typeof input extends Sequence<infer T> ? T : never} T */
178
- /** @type {(typeof def)|T} */
179
- let r = def
180
- let i = input
181
- while (true) {
182
- const result = next(i)
183
- if (result === undefined) {
184
- return r
185
- }
186
- r = result.first
187
- i = result.tail
188
- }
189
- }
190
-
191
- /** @type {<D>(def: D) => <T>(f: (value: T) => boolean) => (sequence: Sequence<T>) => D|T} */
192
- const find = def => f => input => first(def)(filter(f)(input))
193
-
194
- /** @type {(value: boolean) => boolean} */
195
- const boolIdentity = identity
196
-
197
- /** @type {(sequence: Sequence<boolean>) => boolean} */
198
- const some = input => find(false)(boolIdentity)(input)
199
-
200
- /** @type {(sequence: Sequence<boolean>) => boolean} */
201
- const every = input => !some(map(logicalNot)(input))
202
-
203
- /** @type {<T>(value: T) => (sequence: Sequence<T>) => boolean} */
204
- const includes = value => input => some(map(strictEqual(value))(input))
205
-
206
- /** @type {(count: number) => Thunk<number>} */
207
- const countdown = count => () => {
208
- if (count <= 0) { return undefined }
209
- const first = count - 1
210
- return { first, tail: countdown(first) }
211
- }
212
-
213
- /**
214
- * @template T,A
215
- * @typedef {(value: T) => ScanState<T, A>} ScanOperator
216
- */
217
-
218
- /**
219
- * @template T,A
220
- * @typedef {readonly[A, ScanOperator<T, A>]} ScanState
221
- */
222
-
223
- /** @type {<T,A>(operator: ScanOperator<T, A>) => (result: ResultOne<T>) => Node<A>} */
224
- const scanFn = operator => ({first, tail}) => {
225
- const [value, nextOperator] = operator(first)
226
- return { first: value, tail: scan(nextOperator)(tail) }
227
- }
228
-
229
- /** @type {<T,A>(operator: ScanOperator<T, A>) => (input: Sequence<T>) => Thunk<A>} */
230
- const scan = operator => apply(scanFn(operator))
231
-
232
- /** @type {<T,A>(operator: ScanOperator<T, A>) => <D>(def: D)=> (input: Sequence<T>) => D|A} */
233
- const scanReduce = operator => def => input => last(def)(scan(operator)(input))
234
-
235
- /**
236
- * @template T,A
237
- * @typedef {(prior: A) => (value: T) => A} ReduceOperator
238
- */
239
-
240
- /** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanState<T, A>} */
241
- const scanState = operator => init => [init, scanOperator(operator)(init)]
242
-
243
- /** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanOperator<T, A>} */
244
- const scanOperator = operator => init => value => scanState(operator)(operator(init)(value))
245
-
246
- /** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => (input: Sequence<T>) => A} */
247
- const reduce = operator => init => scanReduce(scanOperator(operator)(init))(init)
248
-
249
- /**
250
- * @template T
251
- * @typedef {ReduceOperator<T, T>} FoldOperator
252
- */
253
-
254
- /** @type {<T>(operator: FoldOperator<T>) => <D>(def: D) => (input: Sequence<T>) => D|T} */
255
- const fold = operator => def => scanReduce(scanState(operator))(def)
256
-
257
- const sum = fold(addition)(0)
258
-
259
- const min = fold(op.min)(undefined)
260
-
261
- const max = fold(op.max)(undefined)
262
-
263
- /** @type {(separator: string) => (input: Sequence<string>) => string} */
264
- const join = separator => fold(op.join(separator))('')
265
-
266
- /** @type {(a: number) => () => number} */
267
- const counter = a => () => a + 1
268
-
269
- /** @type {<T>(input: Sequence<T>) => number} */
270
- const length = reduce(counter)(0)
271
-
272
- /**
273
- * @template T
274
- * @typedef {readonly[number, T]} Entry
275
- */
276
-
277
- /** @type {(index: number) => <T>(value: T) => ScanState<T, Entry<T>>} */
278
- const entryOp = index => value => [[index, value], entryOp(index + 1)]
279
-
280
- /** @type {<T>(input: Sequence<T>) => Thunk<Entry<T>>} */
281
- const entries = scan(entryOp(0))
282
-
283
- /** @type {<T>(prior: Sequence<T>) => (value: T) => Sequence<T>} */
284
- const reverseOp = prior => value => sequence(value)(prior)
285
-
286
- /** @type {<T>(input: Sequence<T>) => Sequence<T>} */
287
- const reverse = reduce(reverseOp)(empty)
288
-
289
- /** @type {<A>(a: Sequence<A>) => <B>(b: Sequence<B>) => Thunk<readonly[A, B]>} */
290
- const zip = a => b => () => {
291
- const aResult = next(a)
292
- if (aResult === undefined) { return undefined }
293
- const bResult = next(b)
294
- if (bResult === undefined) { return undefined }
295
- return { first: [aResult.first, bResult.first], tail: zip(aResult.tail)(bResult.tail) }
296
- }
297
-
298
- /** @type {<T>(e: op.EqualOperator<T>) => (a: Sequence<T>) => (b: Sequence<T>) => Thunk<boolean>} */
299
- const equalZip = e => a => b => () => {
300
- const aResult = next(a)
301
- const bResult = next(b)
302
- if (aResult === undefined || bResult === undefined) {
303
- return { first: aResult === bResult, tail: empty }
304
- }
305
- return { first: e(aResult.first)(bResult.first), tail: equalZip(e)(aResult.tail)(bResult.tail) }
306
- }
307
-
308
- /** @type {<T>(e: op.EqualOperator<T>) => (a: Sequence<T>) => (b: Sequence<T>) => boolean} */
309
- const equal = e => a => b => every(equalZip(e)(a)(b))
310
-
311
- module.exports = {
312
- /** @readonly */
313
- sequence,
314
- /** @readonly */
315
- iterable,
316
- /** @readonly */
317
- next,
318
- /** @readonly */
319
- toArray,
320
- /** @readonly */
321
- flat,
322
- /** @readonly */
323
- last,
324
- /** @readonly */
325
- concat,
326
- /** @readonly */
327
- first,
328
- /** @readonly */
329
- map,
330
- /** @readonly */
331
- flatMap,
332
- /** @readonly */
333
- filter,
334
- /** @readonly */
335
- filterMap,
336
- /** @readonly */
337
- find,
338
- /** @readonly */
339
- some,
340
- /** @readonly */
341
- every,
342
- /** @readonly */
343
- includes,
344
- /** @readonly */
345
- takeWhile,
346
- /** @readonly */
347
- take,
348
- /** @readonly */
349
- dropWhile,
350
- /** @readonly */
351
- drop,
352
- /** @readonly */
353
- scanOperator,
354
- /** @readonly */
355
- scanState,
356
- /** @readonly */
357
- scan,
358
- /** @readonly */
359
- reduce,
360
- /** @readonly */
361
- fold,
362
- /** @readonly */
363
- sum,
364
- /** @readonly */
365
- min,
366
- /** @readonly */
367
- max,
368
- /** @readonly */
369
- join,
370
- /** @readonly */
371
- entries,
372
- /** @readonly */
373
- length,
374
- /** @readonly */
375
- reverse,
376
- /** @readonly */
377
- zip,
378
- /** @readonly */
379
- equal,
380
- /** @readonly */
381
- countdown,
382
- }