@fraczak/k 2.0.0 → 2.0.1

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 CHANGED
@@ -10,31 +10,177 @@ From javascript:
10
10
  console.log([{name:"x"},{nom:"y"},{}].map(fn));
11
11
  // returns: [ "x", "y", "?" ]
12
12
 
13
- Another JSON transformation notation. A `k`-expression (script)
14
- defines a __partial function__, i.e., a function which may fail
15
- for some input. `k`-expressions can be combined to build
16
- other `k`-expressions in three ways:
13
+ ---
17
14
 
18
- 1. composition, e.g.:
15
+ ## k - the way of building and manipulating JSON-like data
19
16
 
20
- (E1 E2 E3 ...)
17
+ Technically, `k` is a notation for defining **first-order partial functions**.
21
18
 
22
- Apart from empty composition, `()`, which defines _identity_, the
23
- paranthesis can be omitted.
19
+ An example of a _partial function_ is the _projection_, e.g., "`.toto`",
20
+ which maps an object to its property named `toto`, or it is not defined if
21
+ the property doesn't exist. E.g.,
24
22
 
25
- 2. product, e.g., vector or structure:
23
+ 1 .toto :
24
+ 2 {"toto": 5, "titi": 10} --> 5
25
+ 3 {"titi": 10} ... undefined // it is not a value!
26
26
 
27
- [ E1, E2, E3, ... ]
28
- { E1 "e1", E2 "e2", E3 "e3", ... }
27
+ > Note: The above 3 lines should be read as follows. A `k`-expression
28
+ > is printed in the first line (before "`:`"). The following lines
29
+ > are examples of the function defined by the `k`-expression applayed
30
+ > to JSON values (first part of each line). If the function for the
31
+ > value is defined, then the result is printed after "`-->`" (line 2 in
32
+ > the above example). If the function is not defined for the value,
33
+ > then "`... undefined`" is printed (line 3).
29
34
 
30
- 3. union (merge), e.g.:
35
+ ---
31
36
 
32
- < E1, E2, E3, ... >
37
+ ### Combining "partial functions"
33
38
 
34
- Elementary partial functions are:
39
+ There are three ways of combining functions:
35
40
 
