@thi.ng/pointfree 3.1.69 → 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 +55 -14
- package/array.d.ts +20 -10
- package/loop.d.ts +6 -5
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
<!-- This file is generated - DO NOT EDIT! -->
|
|
2
2
|
<!-- Please see: https://github.com/thi-ng/umbrella/blob/develop/CONTRIBUTING.md#changes-to-readme-files -->
|
|
3
|
-
> [!IMPORTANT]
|
|
4
|
-
> ‼️ Announcing the thi.ng user survey 2024 📋
|
|
5
|
-
>
|
|
6
|
-
> [Please participate in the survey here!](https://forms.gle/XacbSDEmQMPZg8197)\
|
|
7
|
-
> (open until end of February)
|
|
8
|
-
>
|
|
9
|
-
> **To achieve a better sample size, I'd highly appreciate if you could
|
|
10
|
-
> circulate the link to this survey in your own networks.**
|
|
11
|
-
>
|
|
12
|
-
> [Discussion](https://github.com/thi-ng/umbrella/discussions/447)
|
|
13
|
-
|
|
14
3
|
# 
|
|
15
4
|
|
|
16
5
|
[](https://www.npmjs.com/package/@thi.ng/pointfree)
|
|
@@ -22,7 +11,7 @@
|
|
|
22
11
|
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
|
|
23
12
|
> and anti-framework.
|
|
24
13
|
>
|
|
25
|
-
> 🚀
|
|
14
|
+
> 🚀 Please help me to work full-time on these projects by [sponsoring me on
|
|
26
15
|
> GitHub](https://github.com/sponsors/postspectacular). Thank you! ❤️
|
|
27
16
|
|
|
28
17
|
- [About](#about)
|
|
@@ -144,6 +133,8 @@ ported from [Factor](http://factorcode.org) and
|
|
|
144
133
|
(details explained further below)
|
|
145
134
|
|
|
146
135
|
```ts
|
|
136
|
+
import * as pf from "@thi.ng/pointfree";
|
|
137
|
+
|
|
147
138
|
// define word to compute dot product of two vectors
|
|
148
139
|
const dotp = pf.word([pf.vmul, [pf.add], 0, pf.foldl]);
|
|
149
140
|
// another word to normalize a vector (uses `dotp`)
|
|
@@ -282,7 +273,9 @@ on the stack as is. Therefore, a stack program like: `[1, 2, pf.add]`
|
|
|
282
273
|
compiles to:
|
|
283
274
|
|
|
284
275
|
```ts
|
|
285
|
-
pf.
|
|
276
|
+
import * as pf from "@thi.ng/pointfree";
|
|
277
|
+
|
|
278
|
+
pf.add(pf.push(2)(pf.push(1)(/* <initial context> */)))
|
|
286
279
|
```
|
|
287
280
|
|
|
288
281
|
#### About stack effects
|
|
@@ -316,6 +309,8 @@ section of the result stack. This is merely syntax sugar and we use this
|
|
|
316
309
|
for some of the examples below.
|
|
317
310
|
|
|
318
311
|
```ts
|
|
312
|
+
import * as pf from "@thi.ng/pointfree";
|
|
313
|
+
|
|
319
314
|
// calculate (1 + 2 + 3) * 10
|
|
320
315
|
pf.run(
|
|
321
316
|
// a pointfree stack program w/ stack effects
|
|
@@ -343,6 +338,8 @@ value(s) from result context.
|
|
|
343
338
|
stack programs. Their use case is purely standalone application.
|
|
344
339
|
|
|
345
340
|
```ts
|
|
341
|
+
import * as pf from "@thi.ng/pointfree";
|
|
342
|
+
|
|
346
343
|
// define new word to compute multiply-add:
|
|
347
344
|
// ( x y z -- x*y+z )
|
|
348
345
|
const madd = pf.word([pf.invrot, pf.mul, pf.add]);
|
|
@@ -367,6 +364,8 @@ smaller re-usable units, words, quotations. These often extremely small
|
|
|
367
364
|
words can be much easier tested and reused.
|
|
368
365
|
|
|
369
366
|
```ts
|
|
367
|
+
import * as pf from "@thi.ng/pointfree";
|
|
368
|
+
|
|
370
369
|
// compute square of x
|
|
371
370
|
// ( x -- x*x )
|
|
372
371
|
const pow2 = pf.word([pf.dup, pf.mul]);
|
|
@@ -402,6 +401,8 @@ execution. Quotations can be nested, composed and are executed via
|
|
|
402
401
|
This example uses a quoted form of the above `pow2` word:
|
|
403
402
|
|
|
404
403
|
```ts
|
|
404
|
+
import * as pf from "@thi.ng/pointfree";
|
|
405
|
+
|
|
405
406
|
pf.runU(
|
|
406
407
|
[
|
|
407
408
|
// push quotation on stack
|
|
@@ -425,6 +426,8 @@ all other values in the quotation are passed as arguments. The result of
|
|
|
425
426
|
the function call is placed back on the stack.
|
|
426
427
|
|
|
427
428
|
```ts
|
|
429
|
+
import * as pf from "@thi.ng/pointfree";
|
|
430
|
+
|
|
428
431
|
pf.runU(
|
|
429
432
|
[
|
|
430
433
|
[(a,b) => a + b, 1, 2],
|
|
@@ -441,6 +444,8 @@ functional composition of two quotations is the same as concatenating
|
|
|
441
444
|
two arrays**:
|
|
442
445
|
|
|
443
446
|
```js
|
|
447
|
+
import * as pf from "@thi.ng/pointfree";
|
|
448
|
+
|
|
444
449
|
const add10 = [10, pf.add];
|
|
445
450
|
const mul10 = [10, pf.mul];
|
|
446
451
|
|
|
@@ -458,6 +463,8 @@ Also see [the section about combinators](#dataflow-combinators) for more
|
|
|
458
463
|
advanced options.
|
|
459
464
|
|
|
460
465
|
```ts
|
|
466
|
+
import * as pf from "@thi.ng/pointfree";
|
|
467
|
+
|
|
461
468
|
// build & execute curried quotation
|
|
462
469
|
pf.run([10, [pf.add], pf.pushl, pf.exec], [[13]]);
|
|
463
470
|
// 23
|
|
@@ -467,6 +474,8 @@ Furthermore, the ES6 spread operator can be used to dissolve a quotation
|
|
|
467
474
|
in a larger word/program (i.e. as a form of inlining code).
|
|
468
475
|
|
|
469
476
|
```ts
|
|
477
|
+
import * as pf from "@thi.ng/pointfree";
|
|
478
|
+
|
|
470
479
|
// a quotation is just an array of values/words
|
|
471
480
|
// this function is a quotation generator
|
|
472
481
|
const tupleQ = (n) => [n, pf.collect];
|
|
@@ -509,6 +518,8 @@ restores them again after. Most other combinators are internally built
|
|
|
509
518
|
on `dip` and/or `keep`.
|
|
510
519
|
|
|
511
520
|
```ts
|
|
521
|
+
import * as pf from "@thi.ng/pointfree";
|
|
522
|
+
|
|
512
523
|
// remove `20` before executing quot, then restores after
|
|
513
524
|
// with the effect of apply qout to 2nd topmost value (here: 10)
|
|
514
525
|
pf.run([10, 20, [pf.inc], pf.dip])[0]
|
|
@@ -527,6 +538,8 @@ Calls a quotation with a value on the d-stack, restoring the value after
|
|
|
527
538
|
quotation finished.
|
|
528
539
|
|
|
529
540
|
```ts
|
|
541
|
+
import * as pf from "@thi.ng/pointfree";
|
|
542
|
+
|
|
530
543
|
// here `add` would normally consume two stack values
|
|
531
544
|
// but `keep2` restores them again after the quot has run
|
|
532
545
|
pf.run([1, 2, [pf.add], pf.keep2])[0]
|
|
@@ -542,6 +555,8 @@ pf.run([1, 2, [pf.add], pf.keep2])[0]
|
|
|
542
555
|
value, then applies second quot to the same value.
|
|
543
556
|
|
|
544
557
|
```ts
|
|
558
|
+
import * as pf from "@thi.ng/pointfree";
|
|
559
|
+
|
|
545
560
|
pf.run([2, [10, pf.add], [10, pf.mul], pf.bi])[0]
|
|
546
561
|
// [12, 20]
|
|
547
562
|
|
|
@@ -553,6 +568,8 @@ pf.run([2, 10, 100, [pf.add, pf.add], [pf.mul, pf.mul], pf.bi3])[0]
|
|
|
553
568
|
`tri` takes 3 quotations, else same as `bi`:
|
|
554
569
|
|
|
555
570
|
```ts
|
|
571
|
+
import * as pf from "@thi.ng/pointfree";
|
|
572
|
+
|
|
556
573
|
pf.run([10, [pf.dec], [pf.dup, pf.mul], [pf.inc], pf.tri])[0]
|
|
557
574
|
// [9, 100, 11]
|
|
558
575
|
```
|
|
@@ -567,6 +584,8 @@ pf.run([10, [pf.dec], [pf.dup, pf.mul], [pf.inc], pf.tri])[0]
|
|
|
567
584
|
( x y p q -- px qy )
|
|
568
585
|
|
|
569
586
|
```ts
|
|
587
|
+
import * as pf from "@thi.ng/pointfree";
|
|
588
|
+
|
|
570
589
|
pf.run([10, 20, [pf.inc], [pf.dec], pf.bis])[0]
|
|
571
590
|
// [11, 19]
|
|
572
591
|
|
|
@@ -586,6 +605,8 @@ Applies the quotation `q` to `x`, then to `y`.
|
|
|
586
605
|
( x y q -- qx qy )
|
|
587
606
|
|
|
588
607
|
```ts
|
|
608
|
+
import * as pf from "@thi.ng/pointfree";
|
|
609
|
+
|
|
589
610
|
pf.run([10, 20, [pf.inc], pf.bia])[0]
|
|
590
611
|
// [11, 21]
|
|
591
612
|
|
|
@@ -611,6 +632,8 @@ produce a result array (only flat results pushed on stack), whereas
|
|
|
611
632
|
value on the stack and applies quotation for each.
|
|
612
633
|
|
|
613
634
|
```ts
|
|
635
|
+
import * as pf from "@thi.ng/pointfree";
|
|
636
|
+
|
|
614
637
|
// multiply each array item * 10
|
|
615
638
|
pf.runU([[1, 2, 3, 4], [10, pf.mul], pf.mapll]);
|
|
616
639
|
// [ 10, 20, 30, 40 ]
|
|
@@ -654,13 +677,17 @@ object back on stack at the end. Throws error if there're less remaining
|
|
|
654
677
|
stack values than keys in given array.
|
|
655
678
|
|
|
656
679
|
```ts
|
|
657
|
-
|
|
680
|
+
import * as pf from "@thi.ng/pointfree";
|
|
681
|
+
|
|
682
|
+
pf.runU([1, 2, 3, ["a","b","c"], {}, pf.bindkeys])
|
|
658
683
|
// { c: 3, b: 2, a: 1 }
|
|
659
684
|
```
|
|
660
685
|
|
|
661
686
|
#### Combine array transform op with deeper stack values
|
|
662
687
|
|
|
663
688
|
```ts
|
|
689
|
+
import * as pf from "@thi.ng/pointfree";
|
|
690
|
+
|
|
664
691
|
// helper word to extract a 8bit range from a 32bit int
|
|
665
692
|
// `x` is the orig number, `s` bit shift amount
|
|
666
693
|
// ( x s -- x byte )
|
|
@@ -688,6 +715,8 @@ splitBytes([[0xdecafbad]]);
|
|
|
688
715
|
See `cond` documentation further below...
|
|
689
716
|
|
|
690
717
|
```ts
|
|
718
|
+
import * as pf from "@thi.ng/pointfree";
|
|
719
|
+
|
|
691
720
|
// negate TOS item ONLY if negative, else do nothing
|
|
692
721
|
const abs = pf.wordU([pf.dup, pf.isneg, pf.cond(pf.neg)]);
|
|
693
722
|
|
|
@@ -701,6 +730,8 @@ abs([42])
|
|
|
701
730
|
```
|
|
702
731
|
|
|
703
732
|
```ts
|
|
733
|
+
import * as pf from "@thi.ng/pointfree";
|
|
734
|
+
|
|
704
735
|
// `cases()` is similar to JS `switch() { case ... }`
|
|
705
736
|
const classify = (x) =>
|
|
706
737
|
pf.unwrap(
|
|
@@ -731,6 +762,8 @@ as test produces a truthy result. There's also `loopq` which reads its
|
|
|
731
762
|
arguments (same as `loop`) from the stack.
|
|
732
763
|
|
|
733
764
|
```ts
|
|
765
|
+
import * as pf from "@thi.ng/pointfree";
|
|
766
|
+
|
|
734
767
|
// print countdown from 3
|
|
735
768
|
pf.run(
|
|
736
769
|
[
|
|
@@ -754,6 +787,8 @@ counter based iterations. Like `loopq` it's not an higher-order word and
|
|
|
754
787
|
works with a body quotation, which is executed `n` times.
|
|
755
788
|
|
|
756
789
|
```ts
|
|
790
|
+
import * as pf from "@thi.ng/pointfree";
|
|
791
|
+
|
|
757
792
|
pf.run([3, ["counter: ", pf.swap, pf.add, pf.print], pf.dotimes])
|
|
758
793
|
// counter: 0
|
|
759
794
|
// counter: 1
|
|
@@ -764,6 +799,8 @@ pf.run([3, ["counter: ", pf.swap, pf.add, pf.print], pf.dotimes])
|
|
|
764
799
|
looping constructs:
|
|
765
800
|
|
|
766
801
|
```ts
|
|
802
|
+
import * as pf from "@thi.ng/pointfree";
|
|
803
|
+
|
|
767
804
|
// 2D range/grid loop
|
|
768
805
|
//
|
|
769
806
|
// (cols rows body -- ? )
|
|
@@ -818,6 +855,8 @@ several words available for moving data between main ("D-stack") and the
|
|
|
818
855
|
r-stack and to manipulate the structure of the R-stack itself.
|
|
819
856
|
|
|
820
857
|
```ts
|
|
858
|
+
import * as pf from "@thi.ng/pointfree";
|
|
859
|
+
|
|
821
860
|
// this example partitions the main stack into triples
|
|
822
861
|
|
|
823
862
|
// helper word to check if there're values on d-stack
|
|
@@ -1047,6 +1086,8 @@ body within an implicit `try .. catch` and if an error was thrown pushes
|
|
|
1047
1086
|
it on stack and executes error quotation.
|
|
1048
1087
|
|
|
1049
1088
|
```ts
|
|
1089
|
+
import * as pf from "@thi.ng/pointfree";
|
|
1090
|
+
|
|
1050
1091
|
pf.runU([
|
|
1051
1092
|
// body quotation
|
|
1052
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",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"test": "bun test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@thi.ng/api": "^8.9.
|
|
39
|
-
"@thi.ng/checks": "^3.5.
|
|
40
|
-
"@thi.ng/compose": "^2.1.
|
|
41
|
-
"@thi.ng/equiv": "^2.1.
|
|
42
|
-
"@thi.ng/errors": "^2.4.
|
|
38
|
+
"@thi.ng/api": "^8.9.27",
|
|
39
|
+
"@thi.ng/checks": "^3.5.1",
|
|
40
|
+
"@thi.ng/compose": "^2.1.66",
|
|
41
|
+
"@thi.ng/equiv": "^2.1.50",
|
|
42
|
+
"@thi.ng/errors": "^2.4.19"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@microsoft/api-extractor": "^7.40.1",
|
|
@@ -132,5 +132,5 @@
|
|
|
132
132
|
"thi.ng": {
|
|
133
133
|
"year": 2015
|
|
134
134
|
},
|
|
135
|
-
"gitHead": "
|
|
135
|
+
"gitHead": "df9e312af741d87e6b450afcfea6a6e381662b1e\n"
|
|
136
136
|
}
|