@thi.ng/pointfree 3.1.70 → 3.1.71
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/CHANGELOG.md +1 -1
- package/README.md +54 -2
- package/array.d.ts +20 -10
- package/loop.d.ts +6 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -133,6 +133,8 @@ ported from [Factor](http://factorcode.org) and
|
|
|
133
133
|
(details explained further below)
|
|
134
134
|
|
|
135
135
|
```ts
|
|
136
|
+
import * as pf from "@thi.ng/pointfree";
|
|
137
|
+
|
|
136
138
|
// define word to compute dot product of two vectors
|
|
137
139
|
const dotp = pf.word([pf.vmul, [pf.add], 0, pf.foldl]);
|
|
138
140
|
// another word to normalize a vector (uses `dotp`)
|
|
@@ -271,7 +273,9 @@ on the stack as is. Therefore, a stack program like: `[1, 2, pf.add]`
|
|
|
271
273
|
compiles to:
|
|
272
274
|
|
|
273
275
|
```ts
|
|
274
|
-
pf.
|
|
276
|
+
import * as pf from "@thi.ng/pointfree";
|
|
277
|
+
|
|
278
|
+
pf.add(pf.push(2)(pf.push(1)(/* <initial context> */)))
|
|
275
279
|
```
|
|
276
280
|
|
|
277
281
|
#### About stack effects
|
|
@@ -305,6 +309,8 @@ section of the result stack. This is merely syntax sugar and we use this
|
|
|
305
309
|
for some of the examples below.
|
|
306
310
|
|
|
307
311
|
```ts
|
|
312
|
+
import * as pf from "@thi.ng/pointfree";
|
|
313
|
+
|
|
308
314
|
// calculate (1 + 2 + 3) * 10
|
|
309
315
|
pf.run(
|
|
310
316
|
// a pointfree stack program w/ stack effects
|
|
@@ -332,6 +338,8 @@ value(s) from result context.
|
|
|
332
338
|
stack programs. Their use case is purely standalone application.
|
|
333
339
|
|
|
334
340
|
```ts
|
|
341
|
+
import * as pf from "@thi.ng/pointfree";
|
|
342
|
+
|
|
335
343
|
// define new word to compute multiply-add:
|
|
336
344
|
// ( x y z -- x*y+z )
|
|
337
345
|
const madd = pf.word([pf.invrot, pf.mul, pf.add]);
|
|
@@ -356,6 +364,8 @@ smaller re-usable units, words, quotations. These often extremely small
|
|
|
356
364
|
words can be much easier tested and reused.
|
|
357
365
|
|
|
358
366
|
```ts
|
|
367
|
+
import * as pf from "@thi.ng/pointfree";
|
|
368
|
+
|
|
359
369
|
// compute square of x
|
|
360
370
|
// ( x -- x*x )
|
|
361
371
|
const pow2 = pf.word([pf.dup, pf.mul]);
|
|
@@ -391,6 +401,8 @@ execution. Quotations can be nested, composed and are executed via
|
|
|
391
401
|
This example uses a quoted form of the above `pow2` word:
|
|
392
402
|
|
|
393
403
|
```ts
|
|
404
|
+
import * as pf from "@thi.ng/pointfree";
|
|
405
|
+
|
|
394
406
|
pf.runU(
|
|
395
407
|
[
|
|
396
408
|
// push quotation on stack
|
|
@@ -414,6 +426,8 @@ all other values in the quotation are passed as arguments. The result of
|
|
|
414
426
|
the function call is placed back on the stack.
|
|
415
427
|
|
|
416
428
|
```ts
|
|
429
|
+
import * as pf from "@thi.ng/pointfree";
|
|
430
|
+
|
|
417
431
|
pf.runU(
|
|
418
432
|
[
|
|
419
433
|
[(a,b) => a + b, 1, 2],
|
|
@@ -430,6 +444,8 @@ functional composition of two quotations is the same as concatenating
|
|
|
430
444
|
two arrays**:
|
|
431
445
|
|
|
432
446
|
```js
|
|
447
|
+
import * as pf from "@thi.ng/pointfree";
|
|
448
|
+
|
|
433
449
|
const add10 = [10, pf.add];
|
|
434
450
|
const mul10 = [10, pf.mul];
|
|
435
451
|
|
|
@@ -447,6 +463,8 @@ Also see [the section about combinators](#dataflow-combinators) for more
|
|
|
447
463
|
advanced options.
|
|
448
464
|
|
|
449
465
|
```ts
|
|
466
|
+
import * as pf from "@thi.ng/pointfree";
|
|
467
|
+
|
|
450
468
|
// build & execute curried quotation
|
|
451
469
|
pf.run([10, [pf.add], pf.pushl, pf.exec], [[13]]);
|
|
452
470
|
// 23
|
|
@@ -456,6 +474,8 @@ Furthermore, the ES6 spread operator can be used to dissolve a quotation
|
|
|
456
474
|
in a larger word/program (i.e. as a form of inlining code).
|
|
457
475
|
|
|
458
476
|
```ts
|
|
477
|
+
import * as pf from "@thi.ng/pointfree";
|
|
478
|
+
|
|
459
479
|
// a quotation is just an array of values/words
|
|
460
480
|
// this function is a quotation generator
|
|
461
481
|
const tupleQ = (n) => [n, pf.collect];
|
|
@@ -498,6 +518,8 @@ restores them again after. Most other combinators are internally built
|
|
|
498
518
|
on `dip` and/or `keep`.
|
|
499
519
|
|
|
500
520
|
```ts
|
|
521
|
+
import * as pf from "@thi.ng/pointfree";
|
|
522
|
+
|
|
501
523
|
// remove `20` before executing quot, then restores after
|
|
502
524
|
// with the effect of apply qout to 2nd topmost value (here: 10)
|
|
503
525
|
pf.run([10, 20, [pf.inc], pf.dip])[0]
|
|
@@ -516,6 +538,8 @@ Calls a quotation with a value on the d-stack, restoring the value after
|
|
|
516
538
|
quotation finished.
|
|
517
539
|
|
|
518
540
|
```ts
|
|
541
|
+
import * as pf from "@thi.ng/pointfree";
|
|
542
|
+
|
|
519
543
|
// here `add` would normally consume two stack values
|
|
520
544
|
// but `keep2` restores them again after the quot has run
|
|
521
545
|
pf.run([1, 2, [pf.add], pf.keep2])[0]
|
|
@@ -531,6 +555,8 @@ pf.run([1, 2, [pf.add], pf.keep2])[0]
|
|
|
531
555
|
value, then applies second quot to the same value.
|
|
532
556
|
|
|
533
557
|
```ts
|
|
558
|
+
import * as pf from "@thi.ng/pointfree";
|
|
559
|
+
|
|
534
560
|
pf.run([2, [10, pf.add], [10, pf.mul], pf.bi])[0]
|
|
535
561
|
// [12, 20]
|
|
536
562
|
|
|
@@ -542,6 +568,8 @@ pf.run([2, 10, 100, [pf.add, pf.add], [pf.mul, pf.mul], pf.bi3])[0]
|
|
|
542
568
|
`tri` takes 3 quotations, else same as `bi`:
|
|
543
569
|
|
|
544
570
|
```ts
|
|
571
|
+
import * as pf from "@thi.ng/pointfree";
|
|
572
|
+
|
|
545
573
|
pf.run([10, [pf.dec], [pf.dup, pf.mul], [pf.inc], pf.tri])[0]
|
|
546
574
|
// [9, 100, 11]
|
|
547
575
|
```
|
|
@@ -556,6 +584,8 @@ pf.run([10, [pf.dec], [pf.dup, pf.mul], [pf.inc], pf.tri])[0]
|
|
|
556
584
|
( x y p q -- px qy )
|
|
557
585
|
|
|
558
586
|
```ts
|
|
587
|
+
import * as pf from "@thi.ng/pointfree";
|
|
588
|
+
|
|
559
589
|
pf.run([10, 20, [pf.inc], [pf.dec], pf.bis])[0]
|
|
560
590
|
// [11, 19]
|
|
561
591
|
|
|
@@ -575,6 +605,8 @@ Applies the quotation `q` to `x`, then to `y`.
|
|
|
575
605
|
( x y q -- qx qy )
|
|
576
606
|
|
|
577
607
|
```ts
|
|
608
|
+
import * as pf from "@thi.ng/pointfree";
|
|
609
|
+
|
|
578
610
|
pf.run([10, 20, [pf.inc], pf.bia])[0]
|
|
579
611
|
// [11, 21]
|
|
580
612
|
|
|
@@ -600,6 +632,8 @@ produce a result array (only flat results pushed on stack), whereas
|
|
|
600
632
|
value on the stack and applies quotation for each.
|
|
601
633
|
|
|
602
634
|
```ts
|
|
635
|
+
import * as pf from "@thi.ng/pointfree";
|
|
636
|
+
|
|
603
637
|
// multiply each array item * 10
|
|
604
638
|
pf.runU([[1, 2, 3, 4], [10, pf.mul], pf.mapll]);
|
|
605
639
|
// [ 10, 20, 30, 40 ]
|
|
@@ -643,13 +677,17 @@ object back on stack at the end. Throws error if there're less remaining
|
|
|
643
677
|
stack values than keys in given array.
|
|
644
678
|
|
|
645
679
|
```ts
|
|
646
|
-
|
|
680
|
+
import * as pf from "@thi.ng/pointfree";
|
|
681
|
+
|
|
682
|
+
pf.runU([1, 2, 3, ["a","b","c"], {}, pf.bindkeys])
|
|
647
683
|
// { c: 3, b: 2, a: 1 }
|
|
648
684
|
```
|
|
649
685
|
|
|
650
686
|
#### Combine array transform op with deeper stack values
|
|
651
687
|
|
|
652
688
|
```ts
|
|
689
|
+
import * as pf from "@thi.ng/pointfree";
|
|
690
|
+
|
|
653
691
|
// helper word to extract a 8bit range from a 32bit int
|
|
654
692
|
// `x` is the orig number, `s` bit shift amount
|
|
655
693
|
// ( x s -- x byte )
|
|
@@ -677,6 +715,8 @@ splitBytes([[0xdecafbad]]);
|
|
|
677
715
|
See `cond` documentation further below...
|
|
678
716
|
|
|
679
717
|
```ts
|
|
718
|
+
import * as pf from "@thi.ng/pointfree";
|
|
719
|
+
|
|
680
720
|
// negate TOS item ONLY if negative, else do nothing
|
|
681
721
|
const abs = pf.wordU([pf.dup, pf.isneg, pf.cond(pf.neg)]);
|
|
682
722
|
|
|
@@ -690,6 +730,8 @@ abs([42])
|
|
|
690
730
|
```
|
|
691
731
|
|
|
692
732
|
```ts
|
|
733
|
+
import * as pf from "@thi.ng/pointfree";
|
|
734
|
+
|
|
693
735
|
// `cases()` is similar to JS `switch() { case ... }`
|
|
694
736
|
const classify = (x) =>
|
|
695
737
|
pf.unwrap(
|
|
@@ -720,6 +762,8 @@ as test produces a truthy result. There's also `loopq` which reads its
|
|
|
720
762
|
arguments (same as `loop`) from the stack.
|
|
721
763
|
|
|
722
764
|
```ts
|
|
765
|
+
import * as pf from "@thi.ng/pointfree";
|
|
766
|
+
|
|
723
767
|
// print countdown from 3
|
|
724
768
|
pf.run(
|
|
725
769
|
[
|
|
@@ -743,6 +787,8 @@ counter based iterations. Like `loopq` it's not an higher-order word and
|
|
|
743
787
|
works with a body quotation, which is executed `n` times.
|
|
744
788
|
|
|
745
789
|
```ts
|
|
790
|
+
import * as pf from "@thi.ng/pointfree";
|
|
791
|
+
|
|
746
792
|
pf.run([3, ["counter: ", pf.swap, pf.add, pf.print], pf.dotimes])
|
|
747
793
|
// counter: 0
|
|
748
794
|
// counter: 1
|
|
@@ -753,6 +799,8 @@ pf.run([3, ["counter: ", pf.swap, pf.add, pf.print], pf.dotimes])
|
|
|
753
799
|
looping constructs:
|
|
754
800
|
|
|
755
801
|
```ts
|
|
802
|
+
import * as pf from "@thi.ng/pointfree";
|
|
803
|
+
|
|
756
804
|
// 2D range/grid loop
|
|
757
805
|
//
|
|
758
806
|
// (cols rows body -- ? )
|
|
@@ -807,6 +855,8 @@ several words available for moving data between main ("D-stack") and the
|
|
|
807
855
|
r-stack and to manipulate the structure of the R-stack itself.
|
|
808
856
|
|
|
809
857
|
```ts
|
|
858
|
+
import * as pf from "@thi.ng/pointfree";
|
|
859
|
+
|
|
810
860
|
// this example partitions the main stack into triples
|
|
811
861
|
|
|
812
862
|
// helper word to check if there're values on d-stack
|
|
@@ -1036,6 +1086,8 @@ body within an implicit `try .. catch` and if an error was thrown pushes
|
|
|
1036
1086
|
it on stack and executes error quotation.
|
|
1037
1087
|
|
|
1038
1088
|
```ts
|
|
1089
|
+
import * as pf from "@thi.ng/pointfree";
|
|
1090
|
+
|
|
1039
1091
|
pf.runU([
|
|
1040
1092
|
// body quotation
|
|
1041
1093
|
[pf.div],
|
package/array.d.ts
CHANGED
|
@@ -11,7 +11,9 @@ import type { StackContext, StackFn } from "./api.js";
|
|
|
11
11
|
*
|
|
12
12
|
* Compare:
|
|
13
13
|
*
|
|
14
|
-
* ```
|
|
14
|
+
* ```js
|
|
15
|
+
* import * as pf from "@thi.ng/pointfree";
|
|
16
|
+
*
|
|
15
17
|
* // using array literal within word definition
|
|
16
18
|
* foo = pf.word([ [], 1, pf.pushl ])
|
|
17
19
|
* pf.runU(foo)
|
|
@@ -108,7 +110,9 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
108
110
|
* any number of results and therefore also be used as filter, mapcat,
|
|
109
111
|
* reduce...
|
|
110
112
|
*
|
|
111
|
-
* ```
|
|
113
|
+
* ```js
|
|
114
|
+
* import { mapl, mul, run } from "@thi.ng/pointfree";
|
|
115
|
+
*
|
|
112
116
|
* // each item times 10
|
|
113
117
|
* run([[1, 2, 3, 4], [10, mul], mapl])
|
|
114
118
|
* // [ [ 10, 20, 30, 40 ], [], {} ]
|
|
@@ -116,7 +120,9 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
116
120
|
*
|
|
117
121
|
* Use for filtering:
|
|
118
122
|
*
|
|
119
|
-
* ```
|
|
123
|
+
* ```js
|
|
124
|
+
* import { cond, drop, dup, even, mapl, run } from "@thi.ng/pointfree";
|
|
125
|
+
*
|
|
120
126
|
* // drop even numbers, duplicate odd ones
|
|
121
127
|
* run([[1, 2, 3, 4], [dup, even, cond(drop, dup)], mapl])
|
|
122
128
|
* // [ [ 1, 1, 3, 3 ], [], {} ]
|
|
@@ -124,7 +130,9 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
124
130
|
*
|
|
125
131
|
* Reduction:
|
|
126
132
|
*
|
|
127
|
-
* ```
|
|
133
|
+
* ```js
|
|
134
|
+
* import { add, mapl, runU } from "@thi.ng/pointfree";
|
|
135
|
+
*
|
|
128
136
|
* // the `0` is the initial reduction result
|
|
129
137
|
* runU([0, [1, 2, 3, 4], [add], mapl])
|
|
130
138
|
* // 10
|
|
@@ -136,7 +144,7 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
136
144
|
* Use {@link mapll} to transform:
|
|
137
145
|
*
|
|
138
146
|
* @example
|
|
139
|
-
* ```
|
|
147
|
+
* ```js
|
|
140
148
|
* import { runU, mapll, mul } from "@thi.ng/pointfree";
|
|
141
149
|
*
|
|
142
150
|
* runU([[1, 2, 3, 4], [10, mul], mapll])
|
|
@@ -148,7 +156,7 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
148
156
|
* interim value into the result:
|
|
149
157
|
*
|
|
150
158
|
* @example
|
|
151
|
-
* ```
|
|
159
|
+
* ```js
|
|
152
160
|
* import { list, mapl, mul, pushr, runU } from "@thi.ng/pointfree";
|
|
153
161
|
*
|
|
154
162
|
* runU([list, [1, 2, 3, 4], [10, mul, pushr], mapl])
|
|
@@ -158,7 +166,7 @@ export declare const catr: (ctx: StackContext) => StackContext;
|
|
|
158
166
|
* If the array size is known & not changed by transformation:
|
|
159
167
|
*
|
|
160
168
|
* @example
|
|
161
|
-
* ```
|
|
169
|
+
* ```js
|
|
162
170
|
* import { collect, mapl, mul, runU } from "@thi.ng/pointfree";
|
|
163
171
|
*
|
|
164
172
|
* runU([[1, 2, 3, 4], [10, mul], mapl, 4, collect])
|
|
@@ -174,7 +182,7 @@ export declare const mapl: (ctx: StackContext) => StackContext;
|
|
|
174
182
|
* ( arr q -- arr )
|
|
175
183
|
*
|
|
176
184
|
* @example
|
|
177
|
-
* ```
|
|
185
|
+
* ```js
|
|
178
186
|
* import { mapll, mul, runU } from "@thi.ng/pointfree";
|
|
179
187
|
*
|
|
180
188
|
* runU([[1, 2, 3, 4], [10, mul], mapll])
|
|
@@ -183,7 +191,9 @@ export declare const mapl: (ctx: StackContext) => StackContext;
|
|
|
183
191
|
*
|
|
184
192
|
* Filter / mapcat:
|
|
185
193
|
*
|
|
186
|
-
* ```
|
|
194
|
+
* ```js
|
|
195
|
+
* import { cond, drop, dup, even, mapll, run } from "@thi.ng/pointfree";
|
|
196
|
+
*
|
|
187
197
|
* // drop even numbers, duplicate odd ones
|
|
188
198
|
* run([[1, 2, 3, 4], [dup, even, cond(drop, dup)], mapll])
|
|
189
199
|
* // [ [ [ 1, 1, 3, 3 ] ], [], {} ]
|
|
@@ -267,7 +277,7 @@ export declare const setat: (ctx: StackContext) => StackContext;
|
|
|
267
277
|
* keys in given array.
|
|
268
278
|
*
|
|
269
279
|
* @example
|
|
270
|
-
* ```
|
|
280
|
+
* ```js
|
|
271
281
|
* import { bindkeys, runU } from "@thi.ng/pointfree";
|
|
272
282
|
*
|
|
273
283
|
* runU([1,2,3, ["a","b","c"], {}, bindkeys])
|
package/loop.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import type { StackContext, StackProc } from "./api.js";
|
|
|
6
6
|
* ( -- ? )
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
|
-
* ```
|
|
10
|
-
* import { dec, dup, ispos, print,
|
|
9
|
+
* ```js
|
|
10
|
+
* import { dec, dup, ispos, print, run } from "@thi.ng/pointfree";
|
|
11
11
|
*
|
|
12
12
|
* run([loop([dup, ispos], [dup, print, dec])], [[3]])
|
|
13
13
|
* // 3
|
|
@@ -15,6 +15,7 @@ import type { StackContext, StackProc } from "./api.js";
|
|
|
15
15
|
* // 1
|
|
16
16
|
* // [ true, [ 0 ], undefined ]
|
|
17
17
|
* ```
|
|
18
|
+
*
|
|
18
19
|
* @param test -
|
|
19
20
|
* @param body -
|
|
20
21
|
*/
|
|
@@ -33,7 +34,7 @@ export declare const loopq: (ctx: StackContext) => StackContext;
|
|
|
33
34
|
* pushes current counter on d-stack prior to executing body.
|
|
34
35
|
*
|
|
35
36
|
* @example
|
|
36
|
-
* ```
|
|
37
|
+
* ```js
|
|
37
38
|
* import { add, print, swap, runU } from "@thi.ng/pointfree";
|
|
38
39
|
*
|
|
39
40
|
* run([3, ["i=", swap, add, print], dotimes])
|
|
@@ -44,8 +45,8 @@ export declare const loopq: (ctx: StackContext) => StackContext;
|
|
|
44
45
|
*
|
|
45
46
|
* With empty body acts as finite range generator 0 .. n:
|
|
46
47
|
*
|
|
47
|
-
* ```
|
|
48
|
-
* import { collect, cpdr, dotimes, movrd, runU } from "@thi.ng/pointfree";
|
|
48
|
+
* ```js
|
|
49
|
+
* import { collect, cpdr, dotimes, movrd, run, runU } from "@thi.ng/pointfree";
|
|
49
50
|
*
|
|
50
51
|
* // range gen
|
|
51
52
|
* run([3, [], dotimes])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/pointfree",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.71",
|
|
4
4
|
"description": "Pointfree functional composition / Forth style stack execution engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -132,5 +132,5 @@
|
|
|
132
132
|
"thi.ng": {
|
|
133
133
|
"year": 2015
|
|
134
134
|
},
|
|
135
|
-
"gitHead": "
|
|
135
|
+
"gitHead": "df9e312af741d87e6b450afcfea6a6e381662b1e\n"
|
|
136
136
|
}
|