36
- 4. _projection_, i.e., extracting the value of a given field or
37
- index. Examples:
41
+ 1. **composition**: `(f1 f2 ...)`, e.g. `(.toto .titi)` extracts
42
+ nested field.
43
+
44
+ (.toto .titi) :
45
+ {"toto": {"titi": 10}} --> 10
46
+ {"toto": 10 } ... undefined
47
+ {} ... undefined
48
+
49
+ 2. **merge**: `< f1, f2,... >`, e.g., `<.toto, .titi>` extracts field
50
+ `toto` if present; otherwise extracts `titi`.
51
+
52
+ <.toto, .titi> :
53
+ {"toto": 5, "titi": 10} --> 5
54
+ {"titi": 10 } --> 10
55
+ {} ... undefined
56
+
57
+ 3. **product**: `{ f1 label1, f2 label2, ...}`, e.g., `{.toto TOTO,
58
+ .titi TITI}` extracts two fields and builds a record out of them.
59
+
60
+ {.toto TOTO, .titi TITI} :
61
+ {"toto": 5, "titi": 10, "x": 3} --> {"TOTO": 5, "TITI": 10}
62
+ {"titi": 10 } ... undefined
63
+
64
+ ---
65
+
66
+ **QUIZ**: What is:
67
+
68
+ - empty composition: `()` ?
69
+ - empty merge: `<>` ?
70
+ - empty product: `{}` ?
71
+ - `{{{{} s} s} s}` ?
72
+ - `({{{() a} b} c} .c .b .a)` ?
73
+
74
+ ---
75
+
76
+ ### Syntactic sugar
77
+
78
+ - parenthesis can be omitted, except for the empty composition `()`,
79
+ - dot (`.`) in "projection" acts as a separator so the space around it can be omitted.
80
+
81
+ For example, `[(.toto .titi (.0 .1))]` can be written as `[.toto.titi.0.1]`.
82
+
83
+ Comments can be introduced by `//`, `--`, `%`, or `#` and extends to
84
+ the end of line. Multiline `C`-like comments, `/* ... */`, are also
85
+ supported.
86
+
87
+ ### Basic extensions
88
+
89
+ #### Constants, i.e., literals for `strings`, `integers`, `booleans`, and `null`
90
+
91
+ A constant defines a function which ignores its argument and produces
92
+ the constant value. E.g.:
93
+
94
+ {123 int, "kScript" str, true bool, null null} :
95
+ "any" --> {"int":123,"str":"kScript","bool":true,"null":null}
96
+
97
+ #### Vector product
98
+
99
+ Vector product can be seen as an abbreviation for product whose field
100
+ names are integers starting from zero. E.g., `{.toto 0, .titi 1, 123 2}`
101
+ can be written as `[.toto, .titi, 123]`.
102
+
103
+ [.toto, .titi, 12] :
104
+ {"toto": 5, "titi": 10 } --> [5, 10, 12]
105
+
106
+ .1 :
107
+ ["A","B","C"] --> "B"
108
+ ["a"] ... undefined
109
+
110
+ ---
111
+
112
+ ### Pragmatic extensions, aka "standard library"
113
+
114
+ - `GT` : -- identity for lists of decreasing elements; undefined otherwise
115
+
116
+ [4,3] --> [4,3]
117
+ [3,4] ... undefined
118
+ [] --> []
119
+ [4,3,0] --> [4,3,0]
120
+
121
+ - `EQ` : -- identity for lists of equal elements; undefined otherwise
122
+
123
+ [4,4] --> [4,4]
124
+ [4,5] ... undefined
125
+ [4,4,4] --> [4,4,4]
126
+ [] --> []
127
+
128
+ - `{PLUS plus, TIMES times}` :
129
+
130
+ [1,2] --> {"plus":3,"times":2}
131
+ [2,2,2] --> {"plus":6,"times":8}
132
+ [] --> {"plus":0,"times":1}
133
+
134
+ - `CONCAT` :
135
+
136
+ ["a","bc","d"] --> "abcd"
137
+
138
+ - `toJSON` :
139
+
140
+ {"a": 12} --> "{\"a\":12}"
141
+
142
+ - `fromJSON` :
143
+
144
+ "{\"a\":12}" --> {"a":12}
145
+
146
+ - other predefined parial functions are: `DIV`, `FDIV`, `CONS`, `SNOC`, `toDateMsec`,
147
+ `toDateStr`, and `_log!`.
148
+
149
+ ---
150
+
151
+ ### Function definitions
152
+
153
+ dec = [(),-1] PLUS;
154
+ max = <SNOC [.0, .1 max] <GT.0, .1>, .0> ;
155
+ factorial = < [(),0] GT .0 [dec factorial, ()] TIMES, 1 >;
156
+
157
+ ### Codes (_types_)
158
+
159
+ _Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
160
+
161
+ $nat = <nat 1, {} 0>;
162
+ $pair = {nat x, nat y};
163
+
164
+ suc = {$nat 1};
165
+ add = $pair <{.x.1 x, .y suc y} add, .y>;
166
+
167
+ #### Basic extension codes
168
+
169
+ Since _basic extension_ introduces integers, booleans, and strings, there are three
170
+ predefined types: `int`, `bool`, and `string`. A vector product code can also be defined
171
+ by `[ codeExp ]`. All members of the vector are the same code. E.g.,
172
+
173
+ $intVector = [ int ];
174
+ $boolVector = [ bool ];
175
+ $tree = [ tree ];
176
+
177
+ emptyList? = $intVector $[ string ]; -- as only an empty vector can be a vector
178
+ -- of integers and a vector of strings
179
+ ---
180
+
181
+ ## Examples
182
+
183
+ 1. projection:
38
184
 
39
185
  .x
40
186
  ."field name"
@@ -43,7 +189,7 @@ other `k`-expressions in three ways:
43
189
  The function is defined only if its argument is a structure with
44
190
  the field (or a vector with the index).
45
191
 
46
- 5. _constants_, literals for Strings, Booleans, and
192
+ 2. _constants_, literals for Strings, Booleans, and
47
193
  Integers. Examples:
48
194
 
49
195
  "a string"
@@ -52,14 +198,12 @@ the field (or a vector with the index).
52
198
  false
53
199
  null
54
200
 
