@mojir/lits 2.1.33 → 2.1.35

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
@@ -1,6 +1,6 @@
1
1
  # Lits
2
2
 
3
- Lits is a lexically scoped pure functional language with algebraic notation. It combines the power of functional programming with an intuitive, readable syntax.
3
+ Lits is a lexically scoped pure functional language with algebraic notation. It combines the power of functional programming with an intuitive, readable syntax that makes complex operations simple and expressive.
4
4
 
5
5
  Try it in the [Lits Playground](https://mojir.github.io/lits/).
6
6
 
@@ -13,18 +13,51 @@ Try it in the [Lits Playground](https://mojir.github.io/lits/).
13
13
  - **Comprehensive standard library** - Rich set of functions for collections, math, strings, and more
14
14
  - **Structural equality** - Objects are compared by value, not by reference
15
15
  - **Destructuring** - Extract values from complex data structures with ease
16
+ - **Lexical scoping** - Variables are scoped to their defining context
16
17
 
17
18
  ## Installation
18
19
 
19
- *[Add installation instructions here]*
20
+ ### As a Library
21
+
22
+ ```bash
23
+ npm install @mojir/lits
24
+ ```
25
+
26
+ ### CLI Tool
27
+
28
+ Install globally to use the Lits command-line interface:
29
+
30
+ ```bash
31
+ npm install --global @mojir/lits
32
+ ```
33
+
34
+ #### CLI Usage
35
+
36
+ ```bash
37
+ # Start an interactive REPL session
38
+ $ lits
39
+
40
+ # Evaluate Lits code directly
41
+ $ lits -e "5 + 3"
42
+ $ lits -e "[1, 2, 3, 4] filter odd? map inc"
43
+
44
+ # Run a Lits file
45
+ $ lits -f script.lits
46
+ $ lits -f examples/factorial.lits
47
+
48
+ # Get help
49
+ $ lits --help
50
+ ```
51
+
52
+ The REPL provides an interactive environment where you can experiment with Lits code, test functions, and explore the language features in real-time.
20
53
 
21
54
  ## Quick Start
22
55
 
23
56
  Here's a simple example to get you started:
24
57
 
25
- ```
58
+ ```lits
26
59
  // Defining a function
27
- square = x -> x * x;
60
+ let square = x -> x * x;
28
61
 
29
62
  // Using the function
30
63
  let result = square(5);
@@ -39,351 +72,697 @@ let sum = +([1, 2, 3, 4, 5]);
39
72
  // => 15
40
73
  ```
41
74
 
42
- ## Syntax
75
+ ## Basic Syntax
43
76
 
44
- ### Basic Data Types
77
+ ### Data Types
45
78
 
46
- ```
79
+ ```lits
47
80
  // Numbers
48
- 42 // integer
49
- 3.14 // float
50
- 0xFFFF // hexadecimal
51
- 0b1100 // binary
52
- 0o77 // octal
53
- -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
54
87
 
55
88
  // Strings
56
- "Hello, world!"
89
+ "Hello, world!";
57
90
 
58
91
  // Booleans
59
- true
60
- false
92
+ true;
93
+ false;
61
94
 
62
95
  // Null
63
- null
96
+ null;
64
97
 
65
98
  // Arrays
66
- [1, 2, 3, 4]
99
+ [1, 2, 3, 4];
67
100
 
68
101
  // Objects
69
- { name: "John", age: 30 }
70
- ```
71
-
72
- ### Builtin Number Symbols
73
-
74
- Lits provides a set of predefined mathematical constants that can be used directly in your code:
102
+ { name: "John", age: 30 };
75
103
 
104
+ // Regular expressions
105
+ #"pattern";
76
106
  ```
77
- // Mathematical constants
78
- PI // => 3.141592653589793
79
- π // => 3.141592653589793 (Unicode alternative)
80
- -PI // => -3.141592653589793
81
- -π // => -3.141592653589793
82
-
83
- E // => 2.718281828459045 (Euler's number)
84
- ε // => 2.718281828459045 (Unicode alternative)
85
- -E // => -2.718281828459045
86
- -ε // => -2.718281828459045
87
107
 
88
- PHI // => 1.618033988749895 (Golden ratio)
89
- φ // => 1.618033988749895 (Unicode alternative)
90
- -PHI // => -1.618033988749895
91
- -φ // => -1.618033988749895
108
+ ### Mathematical Constants
92
109
 
93
- // Infinity values
94
- POSITIVE_INFINITY // => Infinity
95
- ∞ // => Infinity (Unicode alternative)
96
- NEGATIVE_INFINITY // => -Infinity
97
- -∞ // => -Infinity (Unicode alternative)
110
+ Lits provides predefined mathematical constants:
98
111
 
99
- // Integer limits
100
- MAX_SAFE_INTEGER // => 9007199254740991
101
- MIN_SAFE_INTEGER // => -9007199254740991
112
+ ```lits
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)
102
119
 
103
- // Floating point limits
104
- MAX_VALUE // => 1.7976931348623157e+308
105
- MIN_VALUE // => 5e-324
120
+ // Infinity values
121
+ POSITIVE_INFINITY; // => Infinity
122
+ ∞; // => Infinity (Unicode alternative)
123
+ NEGATIVE_INFINITY; // => -Infinity
106
124
 
107
- // Not a Number
108
- NaN // => NaN
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
109
130
  ```
110
131
 
111
- These constants can be used anywhere a number value is expected and help make mathematical code more readable and elegant.
132
+ ## Special Expressions
112
133
 
113
134
  ### Variable Binding
114
135
 
115
- ```
116
- // Let expression
136
+ #### Let
137
+
138
+ ```lits
139
+ // Simple binding
117
140
  let x = 10;
118
141
  // => 10
119
142
 
120
143
  // Variables are immutable
121
- let x = 20; // Error: x is already defined
144
+ // let x = 20; // Error: x is already defined
122
145
 
123
- // But can be shadowed in inner scopes
124
- let y = do
146
+ // Shadowing in inner scopes
147
+ let y = {
125
148
  let x = 20;
126
149
  x
127
- end;
150
+ };
128
151
  // => 20, outer x is still 10
129
152
  ```
130
153
 
131
- ### Functions
154
+ #### Destructuring
155
+
156
+ ```lits
157
+ // Object destructuring
158
+ let { name, age } = { name: "John", age: 30 };
159
+ // name => "John", age => 30
160
+ ```
161
+
162
+ ```lits
163
+ // Array destructuring
164
+ let [a, b] = [1, 2, 3, 4];
165
+ // a => 1, b => 2
166
+ ```
167
+
168
+ ```lits
169
+ // With default values
170
+ let { name = "Unknown", age = 0 } = { name: "John" };
171
+ // name => "John", age => 0
172
+ ```
132
173
 
174
+ ```lits
175
+ // Rest patterns
176
+ let [head, ...tail] = [1, 2, 3, 4];
177
+ // head => 1, tail => [2, 3, 4]
133
178
  ```
134
- // Lambda functions
179
+
180
+ ```lits
181
+ // Destructuring in function parameters
182
+ let displayPerson = ({name, age}) ->
183
+ name ++ " is " ++ str(age) ++ " years old";
184
+
185
+ displayPerson({ name: "John", age: 30 });
186
+ // => "John is 30 years old"
187
+ ```
188
+
189
+ ### Functions
190
+
191
+ #### Lambda Functions
192
+
193
+ ```lits
194
+ // Multi-parameter lambda
135
195
  let add = (a, b) -> a + b;
136
196
 
137
- // Short form with positional arguments
138
- let add = -> $1 + $2;
197
+ // Single parameter (parentheses optional)
198
+ let square = x -> x * x;
199
+
200
+ // No parameters
201
+ let constant = () -> 42;
139
202
 
140
- // Single argument short form
141
- let cube = x -> x ** 3;
142
- let fourth = -> $ ** 4;
203
+ // Positional arguments
204
+ let add-v2 = -> $1 + $2;
205
+
206
+ // Single positional argument
207
+ let square-v2 = -> $ * $;
208
+
209
+ // Self-reference for recursion
210
+ let factorial = n ->
211
+ if n <= 1 then
212
+ 1
213
+ else
214
+ n * self(n - 1)
215
+ end;
143
216
  ```
144
217
 
145
218
  ### Control Flow
146
219
 
147
- ```
220
+ #### If/Unless
221
+
222
+ ```lits
148
223
  // If expression
224
+ let x = !:random-int(0, 20); // Random number between 0 and 19
225
+
149
226
  if x > 10 then
150
227
  "large"
151
228
  else
152
229
  "small"
230
+ end;
153
231
  // => "large" (if x > 10) or "small" (if x <= 10)
154
232
 
155
- // Unless expression (reversed if)
233
+ // If without else returns null
234
+ if false then "never" end;
235
+ // => null
236
+
237
+ // Unless (inverted if)
156
238
  unless x > 10 then
157
239
  "small"
158
240
  else
159
241
  "large"
242
+ end;
160
243
  // => "small" (if x <= 10) or "large" (if x > 10)
244
+ ```
245
+
246
+ #### Cond
247
+
248
+ ```lits
249
+ let x = !:random-int(0, 20); // Random number between 0 and 19
250
+
251
+ // Multi-branch conditional
252
+ cond
253
+ case x < 5 then "small"
254
+ case x < 10 then "medium"
255
+ case x < 15 then "large"
256
+ end ?? "extra large"
257
+ // Tests conditions sequentially, returns first truthy match
258
+ ```
259
+
260
+ #### Switch
261
+
262
+ ```lits
263
+ let x = !:random-int(0, 3); // Random number between 0 and 2
161
264
 
162
- // Switch expression
265
+ // Switch on value
163
266
  switch x
164
267
  case 0 then "zero"
165
268
  case 1 then "one"
166
269
  case 2 then "two"
167
- end;
168
- // => "zero" (if x = 0), "one" (if x = 1), "two" (if x = 2), or null (otherwise)
270
+ end
271
+ // => "zero" (if x = 0), "one" (if x = 1), etc., or null if no match
272
+ ```
169
273
 
170
- // Cond expression
171
- cond
172
- case val < 5 then "S"
173
- case val < 10 then "M"
174
- case val < 15 then "L"
175
- end ?? "No match";
176
- // => "S" (if val < 5), "M" (if 5 <= val < 10), "L" (if 10 <= val < 15), or "No match" (otherwise)
274
+ ### Loops and Iteration
275
+
276
+ #### For Comprehensions
277
+
278
+ ```lits
279
+ // Simple iteration
280
+ for (x in [1, 2, 3, 4]) -> x * 2;
281
+ // => [2, 4, 6, 8]
282
+
283
+ // With filtering
284
+ for (x in [1, 2, 3, 4] when odd?(x)) -> x * 2;
285
+ // => [2, 6]
286
+
287
+ // With while condition
288
+ for (x in [1, 2, 3, 4] while x < 3) -> x * 2;
289
+ // => [2, 4]
290
+
291
+ // With let bindings
292
+ for (x in [1, 2, 3] let doubled = x * 2) -> doubled + 1;
293
+ // => [3, 5, 7]
294
+
295
+ // Multiple iterators
296
+ for (x in [1, 2], y in [10, 20]) -> x + y;
297
+ // => [11, 21, 12, 22]
298
+
299
+ // Object iteration
300
+ for (entry in { a: 1, b: 2 } let [key, value] = entry) -> key ++ ":" ++ str(value);
301
+ // => ["a:1", "b:2"]
302
+ ```
303
+
304
+ #### Doseq (Side Effects)
305
+
306
+ ```lits
307
+ // For side effects only (returns null)
308
+ doseq (x in [1, 2, 3]) -> write!(x)
309
+ // Prints: 1 2 3, returns null
310
+ ```
311
+
312
+ #### Loop (Tail Recursion)
313
+
314
+ ```lits
315
+ // Loop with recur for tail recursion
316
+ loop (n = 5, acc = 1) -> {
317
+ if zero?(n) then
318
+ acc
319
+ else
320
+ recur(n - 1, acc * n)
321
+ end
322
+ }
323
+ // => 120 (factorial of 5)
324
+ ```
325
+
326
+ ### Error Handling
327
+
328
+ #### Try/Catch
177
329
 
178
- // Try/catch
330
+ ```lits
331
+ // Basic try/catch
332
+ try
333
+ riskyOperation()
334
+ catch
335
+ "Something went wrong"
336
+ end;
337
+
338
+ // With error binding
179
339
  try
180
340
  riskyOperation()
181
341
  catch (error)
182
342
  "Error: " ++ error.message
183
- // => result of riskyOperation() or error message if an exception occurs
343
+ end;
184
344
  ```
185
345
 
186
- ### List Comprehension
346
+ #### Throw
187
347
 
348
+ ```lits
349
+ // Throwing errors
350
+ try
351
+ throw("Custom error message");
352
+ catch
353
+ "Caught an error"
354
+ end;
355
+
356
+ // In context
357
+ let divide = (a, b) ->
358
+ if zero?(b) then
359
+ throw("Division by zero")
360
+ else
361
+ a / b
362
+ end;
188
363
  ```
189
- // Simple for comprehension
190
- TODO
364
+
365
+ ### Logical Operators
366
+
367
+ #### And/Or
368
+
369
+ ```lits
370
+ // Logical AND (short-circuit)
371
+ true && "second value"; // => "second value"
372
+ false && "never reached"; // => false
373
+
374
+ // Logical OR (short-circuit)
375
+ false || "default value"; // => "default value"
376
+ true || "never reached"; // => true
377
+
378
+ // Multiple arguments
379
+ &&(true, true, "all true"); // => "all true"
380
+ ||(false, false, "found"); // => "found"
191
381
  ```
192
382
 
193
- ### Destructuring
383
+ #### Null Coalescing
194
384
 
385
+ ```lits
386
+ // Null coalescing operator
387
+ null ?? "default"; // => "default"
388
+ undefined ?? "default"; // => "default"
389
+ 0 ?? "default"; // => 0 (only null/undefined are coalesced)
390
+ false ?? "default"; // => false
391
+ "" ?? "default"; // => ""
195
392
  ```
196
- // Object destructuring
197
- let { name, age } = { name: "John", age: 30 };
198
- // name => "John"
199
- // age => 30
200
393
 
201
- // Array destructuring
202
- let [nbr1, nbr2] = [1, 2, 3, 4];
203
- // nbr1 => 1
204
- // nbr2 => 2
394
+ ### Blocks
205
395
 
206
- // Destructuring in function parameters
207
- let displayPerson = ({name, age}) ->
208
- name ++ " is " ++ str(age) ++ " years old";
396
+ ```lits
397
+ // Block expressions
398
+ {
399
+ let a = 1 + 2 + 3;
400
+ let b = x -> x * x;
401
+ b(a)
402
+ }
403
+ // => 36 (returns value of last expression)
404
+ ```
209
405
 
210
- displayPerson({ name: "John", age: 30 });
211
- // => "John is 30 years old"
406
+ ### Arrays and Objects
407
+
408
+ #### Array Construction
409
+
410
+ ```lits
411
+ // Array literal
412
+ [1, 2, 3, 4];
413
+
414
+ // Array function
415
+ array(1, 2, 3, 4);
416
+
417
+ // With spread
418
+ let small-set = [3, 4, 5];
419
+ [1, 2, ...small-set, 6];
420
+ // => [1, 2, 3, 4, 5, 6];
421
+ ```
422
+
423
+ #### Object Construction
424
+
425
+ ```lits
426
+ // Object literal
427
+ { name: "John", age: 30 };
428
+
429
+ // Object function
430
+ object("name", "John", "age", 30);
431
+
432
+ // With spread
433
+ let defaults = { type: "Person", active: true };
434
+ {
435
+ ...defaults,
436
+ name: "John",
437
+ age: 30
438
+ };
439
+ // => { type: "Person", active: true, name: "John", age: 30 }
440
+ ```
441
+
442
+ ### Recursion
443
+
444
+ #### Recur
445
+
446
+ ```lits
447
+ // Tail recursion with recur
448
+ let countdown = n -> {
449
+ write!(n);
450
+ if pos?(n) then
451
+ recur(n - 1)
452
+ end
453
+ };
454
+
455
+ countdown(3)
456
+ // Prints: 3 2 1 0
212
457
  ```
213
458
 
214
459
  ## Operators and Functions
215
460
 
216
- ### Function Usage vs Operator Usage
461
+ ### Algebraic Notation
217
462
 
218
463
  All functions that take two parameters can be used as operators:
219
464
 
220
- ```
465
+ ```lits
221
466
  // As a function
222
- max(5, 10);
223
- // => 10
467
+ max(5, 10); // => 10
224
468
 
225
469
  // As an operator
226
- 5 max 10;
227
- // => 10
470
+ 5 max 10; // => 10
228
471
  ```
229
472
 
230
473
  All operators can be used as functions:
231
474
 
232
- ```
475
+ ```lits
233
476
  // As an operator
234
- 5 + 3;
235
- // => 8
477
+ 5 + 3; // => 8
236
478
 
237
479
  // As a function
238
- +(5, 3);
239
- // => 8
240
- ```
480
+ +(5, 3); // => 8
241
481
 
242
- ### Parameter Order
482
+ // Partial application with underscore placeholder
483
+ let add5 = +(5, _);
484
+ add5(3); // => 8
243
485
 
244
- Lits favors subject-first parameter order:
486
+ // Multiple placeholders
487
+ let subtractTwoValues = -(100, _, _);
488
+ subtractTwoValues(4, 3); // => 93
245
489
 
246
- ```
247
- // Lits
248
- filter([1, 2, 3, 4], odd?);
249
- // => [1, 3]
490
+ // Single placeholder in different positions
491
+ let subtract = -(_, 2);
492
+ subtract(10); // => 8
250
493
 
251
- // Unlike for example Clojure
252
- // (filter odd? [1 2 3 4])
494
+ let divide = /(10, _);
495
+ divide(2); // => 5
253
496
  ```
254
497
 
255
- This makes operator usage more readable:
498
+ ### Parameter Order
256
499
 
257
- ```
258
- [1, 2, 3, 4] filter odd?;
259
- // => [1, 3]
260
- ```
500
+ Lits favors subject-first parameter order for better operator chaining:
261
501
 
262
- ## Built-in Functions
502
+ ```lits
503
+ // Function style
504
+ filter([1, 2, 3, 4], odd?); // => [1, 3]
263
505
 
264
- Lits comes with a comprehensive standard library of functions organized into categories:
506
+ // Operator style (more readable)
507
+ [1, 2, 3, 4] filter odd?; // => [1, 3]
508
+ ```
265
509
 
266
- ### Collection Functions
267
- `count`, `get`, `get-in`, `contains?`, `assoc`, `assoc-in`, `++`, `not-empty`, `every?`, `not-every?`, `any?`, `not-any?`, `update`, `update-in`
510
+ ### Pipe Operator
268
511
 
269
- ### Array Functions
270
- `array`, `range`, `repeat`, `flatten`, `mapcat`
512
+ The pipe operator `|>` passes the result of the left expression as the first argument to the right function:
271
513
 
272
- ### Sequence Functions
273
- `nth`, `push`, `pop`, `unshift`, `shift`, `slice`, `splice`, `reductions`, `reduce`, `reduce-right`, `map`, `filter`, `position`, `index-of`, `last-index-of`, `some`, `reverse`, `first`, `second`, `last`, `rest`, `next`, `take`, `take-last`, `take-while`, `drop`, `drop-last`, `drop-while`, `sort`, `sort-by`, `distinct`, `remove`, `remove-at`, `split-at`, `split-with`, `frequencies`, `group-by`, `partition`, `partition-all`, `partition-by`, `starts-with?`, `ends-with?`, `interleave`, `interpose`
514
+ ```lits
515
+ // Without pipe operator
516
+ reduce(map(filter([1, 2, 3, 4, 5, 6], odd?), -> $ + $), +, 0);
274
517
 
275
- ### Math Functions
276
- `+`, `-`, `*`, `/`, `mod`, `%`, `quot`, `inc`, `dec`, `√`, `∛`, `**`, `round`, `trunc`, `floor`, `ceil`, `min`, `max`, `abs`, `sign`, `log`, `log2`, `log10`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`
518
+ // With pipe operator (much more readable)
519
+ [1, 2, 3, 4, 5, 6]
520
+ |> filter(_, odd?)
521
+ |> map(_, -> $ * $)
522
+ |> reduce(_, +, 0);
523
+ // => 35
277
524
 
278
- ### Functional Programming
279
- `apply`, `identity`, `partial`, `comp`, `constantly`, `juxt`, `complement`, `every-pred`, `some-pred`, `fnull`
525
+ // Simple transformations
526
+ "hello world"
527
+ |> upper-case
528
+ |> split(_, " ")
529
+ |> reverse
530
+ |> join(_, "-");
531
+ // => "WORLD-HELLO"
280
532
 
281
- ### Object Functions
282
- `dissoc`, `object`, `keys`, `vals`, `entries`, `find`, `merge`, `merge-with`, `zipmap`, `select-keys`
533
+ // Mathematical operations
534
+ 10
535
+ |> +(_, 5)
536
+ |> *(_, 2)
537
+ |> /(_, 3);
538
+ // => 10 (10 + 5 = 15, 15 * 2 = 30, 30 / 3 = 10)
283
539
 
284
- ### String Functions
285
- `string-repeat`, `str`, `number`, `lower-case`, `upper-case`, `trim`, `trim-left`, `trim-right`, `pad-left`, `pad-right`, `split`, `split-lines`, `template`, `to-char-code`, `from-char-code`, `encode-base64`, `decode-base64`, `encode-uri-component`, `decode-uri-component`, `join`, `capitalize`, `blank?`
540
+ // Data processing pipeline
541
+ { numbers: [1, 2, 3, 4, 5], multiplier: 3 }
542
+ |> get(_, "numbers")
543
+ |> filter(_, even?)
544
+ |> map(_, *(_, 3))
545
+ |> reduce(_, +, 0);
546
+ // => 18 (even numbers [2, 4] -> [6, 12] -> sum = 18)
547
+ ```
286
548
 
287
- ### Predicates
288
- `boolean?`, `null?`, `number?`, `string?`, `function?`, `integer?`, `array?`, `object?`, `coll?`, `seq?`, `regexp?`, `zero?`, `pos?`, `neg?`, `even?`, `odd?`, `finite?`, `nan?`, `negative-infinity?`, `positive-infinity?`, `false?`, `true?`, `empty?`, `not-empty?`
549
+ ## Built-in Functions
289
550
 
290
- ### Regular Expressions
291
- `regexp`, `match`, `replace`, `replace-all`
551
+ Lits comes with a comprehensive standard library of functions for:
292
552
 
293
- ### Bitwise Operations
294
- `<<`, `>>`, `>>>`, `~`, `&`, `bit-and-not`, `|`, `^`, `bit-flip`, `bit-clear`, `bit-set`, `bit-test`
553
+ - **Arithmetic and Math**: Basic operations, trigonometry, logarithms, rounding
554
+ - **Collections**: Working with arrays and objects (get, assoc, merge, etc.)
555
+ - **Sequences**: Filtering, mapping, reducing, sorting, and transforming data
556
+ - **Strings**: Manipulation, formatting, encoding, and pattern matching
557
+ - **Predicates**: Type checking and condition testing functions
558
+ - **Functional Programming**: Function composition, partial application, and utilities
559
+ - **Regular Expressions**: Pattern matching and text processing
560
+ - **Bitwise Operations**: Low-level bit manipulation
561
+ - **Assertions**: Testing and validation utilities
295
562
 
296
- ### Assertions
297
- `assert`, `assert=`, `assert!=`, `assert-gt`, `assert-lt`, `assert-gte`, `assert-lte`, `assert-true`, `assert-false`, `assert-truthy`, `assert-falsy`, `assert-null`, `assert-throws`, `assert-throws-error`, `assert-not-throws`
563
+ For a complete reference of all available functions with examples, visit the [Lits Playground](https://mojir.github.io/lits/) where you can explore the interactive documentation and try functions in real-time.
298
564
 
299
565
  ## Modules and Exports
300
566
 
301
- You can export definitions to make them available to other modules:
302
-
303
- ```
304
- // Exporting variables
305
- export let magic-number = 42;
306
- // => 42
307
-
308
- // Exporting functions
567
+ ```lits
568
+ // Export variables and functions
569
+ export let pi = 3.14159;
309
570
  export let square = x -> x * x;
310
- ```
311
-
312
- ## API
313
-
314
- Lits provides a JavaScript API for embedding:
315
571
 
316
- ```javascript
317
- interface Lits {
318
- getRuntimeInfo: () => LitsRuntimeInfo
319
- run: (program: string, params?: ContextParams & FilePathParams) => unknown
320
- context: (programOrAst: string | Ast, params?: ContextParams & FilePathParams) => Context
321
- getUndefinedSymbols: (programOrAst: string | Ast, params: ContextParams) => Set<string>
322
- tokenize: (program: string, tokenizeParams: FilePathParams & MinifyParams) => TokenStream
323
- parse: (tokenStream: TokenStream) => Ast
324
- evaluate: (ast: Ast, params: ContextParams) => unknown
325
- transformSymbols: (tokenStream: TokenStream, transformer: (symbol: string) => string) => TokenStream
326
- untokenize: (tokenStream: TokenStream) => string
327
- apply: (fn: LitsFunction, fnParams: unknown[], params: ContextParams) => unknown
328
- }
572
+ // Exported values become available to other modules
329
573
  ```
330
574
 
331
575
  ## Examples
332
576
 
333
- ### Factorial Function
577
+ ### Factorial
334
578
 
335
- ```
336
- let factorial = (n) ->
579
+ ```lits
580
+ let factorial = n ->
337
581
  if n <= 1 then
338
582
  1
339
583
  else
340
- n * self(n - 1);
584
+ n * self(n - 1)
585
+ end;
341
586
 
342
- factorial(5);
343
- // => 120
587
+ factorial(5) // => 120
344
588
  ```
345
589
 
346
- ### Fibonacci Sequence
590
+ ### Array Processing
591
+
592
+ ```lits
593
+ let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
594
+
595
+ // Get even numbers squared
596
+ let evenSquares = numbers
597
+ |> filter(_, even?)
598
+ |> map(_, -> $ * $);
599
+ // => [4, 16, 36, 64, 100]
347
600
 
601
+ // Sum of odd numbers
602
+ let oddSum = numbers
603
+ |> filter(_, odd?)
604
+ |> reduce(_, +, 0);
605
+ // => 25
348
606
  ```
349
- let fib = n ->
350
- if n < 2 then
351
- n
352
- else
353
- self(n - 1) + fib(n - 2)
354
607
 
355
- // Generate the first 10 Fibonacci numbers
356
- range(10) map fib;
357
- // => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
608
+ ### Object Manipulation
609
+
610
+ ```lits
611
+ let person = { name: "John", age: 30, city: "New York" };
612
+
613
+ // Update age
614
+ let older = assoc(person, "age", 31);
615
+
616
+ // Add new field
617
+ let withJob = assoc(older, "job", "Developer");
618
+
619
+ // Using pipe operator for chaining
620
+ let updated = person
621
+ |> assoc(_, "age", 31)
622
+ |> assoc(_, "job", "Developer");
358
623
  ```
359
624
 
360
- ### Working with Collections
625
+ ### Pattern Matching Examples
626
+
627
+ #### Switch (for matching against a single value)
628
+
629
+ ```lits
630
+ let gradeToLetter = grade ->
631
+ switch grade
632
+ case 90 then "A"
633
+ case 80 then "B"
634
+ case 70 then "C"
635
+ case 60 then "D"
636
+ end ?? "F";
361
637
 
638
+ gradeToLetter(80); // => "B"
639
+ gradeToLetter(55); // => "F"
640
+
641
+ // HTTP status code handling
642
+ let statusMessage = code ->
643
+ switch code
644
+ case 200 then "OK"
645
+ case 404 then "Not Found"
646
+ case 500 then "Internal Server Error"
647
+ end ?? "Unknown Status";
362
648
  ```
363
- let people = [
364
- { name: "Alice", age: 25 },
365
- { name: "Bob", age: 30 },
366
- { name: "Charlie", age: 35 },
367
- { name: "Diana", age: 40 }
368
- ];
369
649
 
370
- // Get all names
371
- people map (p -> p.name);
372
- // => ["Alice", "Bob", "Charlie", "Diana"]
650
+ #### Cond (for testing different conditions)
651
+
652
+ ```lits
653
+ let describe = x ->
654
+ cond
655
+ case null?(x) then "nothing"
656
+ case number?(x) then "a number: " ++ str(x)
657
+ case string?(x) then "text: " ++ x
658
+ case array?(x) then "list of " ++ str(count(x)) ++ " items"
659
+ end ?? "unknown type";
660
+
661
+ describe(42); // => "a number: 42"
662
+ describe([1,2,3]); // => "list of 3 items"
373
663
 
374
- // Get people older than 30
375
- people filter (p -> p.age > 30);
376
- // => [{ name: "Charlie", age: 35 }, { name: "Diana", age: 40 }]
664
+ // Grade ranges
665
+ let gradeToLetter = score ->
666
+ cond
667
+ case score >= 90 then "A"
668
+ case score >= 80 then "B"
669
+ case score >= 70 then "C"
670
+ case score >= 60 then "D"
671
+ end ?? "F";
377
672
 
378
- // Calculate average age
379
- (people map (p -> p.age) reduce +) / count(people);
380
- // => 32.5
673
+ gradeToLetter(85); // => "B"
674
+ gradeToLetter(55); // => "F"
381
675
  ```
382
676
 
383
- ## Contributing
677
+ ## JavaScript Interoperability
678
+
679
+ Lits provides a comprehensive JavaScript API for embedding and integration:
680
+
681
+ ```javascript
682
+ import { Lits } from 'lits';
683
+
684
+ // Create a Lits instance
685
+ const lits = new Lits();
686
+
687
+ // Run Lits code
688
+ const result = lits.run('+(5, 3)');
689
+ console.log(result); // 8
690
+
691
+ // Pass JavaScript values to Lits
692
+ const result2 = lits.run('name ++ " is " ++ str(age)', {
693
+ values: {
694
+ name: "John",
695
+ age: 30
696
+ }
697
+ });
698
+ console.log(result2); // "John is 30"
699
+
700
+ // Expose JavaScript functions to Lits
701
+ const result3 = lits.run('myAlert("Hello from Lits!")', {
702
+ jsFunctions: {
703
+ myAlert: {
704
+ fn: (message) => console.log(`Alert: ${message}`),
705
+ arity: { min: 1, max: 1 }
706
+ }
707
+ }
708
+ });
709
+
710
+ // Parse and evaluate separately for better performance
711
+ const tokens = lits.tokenize('+(5, 3)');
712
+ const ast = lits.parse(tokens);
713
+ const result4 = lits.evaluate(ast, {});
714
+ ```
715
+
716
+ ### Lits Class Methods
717
+
718
+ ```typescript
719
+ interface Lits {
720
+ // Execute Lits code directly
721
+ run(program: string, params?: ContextParams & FilePathParams): unknown
722
+
723
+ // Get execution context after running code
724
+ context(programOrAst: string | Ast, params?: ContextParams & FilePathParams): Context
725
+
726
+ // Find undefined symbols in code
727
+ getUndefinedSymbols(programOrAst: string | Ast, params?: ContextParams): Set<string>
728
+
729
+ // Parse pipeline
730
+ tokenize(program: string, params?: FilePathParams & MinifyParams): TokenStream
731
+ parse(tokenStream: TokenStream): Ast
732
+ evaluate(ast: Ast, params: ContextParams): unknown
733
+
734
+ // Apply Lits function with JavaScript arguments
735
+ apply(fn: LitsFunction, fnParams: unknown[], params?: ContextParams): unknown
736
+
737
+ // Utility methods
738
+ transformSymbols(tokenStream: TokenStream, transformer: (symbol: string) => string): TokenStream
739
+ untokenize(tokenStream: TokenStream): string
740
+ getRuntimeInfo(): LitsRuntimeInfo
741
+ }
742
+ ```
743
+
744
+ ### Context Parameters
745
+
746
+ ```typescript
747
+ interface ContextParams {
748
+ globalContext?: Context // Global variable context
749
+ contexts?: Context[] // Additional context layers
750
+ values?: Record<string, unknown> // JavaScript values to expose
751
+ jsFunctions?: Record<string, JsFunction> // JavaScript functions to expose
752
+ globalModuleScope?: boolean // Module scoping behavior
753
+ }
754
+
755
+ interface JsFunction {
756
+ fn: (...args: any[]) => unknown // The JavaScript function
757
+ arity?: Arity // Function arity constraints
758
+ docString?: string // Documentation
759
+ }
760
+ ```
384
761
 
385
- *[Add contribution guidelines here]*
762
+ ## Learn More
386
763
 
387
- ## License
764
+ - Try Lits in the [online playground](https://mojir.github.io/lits/)
765
+ - Explore the comprehensive function reference
766
+ - Check out more complex examples in the documentation
388
767
 
389
- *[Add license information here]*
768
+ Lits combines the elegance of functional programming with practical syntax, making it perfect for data transformation, mathematical computation, and any scenario where immutability and expressiveness are valued.