@mojir/lits 2.1.34 → 2.1.36
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 +396 -291
- package/dist/cli/cli.js +142 -82
- package/dist/index.esm.js +141 -81
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +141 -81
- package/dist/index.js.map +1 -1
- package/dist/lits.iife.js +141 -81
- package/dist/lits.iife.js.map +1 -1
- package/dist/testFramework.esm.js +141 -81
- package/dist/testFramework.esm.js.map +1 -1
- package/dist/testFramework.js +141 -81
- package/dist/testFramework.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ let squares = [1, 2, 3, 4, 5] map square;
|
|
|
68
68
|
// => [1, 4, 9, 16, 25]
|
|
69
69
|
|
|
70
70
|
// Using operator as a function
|
|
71
|
-
let sum = +(
|
|
71
|
+
let sum = +(1, 2, 3, 4, 5);
|
|
72
72
|
// => 15
|
|
73
73
|
```
|
|
74
74
|
|
|
@@ -78,31 +78,31 @@ let sum = +([1, 2, 3, 4, 5]);
|
|
|
78
78
|
|
|
79
79
|
```lits
|
|
80
80
|
// Numbers
|
|
81
|
-
42 // integer
|
|
82
|
-
3.14 // float
|
|
83
|
-
0xFFFF // hexadecimal
|
|
84
|
-
0b1100 // binary
|
|
85
|
-
0o77 // octal
|
|
86
|
-
-2.3e-2 // scientific notation
|
|
81
|
+
42; // integer
|
|
82
|
+
3.14; // float
|
|
83
|
+
0xFFFF; // hexadecimal
|
|
84
|
+
0b1100; // binary
|
|
85
|
+
0o77; // octal
|
|
86
|
+
-2.3e-2; // scientific notation
|
|
87
87
|
|
|
88
88
|
// Strings
|
|
89
|
-
"Hello, world!"
|
|
89
|
+
"Hello, world!";
|
|
90
90
|
|
|
91
91
|
// Booleans
|
|
92
|
-
true
|
|
93
|
-
false
|
|
92
|
+
true;
|
|
93
|
+
false;
|
|
94
94
|
|
|
95
95
|
// Null
|
|
96
|
-
null
|
|
96
|
+
null;
|
|
97
97
|
|
|
98
98
|
// Arrays
|
|
99
|
-
[1, 2, 3, 4]
|
|
99
|
+
[1, 2, 3, 4];
|
|
100
100
|
|
|
101
101
|
// Objects
|
|
102
|
-
{ name: "John", age: 30 }
|
|
102
|
+
{ name: "John", age: 30 };
|
|
103
103
|
|
|
104
104
|
// Regular expressions
|
|
105
|
-
#"pattern"
|
|
105
|
+
#"pattern";
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
### Mathematical Constants
|
|
@@ -110,26 +110,23 @@ null
|
|
|
110
110
|
Lits provides predefined mathematical constants:
|
|
111
111
|
|
|
112
112
|
```lits
|
|
113
|
-
PI // => 3.141592653589793
|
|
114
|
-
|
|
115
|
-
E // => 2.718281828459045 (Euler's number)
|
|
116
|
-
|
|
117
|
-
PHI // => 1.618033988749895 (Golden ratio)
|
|
118
|
-
|
|
113
|
+
PI; // => 3.141592653589793
|
|
114
|
+
π; // => 3.141592653589793 (Unicode alternative)
|
|
115
|
+
E; // => 2.718281828459045 (Euler's number)
|
|
116
|
+
ε; // => 2.718281828459045 (Unicode alternative)
|
|
117
|
+
PHI; // => 1.618033988749895 (Golden ratio)
|
|
118
|
+
φ; // => 1.618033988749895 (Unicode alternative)
|
|
119
119
|
|
|
120
120
|
// Infinity values
|
|
121
|
-
POSITIVE_INFINITY // => Infinity
|
|
122
|
-
|
|
123
|
-
NEGATIVE_INFINITY // => -Infinity
|
|
121
|
+
POSITIVE_INFINITY; // => Infinity
|
|
122
|
+
∞; // => Infinity (Unicode alternative)
|
|
123
|
+
NEGATIVE_INFINITY; // => -Infinity
|
|
124
124
|
|
|
125
125
|
// Integer and float limits
|
|
126
|
-
MAX_SAFE_INTEGER // => 9007199254740991
|
|
127
|
-
MIN_SAFE_INTEGER // => -9007199254740991
|
|
128
|
-
MAX_VALUE // => 1.7976931348623157e+308
|
|
129
|
-
MIN_VALUE // => 5e-324
|
|
130
|
-
|
|
131
|
-
// Not a Number
|
|
132
|
-
NaN // => NaN
|
|
126
|
+
MAX_SAFE_INTEGER; // => 9007199254740991
|
|
127
|
+
MIN_SAFE_INTEGER; // => -9007199254740991
|
|
128
|
+
MAX_VALUE; // => 1.7976931348623157e+308
|
|
129
|
+
MIN_VALUE; // => 5e-324
|
|
133
130
|
```
|
|
134
131
|
|
|
135
132
|
## Special Expressions
|
|
@@ -144,7 +141,7 @@ let x = 10;
|
|
|
144
141
|
// => 10
|
|
145
142
|
|
|
146
143
|
// Variables are immutable
|
|
147
|
-
let x = 20; // Error: x is already defined
|
|
144
|
+
// let x = 20; // Error: x is already defined
|
|
148
145
|
|
|
149
146
|
// Shadowing in inner scopes
|
|
150
147
|
let y = {
|
|
@@ -156,29 +153,116 @@ let y = {
|
|
|
156
153
|
|
|
157
154
|
#### Destructuring
|
|
158
155
|
|
|
156
|
+
##### Basic Object Destructuring
|
|
157
|
+
|
|
159
158
|
```lits
|
|
160
159
|
// Object destructuring
|
|
161
160
|
let { name, age } = { name: "John", age: 30 };
|
|
162
161
|
// name => "John", age => 30
|
|
162
|
+
```
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
let [first, second] = [1, 2, 3, 4];
|
|
166
|
-
// first => 1, second => 2
|
|
167
|
-
|
|
164
|
+
```lits
|
|
168
165
|
// With default values
|
|
169
166
|
let { name = "Unknown", age = 0 } = { name: "John" };
|
|
170
167
|
// name => "John", age => 0
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```lits
|
|
171
|
+
// Renaming with 'as'
|
|
172
|
+
let { name as userName } = { name: "Dave" };
|
|
173
|
+
// userName => "Dave"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```lits
|
|
177
|
+
// Multiple renames
|
|
178
|
+
let { firstName as name, age as years } = { firstName: "Eve", age: 28 };
|
|
179
|
+
// name => "Eve", years => 28
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
##### Advanced Destructuring Patterns
|
|
183
|
+
|
|
184
|
+
```lits
|
|
185
|
+
// Complex nested destructuring with defaults and renaming
|
|
186
|
+
let {
|
|
187
|
+
name as userName = "Guest",
|
|
188
|
+
profile: {
|
|
189
|
+
age = 0,
|
|
190
|
+
contact: { email as userEmail = "none" }
|
|
191
|
+
},
|
|
192
|
+
settings = { theme: "light" },
|
|
193
|
+
scores as userScores = [],
|
|
194
|
+
...others
|
|
195
|
+
} = { name: "Sam", profile: { contact: {} }};
|
|
196
|
+
// userName => "Sam", age => 0, userEmail => "none", etc.
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```lits
|
|
200
|
+
// Combining array and object destructuring
|
|
201
|
+
let [{ name }, { age }] = [{ name: "Tina" }, { age: 33 }];
|
|
202
|
+
// name => "Tina", age => 33
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```lits
|
|
206
|
+
// Object with array property destructuring
|
|
207
|
+
let { name, scores: [one, two] } = { name: "Uma", scores: [85, 92] };
|
|
208
|
+
// name => "Uma", one => 85, two => 92
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
##### Array Destructuring
|
|
171
212
|
|
|
172
|
-
|
|
213
|
+
```lits
|
|
214
|
+
// Array destructuring
|
|
215
|
+
let [, , a, b] = [1, 2, 3, 4];
|
|
216
|
+
// a => 3, b => 4
|
|
217
|
+
|
|
218
|
+
// Array destructuring with defaults
|
|
219
|
+
let [one, two = 2] = [1];
|
|
220
|
+
// one => 1, two => 2
|
|
221
|
+
|
|
222
|
+
// Skipping elements
|
|
223
|
+
let [x, , z] = [1, 2, 3];
|
|
224
|
+
// x => 1, z => 3
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
##### Rest Patterns
|
|
228
|
+
|
|
229
|
+
```lits
|
|
230
|
+
// Array rest pattern
|
|
173
231
|
let [head, ...tail] = [1, 2, 3, 4];
|
|
174
232
|
// head => 1, tail => [2, 3, 4]
|
|
175
233
|
|
|
176
|
-
//
|
|
177
|
-
let
|
|
178
|
-
|
|
234
|
+
// Object rest pattern
|
|
235
|
+
let { name, ...otherProps } = { name: "John", age: 30, city: "NYC" };
|
|
236
|
+
// name => "John", otherProps => { age: 30, city: "NYC" }
|
|
179
237
|
|
|
180
|
-
|
|
181
|
-
|
|
238
|
+
// Empty rest patterns
|
|
239
|
+
let [only, ...empty] = [1];
|
|
240
|
+
// only => 1, empty => []
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
##### Function Parameter Destructuring
|
|
244
|
+
|
|
245
|
+
```lits
|
|
246
|
+
// Basic parameter destructuring
|
|
247
|
+
let greet = ({ name }) -> "Hello, " ++ name;
|
|
248
|
+
greet({ name: "Pat" });
|
|
249
|
+
// => "Hello, Pat"
|
|
250
|
+
|
|
251
|
+
// With defaults in parameters
|
|
252
|
+
let greet2 = ({ name = "friend" }) -> "Hello, " ++ name;
|
|
253
|
+
greet2({});
|
|
254
|
+
// => "Hello, friend"
|
|
255
|
+
|
|
256
|
+
// Nested parameter destructuring
|
|
257
|
+
let processUser = ({ profile: { name, age }}) ->
|
|
258
|
+
name ++ " is " ++ str(age);
|
|
259
|
+
processUser({ profile: { name: "Quinn", age: 29 }});
|
|
260
|
+
// => "Quinn is 29"
|
|
261
|
+
|
|
262
|
+
// Array parameter destructuring
|
|
263
|
+
let processCoords = ([x, y]) -> x + y;
|
|
264
|
+
processCoords([3, 4]);
|
|
265
|
+
// => 7
|
|
182
266
|
```
|
|
183
267
|
|
|
184
268
|
### Functions
|
|
@@ -196,10 +280,10 @@ let square = x -> x * x;
|
|
|
196
280
|
let constant = () -> 42;
|
|
197
281
|
|
|
198
282
|
// Positional arguments
|
|
199
|
-
let add = -> $1 + $2;
|
|
283
|
+
let add-v2 = -> $1 + $2;
|
|
200
284
|
|
|
201
285
|
// Single positional argument
|
|
202
|
-
let square = -> $ * $;
|
|
286
|
+
let square-v2 = -> $ * $;
|
|
203
287
|
|
|
204
288
|
// Self-reference for recursion
|
|
205
289
|
let factorial = n ->
|
|
@@ -215,49 +299,76 @@ let factorial = n ->
|
|
|
215
299
|
#### If/Unless
|
|
216
300
|
|
|
217
301
|
```lits
|
|
218
|
-
//
|
|
302
|
+
let x = !:random-int(0, 20); // Random number between 0 and 19
|
|
303
|
+
|
|
219
304
|
if x > 10 then
|
|
220
305
|
"large"
|
|
221
306
|
else
|
|
222
307
|
"small"
|
|
223
|
-
end
|
|
308
|
+
end;
|
|
224
309
|
// => "large" (if x > 10) or "small" (if x <= 10)
|
|
225
310
|
|
|
226
311
|
// If without else returns null
|
|
227
|
-
if false then "never" end
|
|
312
|
+
if false then "never" end;
|
|
228
313
|
// => null
|
|
229
314
|
|
|
230
315
|
// Unless (inverted if)
|
|
231
|
-
|
|
316
|
+
let y = !:random-int(0, 20);
|
|
317
|
+
unless y > 10 then
|
|
232
318
|
"small"
|
|
233
319
|
else
|
|
234
320
|
"large"
|
|
235
|
-
end
|
|
236
|
-
// => "small" (if
|
|
321
|
+
end;
|
|
322
|
+
// => "small" (if y <= 10) or "large" (if y > 10)
|
|
237
323
|
```
|
|
238
324
|
|
|
239
325
|
#### Cond
|
|
240
326
|
|
|
241
327
|
```lits
|
|
328
|
+
let x = !:random-int(0, 20); // Random number between 0 and 19
|
|
329
|
+
|
|
242
330
|
// Multi-branch conditional
|
|
243
331
|
cond
|
|
244
332
|
case x < 5 then "small"
|
|
245
333
|
case x < 10 then "medium"
|
|
246
334
|
case x < 15 then "large"
|
|
247
|
-
end ?? "extra large"
|
|
335
|
+
end ?? "extra large";
|
|
248
336
|
// Tests conditions sequentially, returns first truthy match
|
|
337
|
+
|
|
338
|
+
// Cond with complex conditions
|
|
339
|
+
let urgent = !:random-int(0, 2) == 1;
|
|
340
|
+
let important = !:random-int(0, 2) == 1;
|
|
341
|
+
let priority = cond
|
|
342
|
+
case urgent && important then "critical"
|
|
343
|
+
case urgent then "high"
|
|
344
|
+
case important then "medium"
|
|
345
|
+
end ?? "low";
|
|
249
346
|
```
|
|
250
347
|
|
|
251
348
|
#### Switch
|
|
252
349
|
|
|
253
350
|
```lits
|
|
351
|
+
let x = !:random-int(0, 3); // Random number between 0 and 2
|
|
352
|
+
|
|
254
353
|
// Switch on value
|
|
255
354
|
switch x
|
|
256
355
|
case 0 then "zero"
|
|
257
356
|
case 1 then "one"
|
|
258
357
|
case 2 then "two"
|
|
259
|
-
end
|
|
358
|
+
end;
|
|
260
359
|
// => "zero" (if x = 0), "one" (if x = 1), etc., or null if no match
|
|
360
|
+
|
|
361
|
+
// Switch with multiple cases
|
|
362
|
+
let userInput = "help";
|
|
363
|
+
let exit = -> "exiting";
|
|
364
|
+
let showHelp = -> "showing help";
|
|
365
|
+
let saveData = -> "saving data";
|
|
366
|
+
|
|
367
|
+
switch userInput
|
|
368
|
+
case "quit" then exit()
|
|
369
|
+
case "help" then showHelp()
|
|
370
|
+
case "save" then saveData()
|
|
371
|
+
end;
|
|
261
372
|
```
|
|
262
373
|
|
|
263
374
|
### Loops and Iteration
|
|
@@ -266,27 +377,41 @@ end
|
|
|
266
377
|
|
|
267
378
|
```lits
|
|
268
379
|
// Simple iteration
|
|
269
|
-
for (x in [1, 2, 3, 4]) -> x * 2
|
|
380
|
+
for (x in [1, 2, 3, 4]) -> x * 2;
|
|
270
381
|
// => [2, 4, 6, 8]
|
|
271
382
|
|
|
272
|
-
// With filtering
|
|
273
|
-
for (x in [1, 2, 3, 4] when odd?(x)) -> x * 2
|
|
383
|
+
// With filtering (when clause)
|
|
384
|
+
for (x in [1, 2, 3, 4] when odd?(x)) -> x * 2;
|
|
274
385
|
// => [2, 6]
|
|
275
386
|
|
|
276
|
-
// With while
|
|
277
|
-
for (x in [1, 2, 3, 4] while x < 3) -> x * 2
|
|
387
|
+
// With early termination (while clause)
|
|
388
|
+
for (x in [1, 2, 3, 4] while x < 3) -> x * 2;
|
|
278
389
|
// => [2, 4]
|
|
279
390
|
|
|
280
|
-
// With let bindings
|
|
281
|
-
for (x in [1, 2, 3] let doubled = x * 2) -> doubled + 1
|
|
391
|
+
// With let bindings for intermediate calculations
|
|
392
|
+
for (x in [1, 2, 3] let doubled = x * 2) -> doubled + 1;
|
|
282
393
|
// => [3, 5, 7]
|
|
283
394
|
|
|
284
395
|
// Multiple iterators
|
|
285
|
-
for (x in [1, 2], y in [10, 20]) -> x + y
|
|
396
|
+
for (x in [1, 2], y in [10, 20]) -> x + y;
|
|
286
397
|
// => [11, 21, 12, 22]
|
|
287
398
|
|
|
399
|
+
// Complex for comprehensions with multiple conditions
|
|
400
|
+
for (
|
|
401
|
+
i in range(10)
|
|
402
|
+
let ii = i ^ 2
|
|
403
|
+
while ii < 40
|
|
404
|
+
when ii % 3 == 0,
|
|
405
|
+
j in range(10)
|
|
406
|
+
when j % 2 == 1
|
|
407
|
+
) -> ii + j;
|
|
408
|
+
|
|
409
|
+
// Using previous bindings in subsequent iterations
|
|
410
|
+
for (x in [1, 2], y in [x, 2 * x]) -> x * y;
|
|
411
|
+
// => [1, 2, 4, 8]
|
|
412
|
+
|
|
288
413
|
// Object iteration
|
|
289
|
-
for (
|
|
414
|
+
for (entry in { a: 1, b: 2 } let [key, value] = entry) -> key ++ ":" ++ str(value);
|
|
290
415
|
// => ["a:1", "b:2"]
|
|
291
416
|
```
|
|
292
417
|
|
|
@@ -308,8 +433,41 @@ loop (n = 5, acc = 1) -> {
|
|
|
308
433
|
else
|
|
309
434
|
recur(n - 1, acc * n)
|
|
310
435
|
end
|
|
311
|
-
}
|
|
436
|
+
};
|
|
312
437
|
// => 120 (factorial of 5)
|
|
438
|
+
|
|
439
|
+
// Complex loop with multiple variables
|
|
440
|
+
loop (items = [1, 2, 3, 4, 5], sum = 0, cnt = 0) -> {
|
|
441
|
+
if empty?(items) then
|
|
442
|
+
{ sum: sum, average: sum / cnt }
|
|
443
|
+
else
|
|
444
|
+
recur(rest(items), sum + first(items), cnt + 1)
|
|
445
|
+
end
|
|
446
|
+
};
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Recursion with Recur
|
|
450
|
+
|
|
451
|
+
#### Function Recursion
|
|
452
|
+
|
|
453
|
+
```lits
|
|
454
|
+
// Simple recursive function with recur
|
|
455
|
+
let factorial = (n) -> {
|
|
456
|
+
if n <= 1 then
|
|
457
|
+
1
|
|
458
|
+
else
|
|
459
|
+
n * recur(n - 1)
|
|
460
|
+
end
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// Tail-recursive function
|
|
464
|
+
let sumToN = (n, acc = 0) -> {
|
|
465
|
+
if zero?(n) then
|
|
466
|
+
acc
|
|
467
|
+
else
|
|
468
|
+
recur(n - 1, acc + n)
|
|
469
|
+
end
|
|
470
|
+
};
|
|
313
471
|
```
|
|
314
472
|
|
|
315
473
|
### Error Handling
|
|
@@ -318,223 +476,207 @@ loop (n = 5, acc = 1) -> {
|
|
|
318
476
|
|
|
319
477
|
```lits
|
|
320
478
|
// Basic try/catch
|
|
479
|
+
let riskyOperation = () -> throw("Something went wrong");
|
|
321
480
|
try
|
|
322
481
|
riskyOperation()
|
|
323
482
|
catch
|
|
324
483
|
"Something went wrong"
|
|
325
|
-
end
|
|
484
|
+
end;
|
|
326
485
|
|
|
327
486
|
// With error binding
|
|
328
487
|
try
|
|
329
488
|
riskyOperation()
|
|
330
489
|
catch (error)
|
|
331
490
|
"Error: " ++ error.message
|
|
332
|
-
end
|
|
491
|
+
end;
|
|
492
|
+
|
|
493
|
+
// Try-catch for graceful degradation
|
|
494
|
+
let parseData = () -> { value: 42 };
|
|
495
|
+
let process = (val) -> val * 2;
|
|
496
|
+
try
|
|
497
|
+
let { value } = parseData();
|
|
498
|
+
process(value);
|
|
499
|
+
catch
|
|
500
|
+
"Using default value"
|
|
501
|
+
end;
|
|
333
502
|
```
|
|
334
503
|
|
|
335
504
|
#### Throw
|
|
336
505
|
|
|
337
506
|
```lits
|
|
338
507
|
// Throwing errors
|
|
339
|
-
|
|
508
|
+
try
|
|
509
|
+
throw("Custom error message")
|
|
510
|
+
catch
|
|
511
|
+
"Caught an error"
|
|
512
|
+
end;
|
|
340
513
|
|
|
341
|
-
//
|
|
514
|
+
// Custom error messages in functions
|
|
342
515
|
let divide = (a, b) ->
|
|
343
516
|
if zero?(b) then
|
|
344
|
-
throw("
|
|
517
|
+
throw("Cannot divide by zero")
|
|
345
518
|
else
|
|
346
519
|
a / b
|
|
347
520
|
end;
|
|
348
|
-
```
|
|
349
521
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
false && "never reached" // => false
|
|
358
|
-
|
|
359
|
-
// Logical OR (short-circuit)
|
|
360
|
-
false || "default value" // => "default value"
|
|
361
|
-
true || "never reached" // => true
|
|
362
|
-
|
|
363
|
-
// Multiple arguments
|
|
364
|
-
&&(true, true, "all true") // => "all true"
|
|
365
|
-
||(false, false, "found") // => "found"
|
|
522
|
+
// Conditional error throwing
|
|
523
|
+
let validateAge = (age) ->
|
|
524
|
+
cond
|
|
525
|
+
case age < 0 then throw("Age cannot be negative")
|
|
526
|
+
case age > 150 then throw("Age seems unrealistic")
|
|
527
|
+
case true then age
|
|
528
|
+
end;
|
|
366
529
|
```
|
|
367
530
|
|
|
368
|
-
|
|
531
|
+
### Block Expressions
|
|
369
532
|
|
|
370
533
|
```lits
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
534
|
+
// Block for grouping expressions
|
|
535
|
+
let computeX = () -> 5;
|
|
536
|
+
let computeY = () -> 10;
|
|
537
|
+
let processResult = (z) -> z * 2;
|
|
538
|
+
|
|
539
|
+
let result = {
|
|
540
|
+
let x = computeX();
|
|
541
|
+
let y = computeY();
|
|
542
|
+
let z = x * y;
|
|
543
|
+
processResult(z)
|
|
544
|
+
};
|
|
378
545
|
|
|
379
|
-
|
|
546
|
+
// Block with side effects
|
|
547
|
+
let loadData = () -> [1, 2, 3];
|
|
548
|
+
let processData = (data) -> data map -> $ * 2;
|
|
380
549
|
|
|
381
|
-
```lits
|
|
382
|
-
// Block expressions
|
|
383
550
|
{
|
|
384
|
-
|
|
385
|
-
let
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
551
|
+
write!("Starting process...");
|
|
552
|
+
let data = loadData();
|
|
553
|
+
let processed = processData(data);
|
|
554
|
+
write!("Process completed");
|
|
555
|
+
processed
|
|
556
|
+
};
|
|
389
557
|
```
|
|
390
558
|
|
|
391
|
-
###
|
|
559
|
+
### Array and Object Spread
|
|
392
560
|
|
|
393
|
-
#### Array
|
|
561
|
+
#### Array Spread
|
|
394
562
|
|
|
395
563
|
```lits
|
|
396
|
-
//
|
|
397
|
-
[1, 2, 3, 4]
|
|
398
|
-
|
|
399
|
-
// Array function
|
|
400
|
-
array(1, 2, 3, 4)
|
|
401
|
-
|
|
402
|
-
// With spread
|
|
403
|
-
[1, 2, ...[3, 4, 5], 6]
|
|
564
|
+
// Spread in array literals
|
|
565
|
+
let combined = [1, 2, ...[3, 4, 5], 6];
|
|
404
566
|
// => [1, 2, 3, 4, 5, 6]
|
|
567
|
+
|
|
568
|
+
// Multiple spreads
|
|
569
|
+
let start = [1, 2];
|
|
570
|
+
let middle = [3, 4];
|
|
571
|
+
let stop = [5, 6];
|
|
572
|
+
let result = [...start, ...middle, ...stop];
|
|
405
573
|
```
|
|
406
574
|
|
|
407
|
-
#### Object
|
|
575
|
+
#### Object Spread
|
|
408
576
|
|
|
409
577
|
```lits
|
|
410
|
-
// Object
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
// Object function
|
|
414
|
-
object("name", "John", "age", 30)
|
|
415
|
-
|
|
416
|
-
// With spread
|
|
417
|
-
let defaults = { type: "Person", active: true };
|
|
418
|
-
{
|
|
419
|
-
...defaults,
|
|
578
|
+
// Object spread for merging
|
|
579
|
+
let person = {
|
|
420
580
|
name: "John",
|
|
421
581
|
age: 30
|
|
422
|
-
}
|
|
423
|
-
// => { type: "Person", active: true, name: "John", age: 30 }
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
### Recursion
|
|
582
|
+
};
|
|
427
583
|
|
|
428
|
-
|
|
584
|
+
let employee = {
|
|
585
|
+
...person,
|
|
586
|
+
id: "E123",
|
|
587
|
+
department: "Engineering"
|
|
588
|
+
};
|
|
589
|
+
// => { name: "John", age: 30, id: "E123", department: "Engineering" }
|
|
429
590
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
recur(n - 1)
|
|
436
|
-
end
|
|
591
|
+
// Spread with override
|
|
592
|
+
let defaults = {
|
|
593
|
+
name: "Default Name",
|
|
594
|
+
theme: "light",
|
|
595
|
+
active: true
|
|
437
596
|
};
|
|
438
597
|
|
|
439
|
-
|
|
440
|
-
|
|
598
|
+
let updated = {
|
|
599
|
+
...defaults,
|
|
600
|
+
name: "Custom Name" // Override defaults.name
|
|
601
|
+
};
|
|
441
602
|
```
|
|
442
603
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
### Algebraic Notation
|
|
604
|
+
### Logical Operators
|
|
446
605
|
|
|
447
|
-
|
|
606
|
+
#### And/Or
|
|
448
607
|
|
|
449
608
|
```lits
|
|
450
|
-
//
|
|
451
|
-
|
|
609
|
+
// Logical AND (short-circuit)
|
|
610
|
+
true && "second value"; // => "second value"
|
|
611
|
+
false && "never reached"; // => false
|
|
612
|
+
|
|
613
|
+
// Logical OR (short-circuit)
|
|
614
|
+
false || "default value"; // => "default value"
|
|
615
|
+
true || "never reached"; // => true
|
|
452
616
|
|
|
453
|
-
//
|
|
454
|
-
|
|
617
|
+
// Multiple arguments
|
|
618
|
+
&&(true, true, "all true"); // => "all true"
|
|
619
|
+
||(false, false, "found"); // => "found"
|
|
455
620
|
```
|
|
456
621
|
|
|
457
|
-
|
|
622
|
+
#### Null Coalescing
|
|
458
623
|
|
|
459
624
|
```lits
|
|
460
|
-
//
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
//
|
|
464
|
-
|
|
625
|
+
// Null coalescing operator
|
|
626
|
+
null ?? "default"; // => "default"
|
|
627
|
+
undefined-var ?? "default"; // => "default"
|
|
628
|
+
0 ?? "default"; // => 0 (only null/undefined are coalesced)
|
|
629
|
+
false ?? "default"; // => false
|
|
630
|
+
"" ?? "default"; // => ""
|
|
631
|
+
```
|
|
465
632
|
|
|
466
|
-
|
|
467
|
-
let add5 = +(5, _);
|
|
468
|
-
add5(3) // => 8
|
|
633
|
+
### Ternary Operator
|
|
469
634
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
635
|
+
```lits
|
|
636
|
+
// Conditional expression
|
|
637
|
+
let age = !:random-int(10, 60);
|
|
638
|
+
let result = age >= 18 ? "adult" : "minor";
|
|
473
639
|
|
|
474
|
-
//
|
|
475
|
-
let
|
|
476
|
-
|
|
640
|
+
// Nested ternary
|
|
641
|
+
let score = !:random-int(0, 100);
|
|
642
|
+
let category = score >= 90 ? "A" : score >= 80 ? "B" : "C";
|
|
477
643
|
|
|
478
|
-
|
|
479
|
-
|
|
644
|
+
// With complex expressions
|
|
645
|
+
let isLoggedIn = () -> true;
|
|
646
|
+
let hasPermission = () -> true;
|
|
647
|
+
let status = isLoggedIn() && hasPermission() ? "authorized" : "unauthorized";
|
|
480
648
|
```
|
|
481
649
|
|
|
482
|
-
|
|
650
|
+
## Operators and Precedence
|
|
483
651
|
|
|
484
|
-
Lits
|
|
652
|
+
Lits follows a clear operator precedence hierarchy. Understanding precedence helps you write expressions that behave as expected:
|
|
485
653
|
|
|
486
|
-
|
|
487
|
-
// Function style
|
|
488
|
-
filter([1, 2, 3, 4], odd?) // => [1, 3]
|
|
654
|
+
### Precedence Table (Highest to Lowest)
|
|
489
655
|
|
|
490
|
-
|
|
491
|
-
|
|
656
|
+
1. **Function calls** - `fn(args)`
|
|
657
|
+
2. **Array/Object access** - `arr[index]`, `obj.property`
|
|
658
|
+
3. **Unary operators** - `not`, `!`, `-` (negation)
|
|
659
|
+
4. **Exponentiation** - `^` (right-associative)
|
|
660
|
+
5. **Multiplication, Division, Modulo** - `*`, `/`, `%`
|
|
661
|
+
6. **Addition, Subtraction** - `+`, `-`
|
|
662
|
+
7. **String concatenation** - `++`
|
|
663
|
+
8. **Comparison operators** - `<`, `>`, `<=`, `>=`
|
|
664
|
+
9. **Equality operators** - `==`, `!=`, `identical?`
|
|
665
|
+
10. **Logical AND** - `&&`
|
|
666
|
+
11. **Logical OR** - `||`
|
|
667
|
+
12. **Null coalescing** - `??`
|
|
668
|
+
13. **Ternary conditional** - `condition ? true-value : false-value`
|
|
492
669
|
|
|
493
|
-
|
|
494
|
-
[1, 2, 3, 4, 5, 6]
|
|
495
|
-
filter odd?
|
|
496
|
-
map square
|
|
497
|
-
reduce +
|
|
498
|
-
// => 35
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Pipe Operator
|
|
502
|
-
|
|
503
|
-
The pipe operator `|>` passes the result of the left expression as the first argument to the right function:
|
|
670
|
+
### Examples
|
|
504
671
|
|
|
505
672
|
```lits
|
|
506
|
-
//
|
|
507
|
-
|
|
673
|
+
// Comparison and logical operators
|
|
674
|
+
5 > 3 && 2 < 4; // => true
|
|
675
|
+
5 > 3 || 2 > 4; // => true
|
|
508
676
|
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|> map(_, square)
|
|
513
|
-
|> reduce(_, +)
|
|
514
|
-
// => 35
|
|
515
|
-
|
|
516
|
-
// Simple transformations
|
|
517
|
-
"hello world"
|
|
518
|
-
|> upper-case
|
|
519
|
-
|> split(_, " ")
|
|
520
|
-
|> reverse
|
|
521
|
-
|> join(_, "-")
|
|
522
|
-
// => "WORLD-HELLO"
|
|
523
|
-
|
|
524
|
-
// Mathematical operations
|
|
525
|
-
10
|
|
526
|
-
|> +(_, 5)
|
|
527
|
-
|> *(_, 2)
|
|
528
|
-
|> /(_, 3)
|
|
529
|
-
// => 10 (10 + 5 = 15, 15 * 2 = 30, 30 / 3 = 10)
|
|
530
|
-
|
|
531
|
-
// Data processing pipeline
|
|
532
|
-
{ numbers: [1, 2, 3, 4, 5], multiplier: 3 }
|
|
533
|
-
|> get(_, "numbers")
|
|
534
|
-
|> filter(_, even?)
|
|
535
|
-
|> map(_, *(_, 3))
|
|
536
|
-
|> reduce(_, +)
|
|
537
|
-
// => 18 (even numbers [2, 4] -> [6, 12] -> sum = 18)
|
|
677
|
+
// Ternary has low precedence
|
|
678
|
+
let x = !:random-int(0, 10);
|
|
679
|
+
x + 3 > 4 ? 1 : 0; // => (x + 3) > 4 ? 1 : 0
|
|
538
680
|
```
|
|
539
681
|
|
|
540
682
|
## Built-in Functions
|
|
@@ -557,7 +699,7 @@ For a complete reference of all available functions with examples, visit the [Li
|
|
|
557
699
|
|
|
558
700
|
```lits
|
|
559
701
|
// Export variables and functions
|
|
560
|
-
export let
|
|
702
|
+
export let pi = 3.14159;
|
|
561
703
|
export let square = x -> x * x;
|
|
562
704
|
|
|
563
705
|
// Exported values become available to other modules
|
|
@@ -568,12 +710,7 @@ export let square = x -> x * x;
|
|
|
568
710
|
### Factorial
|
|
569
711
|
|
|
570
712
|
```lits
|
|
571
|
-
let factorial = n ->
|
|
572
|
-
if n <= 1 then
|
|
573
|
-
1
|
|
574
|
-
else
|
|
575
|
-
n * self(n - 1)
|
|
576
|
-
end;
|
|
713
|
+
let factorial = n -> n <= 1 ? 1 : n * self(n - 1);
|
|
577
714
|
|
|
578
715
|
factorial(5) // => 120
|
|
579
716
|
```
|
|
@@ -585,110 +722,78 @@ let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
|
585
722
|
|
|
586
723
|
// Get even numbers squared
|
|
587
724
|
let evenSquares = numbers
|
|
588
|
-
filter even?
|
|
589
|
-
map
|
|
725
|
+
|> filter(_, even?)
|
|
726
|
+
|> map(_, -> $ * $);
|
|
590
727
|
// => [4, 16, 36, 64, 100]
|
|
591
728
|
|
|
592
729
|
// Sum of odd numbers
|
|
593
730
|
let oddSum = numbers
|
|
594
|
-
filter odd?
|
|
595
|
-
reduce
|
|
731
|
+
|> filter(_, odd?)
|
|
732
|
+
|> reduce(_, +, 0);
|
|
596
733
|
// => 25
|
|
597
734
|
```
|
|
598
735
|
|
|
599
|
-
###
|
|
600
|
-
|
|
601
|
-
```lits
|
|
602
|
-
let person = { name: "John", age: 30, city: "New York" };
|
|
603
|
-
|
|
604
|
-
// Update age
|
|
605
|
-
let older = assoc(person, "age", 31);
|
|
606
|
-
|
|
607
|
-
// Add new field
|
|
608
|
-
let withJob = assoc(older, "job", "Developer");
|
|
609
|
-
|
|
610
|
-
// Using pipe operator for chaining
|
|
611
|
-
let updated = person
|
|
612
|
-
|> assoc(_, "age", 31)
|
|
613
|
-
|> assoc(_, "job", "Developer");
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
### Pattern Matching Examples
|
|
617
|
-
|
|
618
|
-
#### Switch (for matching against a single value)
|
|
736
|
+
### String Processing
|
|
619
737
|
|
|
620
738
|
```lits
|
|
621
|
-
let
|
|
622
|
-
switch grade
|
|
623
|
-
case 90 then "A"
|
|
624
|
-
case 80 then "B"
|
|
625
|
-
case 70 then "C"
|
|
626
|
-
case 60 then "D"
|
|
627
|
-
end ?? "F";
|
|
739
|
+
let text = "Hello, World! How are you today?";
|
|
628
740
|
|
|
629
|
-
|
|
630
|
-
|
|
741
|
+
// Word count
|
|
742
|
+
let wordCount = text
|
|
743
|
+
|> split(_, #"\s+")
|
|
744
|
+
|> count(_);
|
|
745
|
+
// => 6
|
|
631
746
|
|
|
632
|
-
//
|
|
633
|
-
let
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
end ?? "Unknown Status";
|
|
747
|
+
// Uppercase words longer than 4 characters
|
|
748
|
+
let longWords = text
|
|
749
|
+
|> split(_, #"\s+")
|
|
750
|
+
|> filter(_, -> count($) > 4)
|
|
751
|
+
|> map(_, upper-case);
|
|
752
|
+
// => ["HELLO,", "WORLD!", "TODAY?"]
|
|
639
753
|
```
|
|
640
754
|
|
|
641
|
-
|
|
755
|
+
### Data Transformation
|
|
642
756
|
|
|
643
757
|
```lits
|
|
644
|
-
let
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
let
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
case score >= 60 then "D"
|
|
662
|
-
end ?? "F";
|
|
663
|
-
|
|
664
|
-
gradeToLetter(85) // => "B"
|
|
665
|
-
gradeToLetter(55) // => "F"
|
|
758
|
+
let users = [
|
|
759
|
+
{ name: "Alice", age: 30, department: "Engineering" },
|
|
760
|
+
{ name: "Bob", age: 25, department: "Marketing" },
|
|
761
|
+
{ name: "Charlie", age: 35, department: "Engineering" }
|
|
762
|
+
];
|
|
763
|
+
|
|
764
|
+
// Group by department and get average age
|
|
765
|
+
let grouped = users |> group-by(_, "department");
|
|
766
|
+
let departmentAges = grouped
|
|
767
|
+
|> entries(_)
|
|
768
|
+
|> map(_, ([dept, people]) -> {
|
|
769
|
+
let ages = people |> map(_, "age");
|
|
770
|
+
let total = ages |> reduce(_, +, 0);
|
|
771
|
+
[dept, total / count(ages)]
|
|
772
|
+
})
|
|
773
|
+
|> (pairs -> zipmap(map(pairs, 0), map(pairs, 1)));
|
|
774
|
+
// => { "Engineering": 32.5, "Marketing": 25 }
|
|
666
775
|
```
|
|
667
776
|
|
|
668
777
|
## JavaScript Interoperability
|
|
669
778
|
|
|
670
|
-
|
|
779
|
+
### Using Lits in JavaScript
|
|
671
780
|
|
|
672
781
|
```javascript
|
|
673
|
-
import { Lits } from 'lits';
|
|
782
|
+
import { Lits } from '@mojir/lits';
|
|
674
783
|
|
|
675
|
-
// Create a Lits instance
|
|
676
784
|
const lits = new Lits();
|
|
677
785
|
|
|
678
|
-
//
|
|
679
|
-
const
|
|
680
|
-
console.log(
|
|
786
|
+
// Basic usage
|
|
787
|
+
const result1 = lits.run('+(1, 2, 3)');
|
|
788
|
+
console.log(result1); // 6
|
|
681
789
|
|
|
682
|
-
//
|
|
790
|
+
// Provide JavaScript values
|
|
683
791
|
const result2 = lits.run('name ++ " is " ++ str(age)', {
|
|
684
|
-
values: {
|
|
685
|
-
name: "John",
|
|
686
|
-
age: 30
|
|
687
|
-
}
|
|
792
|
+
values: { name: 'John', age: 30 }
|
|
688
793
|
});
|
|
689
794
|
console.log(result2); // "John is 30"
|
|
690
795
|
|
|
691
|
-
// Expose JavaScript functions
|
|
796
|
+
// Expose JavaScript functions
|
|
692
797
|
const result3 = lits.run('myAlert("Hello from Lits!")', {
|
|
693
798
|
jsFunctions: {
|
|
694
799
|
myAlert: {
|