55
- 6. The other "built-in" functions: `GT`, `EQ`, `PLUS`,
56
- `TIMES`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`,
57
- `SNOC`, `toDateMsec`, `toDateStr`, and `_log!`. For example:
201
+ 3. "built-in" functions:
58
202
 
59
- [1, 2, 3] PLUS --> integer constant function 6
60
- [4, 4] TIMES toJSON --> string constant function "16"
61
- [3, 2] GT --> vector constant function [3, 2]
62
- [3, 4] GT ... is not defined!
203
+ [1, 2, 3] PLUS -- integer constant function 6
204
+ [4, 4] TIMES toJSON -- string constant function "16"
205
+ [3, 2] GT -- vector constant function [3, 2]
206
+ [3, 4] GT -- ... undefined
63
207
 
64
208
  A more interesting example could be:
65
209
 
@@ -69,7 +213,7 @@ the field (or a vector with the index).
69
213
 
70
214
  [3,8] < GT .0, .1 > --> 8
71
215
 
72
- ## User defined functions
216
+ ### User defined functions
73
217
 
74
218
  `k`-expression can be prefixed by function definitions. E.g.:
75
219
 
@@ -84,22 +228,22 @@ the field (or a vector with the index).
84
228
  Another example could be finding the biggest (max) value in a vector:
85
229
 
86
230
  max = <
87
- SNOC -- [x0, x1, x2, ...] -> [x0, [x1, x2, ...]]
88
- [.0, .1 max] -- [x0, [x1, x2, ...]] -> [x0, max(x1,x2,...)], i.e., recursive call
89
- <GT .0, .1>, -- if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
90
- -- when SNOC is not defined, e.g. the argument is a singleton vector [x0]
91
- .0 -- [x0] -> x0,
231
+ SNOC # [x0, x1, x2, ...] --> [x0, [x1, x2, ...]]
232
+ [.0, .1 max] # [x0, [x1, x2, ...]] --> [x0, max(x1,x2,...)], i.e., recursive call
233
+ <GT .0, .1> # if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
234
+ , # when SNOC is not defined, i.e., if the input vector has one element:
235
+ .0 # [x0] --> x0
92
236
  >;
93
237
  max
94
238
 
95
- ## Value encodings (_codes_)
239
+ ### Value encodings (_codes_)
96
240
 
97
241
  There are three predefined value encodings: `int`, `string`, and
98
242
  `bool`. The language supports `code`-expressions:
99
243
 
100
- * product, e.g., `{int x, int y, bool flag}`
101
- * disjoint union, e.g., `<{} true, {} false>`
102
- * vector, e.g., `[ int ]` (all elements of the vector use the same
244
+ - product, e.g., `{int x, int y, bool flag}`
245
+ - disjoint union, e.g., `<{} true, {} false>`
246
+ - vector, e.g., `[ int ]` (all elements of the vector use the same
103
247
  encoding)
104
248
 
105
249
  One can define recursive codes. E.g.:
@@ -121,7 +265,9 @@ within `k`-expression is again prefixed by `$`.
121
265
  > $ int;
122
266
  height
123
267
 
124
- ## Command line script
268
+ ---
269
+
270
+ ## `k` (a command-line JSON processor using `k` syntax)
125
271
 
126
272
  There is a wrapper, `./node_modules/.bin/k` , which makes it easy to
127
273
  run the language from command line.
@@ -131,7 +277,7 @@ run the language from command line.
131
277
  Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ -1 ] [ json-file ]
132
278
  E.g., cat '{"a": 10}' | ./node_modules/.bin/k '[(),()]'
133
279
 
134
- ### Examples
280
+ For example:
135
281
 
136
282
  1. One `k`-expression with one `json`-object:
137
283
 
@@ -149,6 +295,8 @@ run the language from command line.
149
295
  {"z": 123} --> {"x&y":"no x nor y"}
150
296
  ^D - to interrupt
151
297
 
298
+ If the input is a multiline json object, we need to add `-1` to the command-line options.
299
+
152
300
  3. If the `k`-expression is long, it can be put in a file, e.g.:
153
301
 
154
302
  > cat test.k
@@ -187,7 +335,36 @@ run the language from command line.
187
335
  {"z": 123}
188
336
  ####################################################
189
337
 
190
- ### k-REPL (Read-Evaluate-Print Loop)
338
+ ---
339
+
340
+ ### Short comparaison with `jq` tutorial examples: <https://stedolan.github.io/jq/tutorial/>
341
+
342
+ 1.
343
+ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'
344
+ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | k '()' -1
345
+ 2.
346
+ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'
347
+ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | k '.0' -1
348
+ 3.
349
+ jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
350
+ k '.0 {.commit.message message, .commit.committer.name name}' -1
351
+ 4. note: `k`-expression defines a partial function yielding a single json object, i.e., as far as `k` is concerned,
352
+ examples 4 and 5 of the `jq` tutorial are equivalent.
353
+ 5.
354
+ jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
355
+ k 'f = .commit {.message message, .committer.name name}; %\
356
+ map_f = <SNOC [.0 f,.1 map_f] CONS, [.0 f], []>; %\
357
+ map_f' -1
358
+ 6.
359
+ jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'
360
+ k 'map_html_url = <SNOC [.0 .html_url, .1 map_html_url] CONS, [.0 .html_url], []>; %\
361
+ f = {.commit.message message, .commit.committer.name name, .parents map_html_url parents}; %\
362
+ map_f = <SNOC [.0 f, .1 map_f] CONS, [.0 f] , []>; %\
363
+ map_f' -1
364
+
365
+ ---
366
+
367
+ ## k-REPL (Read-Evaluate-Print Loop)
191
368
 
192
369
  Also there is a REPL, `./node_modules/.bin/k-repl`, which acts like a toy
193
370
  shell for the language. E.g.:
@@ -202,11 +379,13 @@ shell for the language. E.g.:
202
379
  inc inc inc inc
203
380
  => 7
204
381
 
205
- ## Using from `javascript`
382
+ ---
383
+
384
+ ## Using `k` from `javascript`
206
385
 
207
- var k = require("k");
386
+ import k from "@fraczak/k";
208
387
 
209
- k_expression = '()';
388
+ let k_expression = '()';
210
389
  k.run(k_expression,"ANYTHING...");
211
390
  // RETURNS: "ANYTHING..."
212
391
 
@@ -249,7 +428,7 @@ shell for the language. E.g.:
249
428
  k_fn({"age":2,"name":"Mark"});
250
429
  // RETURNS: {"nom":"Mark","age":"enfant"}
251
430
 
252
- var k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
431
+ k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
253
432
 
254
433
  k_fn(1);
255
434
  // RETURNS: 1
@@ -263,7 +442,7 @@ shell for the language. E.g.:
263
442
  k_fn({"t":[{"i":2},{"i":3},{"t":[]}]});
264
443
  // RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
265
444
 
266
- var k_fn = k.compile('$ < < [ int ] ints, [ bool ] bools > list, string None>');
445
+ k_fn = k.compile('$ < < [ int ] ints, [ bool ] bools > list, string None>');
267
446
 
268
447
  k_fn({"None":"None"});
269
448
  // RETURNS: {"None":"None"}
package/codes.mjs CHANGED
@@ -78,7 +78,6 @@ function normalizeAll(codes, representatives) {
78
78
  return Object.keys(codes).reduce(function (normalized, name) {
79
79
  if (name === representatives[name]) {
80
80
  const code = codes[name];
81
-
82
81
  switch (code.code) {
83
82
  case "union":
84
83
  case "product":
package/index.mjs CHANGED
@@ -1,7 +1,5 @@
1
1
  import { parse } from "./parser.mjs";
2
-
3
2
  import run from "./run.mjs";
4
-
5
3
  import t from "./codes.mjs";
6
4
 
7
5
  function finalize(codes) {
@@ -31,5 +29,4 @@ function runScriptOnData(script, data) {
31
29
  runScriptOnData.doc = "Run 'script' (string) on 'data': (script,data) -> data";
32
30
 
33
31
  export default { compile, run: runScriptOnData, parse };
34
-
35
32
  export { compile, runScriptOnData as run, parse };
package/k.mjs CHANGED
@@ -9,7 +9,7 @@ const prog = process.argv[1];
9
9
 
10
10
  let kScript, jsonStream, oneJson;
11
11
 
12
- ({ kScript, jsonStream, oneJson } = (function (oneJson, args) {
12
+ ({ kScript, jsonStream, oneJson } = ((oneJson, args) => {
13
13
  let e;
14
14
  try {
15
15
  kScript = (function (arg) {
@@ -44,49 +44,36 @@ let kScript, jsonStream, oneJson;
44
44
  })(false, process.argv.slice(2)));
45
45
 
46
46
  if (oneJson) {
47
- (function (buffer) {
48
- jsonStream.on("data", function (data) {
49
- return buffer.push(data);
50
- });
51
- return jsonStream.on("end", function () {
52
- var e;
53
- try {
54
- return console.log(
55
- JSON.stringify(kScript(JSON.parse(buffer.join(""))))
56
- );
57
- } catch (error) {
58
- e = error;
59
- return console.error(e);
60
- }
61
- });
62
- })([]);
47
+ const buffer = [];
48
+ jsonStream.on("data", (data) => buffer.push(data));
49
+ jsonStream.on("end", () => {
50
+ try {
51
+ console.log(JSON.stringify(kScript(JSON.parse(buffer.join(""))), null, 2));
52
+ } catch (error) {
53
+ console.error(error);
54
+ }
55
+ });
63
56
  } else {
64
- (function (buffer, line) {
65
- return jsonStream.on("data", function (data) {
66
- var e, first, i, json, last, len, ref, rest, results, todo;
67
- [first, ...rest] = data.toString("utf8").split("\n");
68
- buffer.push(first);
69
- if (rest.length > 0) {
70
- todo = buffer.join("");
71
- (ref = rest), ([...rest] = ref), ([last] = splice.call(rest, -1));
72
- buffer = [last];
73
- todo = [todo, ...rest];
74
- results = [];
75
- for (i = 0, len = todo.length; i < len; i++) {
76
- json = todo[i];
77
- if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
78
- try {
79
- console.log(JSON.stringify(kScript(JSON.parse(json))));
80
- } catch (error) {
81
- e = error;
82
- console.error(`Problem [line ${line}]: '${json}'`);
83
- console.error(e);
84
- }
57
+ let buffer = [];
58
+ let line = 0;
59
+ jsonStream.on("data", (data) => {
60
+ const [first, ...rest] = data.toString("utf8").split("\n");
61
+ buffer.push(first);
62
+ if (rest.length > 0) {
63
+ const todo = buffer.join("");
64
+ const last = rest.pop();
65
+ buffer = [last];;
66
+ for (const exp of [todo, ...rest]) {
67
+ if (!exp.match(/^[ \n\t]*(?:#.*)?$/)) {
68
+ try {
69
+ console.log(JSON.stringify(kScript(JSON.parse(exp))));
70
+ } catch (error) {
71
+ console.error(`Problem [line ${line}]: '${exp}'`);
72
+ console.error(error);
85
73
  }
86
- results.push((line = line + 1));
87
74
  }
88
- return results;
75
+ line++;
89
76
  }
90
- });
91
- })([], 0);
77
+ }
78
+ });
92
79
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "k-language for JSON-like data transformation",
5
5
  "main": "index.mjs",
6
6
  "scripts": {
package/run.mjs CHANGED
@@ -101,6 +101,22 @@ function run(exp, value) {
101
101
  }
102
102
  return builtin[exp.ref](value);
103
103
  case "dot":
104
+ if (typeof value === "string") {
105
+ if (value == exp.dot) return {};
106
+ return;
107
+ }
108
+ if (/^(0|([1-9]\d*))$/.test(value)) {
109
+ if (value == exp.dot) return {};
110
+ return;
111
+ }
112
+ if (value === true) {
113
+ if (exp.dot == "true") return {};
114
+ return;
115
+ }
116
+ if (value === false) {
117
+ if (exp.dot == "false") return {};
118
+ return;
119
+ }
104
120
  return value[exp.dot];
105
121
  case "comp":
106
122
  return exp.comp.reduce((value, exp) => {
package/INTRO.md DELETED
@@ -1,160 +0,0 @@
1
- # k - the way of building and manipulating JSON-like data
2
-
3
- Technically, `k` is a notation for defining __first-order partial functions__.
4
-
5
- An example of a _partial function_ is the _projection_, e.g., "`.toto`",
6
- which maps an object to its property named `toto`, or it is not defined if
7
- the property doesn't exist. E.g.,
8
-
9
- .toto :
10
- {"toto": 5, "titi": 10} --> 5
11
- {"titi": 10} ... undefined // it is not a value!
12
-
13
- ---
14
-
15
- ## Combining "partial functions"
16
-
17
- There are three ways of combining functions:
18
-
19
- 1. __composition__: `(f1 f2 ...)`, e.g. `(.toto .titi)` extracts
20
- nested field.
21
-
22
- (.toto .titi) :
23
- {"toto": {"titi": 10}} --> 10
24
- {"toto": 10 } ... undefined
25
- {} ... undefined
26
-
27
- 2. __merge__: `< f1, f2,... >`, e.g., `<.toto, .titi>` extracts field
28
- `toto` if present; otherwise extracts `titi`.
29
-
30
- <.toto, .titi> :
31
- {"toto": 5, "titi": 10} --> 5
32
- {"titi": 10 } --> 10
33
- {} ... undefined
34
-
35
- 3. __product__: `{ f1 label1, f2 label2, ...}`, e.g., `{.toto TOTO,
36
- .titi TITI}` extracts two fields and builds a record out of them.
37
-
38
- {.toto TOTO, .titi TITI} :
39
- {"toto": 5, "titi": 10} --> {"TOTO": 5, "TITI": 10}
40
- {"titi": 10 } ... undefined
41
-
42
- ---
43
-
44
- __QUIZ__: What is:
45
-
46
- - empty composition: `()` ?
47
- - empty merge: `<>` ?
48
- - empty product: `{}` ?
49
- - `{{{{} s} s} s}` ?
50
- - `({{{() a} b} c} .c .b .a)` ?
51
-
52
- ---
53
-
54
- #### Syntactic sugar:
55
-
56
- - parenthesis can be omitted, except for the empty composition `()`,
57
- - dot (`.`) in "projection" acts as a separator so the space around it can be omitted.
58
-
59
- For example, `[(.toto .titi (.0 .1))]` can be written as `[.toto.titi.0.1]`.
60
-
61
-
62
- ## Basic extensions
63
-
64
- ### Constants, i.e., literals for `strings`, `integers`, `booleans`, and `null`
65
-
66
- A constant defines a function which ignores its argument and produces
67
- the constant value. E.g.:
68
-
69
- {123 int, "kScript" str, true bool, null null} :
70
- <any> --> {"int":123,"str":"kScript","bool":true,"null":null}
71
-
72
- ### Vector product
73
-
74
- Vector product can be used as an abbreviation for product whose field
75
- names are integers starting from zero. E.g., `{.toto "0", .titi "1",
76
- 123 "2"}` can be written as `[.toto, .titi, 123]`.
77
-
78
- [.toto, .titi, 12] :
79
- {"toto": 5, "titi": 10 } --> [5, 10, 12] // {"0":5,"1":10,"2":12}
80
-
81
- .1 :
82
- ["A","B","C"] --> "B"
83
- ["a"] ... undefined
84
- ---
85
-
86
- ## Pragmatic extensions, aka "standard library"
87
-
88
- - `GT` : -- identity for lists of decreasing elements; undefined otherwise
89
-
90
- [4,3] --> [4,3]
91
- [3,4] ... undefined
92
- [] --> []
93
- [4,3,0] --> [4,3,0]
94
-
95
- - `EQ` : -- identity for lists of equal elements; undefined otherwise
96
-
97
- [4,4] --> [4,4]
98
- [4,5] ... undefined
99
- [4,4,4] --> [4,4,4]
100
- [] --> []
101
-
102
- - `{PLUS plus, TIMES times}` :
103
-
104
- [1,2] --> {"plus":3,"times":2}
105
- [2,2,2] --> {"plus":6,"times":8}
106
- [] --> {"plus":0,"times":1}
107
-
108
- - `CONCAT` :
109
-
110
- ["a","bc","d"] --> "abcd"
111
-
112
- - `toJSON` :
113
-
114
- {"a": 12} --> "{\"a\":12}"
115
-
116
- - `fromJSON` :
117
-
118
- "{\"a\":12}" --> {"a":12}
119
-
120
- - other predefined parial functions are: `DIV`, `FDIV`, `CONS`, `SNOC`, `toDateMsec`,
121
- `toDateStr`, and `_log!`.
122
-
123
- ---
124
-
125
- ## Recursive definitions
126
-
127
- -- factorial.k
128
- dec = [(),-1] PLUS;
129
- zero? = [(),0] EQ 0;
130
- factorial = <
131
- zero? 1,
132
- [dec factorial, ()] TIMES
133
- >;
134
- { () x, factorial "x!" }
135
-
136
- ## Codes (_types_)
137
-
138
- _Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
139
-
140
- $nat = <nat 1, {} 0>;
141
- $pair = {nat x, nat y};
142
-
143
- suc = {$nat 1};
144
- add = $pair <{.x.1 x, .y suc y} add, .y>;
145
-
146
- ### Basic extension codes
147
-
148
- Since _basic extension_ introduces integers, booleans, and strings, there are three
149
- predefined types: `int`, `bool`, and `string`. A vector product code can also be defined
150
- by `[ codeExp ]`. All members of the vector are the same code. E.g.,
151
-
152
- $intVector = [ int ];
153
- $boolVector = [ bool ];
154
- $tree = [ tree ];
155
-
156
- emptyList? = $intVector $[ string ]; -- as only an empty vector can be a vector
157
- -- of integers and a vector of strings
158
-
159
-
160
-