@mojir/dvala 0.0.30 → 0.0.32
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 +145 -218
- package/dist/cli/cli.js +5831 -5927
- package/package.json +1 -6
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ $ dvala
|
|
|
41
41
|
|
|
42
42
|
# Evaluate Dvala code directly
|
|
43
43
|
$ dvala eval "5 + 3"
|
|
44
|
-
$ dvala eval "[1, 2, 3, 4] filter
|
|
44
|
+
$ dvala eval "[1, 2, 3, 4] filter isOdd map inc"
|
|
45
45
|
|
|
46
46
|
# Run a Dvala file
|
|
47
47
|
$ dvala run script.dvala
|
|
@@ -184,7 +184,7 @@ rest(numbers); // => [2, 3, 4, 5]
|
|
|
184
184
|
|
|
185
185
|
// Functional array operations
|
|
186
186
|
numbers map -> $ * 2; // => [2, 4, 6, 8, 10]
|
|
187
|
-
numbers filter
|
|
187
|
+
numbers filter isOdd; // => [1, 3, 5]
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
#### Vectors (Number Arrays)
|
|
@@ -194,7 +194,7 @@ A vector is simply a non-empty array containing only numbers. The `vec` module p
|
|
|
194
194
|
```dvala
|
|
195
195
|
// Import vector and linear algebra modules
|
|
196
196
|
let vec = import(vector);
|
|
197
|
-
let lin = import(
|
|
197
|
+
let lin = import(linearAlgebra);
|
|
198
198
|
|
|
199
199
|
// Vectors are just number arrays
|
|
200
200
|
[1, 2, 3, 4, 5]; // This is a vector
|
|
@@ -210,30 +210,30 @@ repeat(3.14, 4); // => [3.14, 3.14, 3.14, 3.14]
|
|
|
210
210
|
|
|
211
211
|
// Vector mathematical operations (use lin module for vector math)
|
|
212
212
|
lin.dot([1, 2, 3], [4, 5, 6]); // => 32 (dot product)
|
|
213
|
-
lin.
|
|
214
|
-
lin.
|
|
215
|
-
lin.
|
|
216
|
-
|
|
217
|
-
// Vector statistical operations (
|
|
218
|
-
sum([1, 2, 3, 4]);
|
|
219
|
-
mean([1, 2, 3, 4]);
|
|
220
|
-
median([1, 2, 3, 4, 5]);
|
|
213
|
+
lin.euclideanNorm([3, 4]); // => 5.0 (Euclidean norm/magnitude)
|
|
214
|
+
lin.normalizeL2([3, 4]); // => [0.6, 0.8] (unit vector)
|
|
215
|
+
lin.euclideanDistance([0, 0], [3, 4]); // => 5.0 (Euclidean distance)
|
|
216
|
+
|
|
217
|
+
// Vector statistical operations (in the vector module)
|
|
218
|
+
vec.sum([1, 2, 3, 4]); // => 10
|
|
219
|
+
vec.mean([1, 2, 3, 4]); // => 2.5
|
|
220
|
+
vec.median([1, 2, 3, 4, 5]); // => 3
|
|
221
221
|
vec.stdev([1, 2, 3, 4]); // => 1.29... (standard deviation)
|
|
222
222
|
vec.variance([1, 2, 3, 4]); // => 1.67... (variance)
|
|
223
223
|
|
|
224
224
|
// Vector analysis (min and max are core built-ins)
|
|
225
225
|
min([3, 1, 4, 1, 5]); // => 1
|
|
226
226
|
max([3, 1, 4, 1, 5]); // => 5
|
|
227
|
-
vec.
|
|
228
|
-
vec.
|
|
227
|
+
vec.minIndex([3, 1, 4]); // => 1 (index of minimum)
|
|
228
|
+
vec.maxIndex([3, 1, 4]); // => 2 (index of maximum)
|
|
229
229
|
|
|
230
230
|
// Cumulative operations
|
|
231
231
|
vec.cumsum([1, 2, 3, 4]); // => [1, 3, 6, 10]
|
|
232
232
|
vec.cumprod([1, 2, 3, 4]); // => [1, 2, 6, 24]
|
|
233
233
|
|
|
234
234
|
// Vector predicates
|
|
235
|
-
vec.
|
|
236
|
-
vec.
|
|
235
|
+
vec.isIncreasing([1, 1, 2, 3, 4]); // => true
|
|
236
|
+
vec.isStrictlyIncreasing([1, 1, 2, 3, 4]); // => false
|
|
237
237
|
|
|
238
238
|
// Structural equality works with all vectors
|
|
239
239
|
[1, 2, 3] == [1, 2, 3]; // => true
|
|
@@ -270,20 +270,20 @@ mat.vandermonde([1, 2, 3]); // => Vandermonde matrix from vector
|
|
|
270
270
|
mat.band(4, 1, 1); // => 4x4 band matrix
|
|
271
271
|
|
|
272
272
|
// Matrix properties and predicates
|
|
273
|
-
mat.
|
|
274
|
-
mat.
|
|
275
|
-
mat.
|
|
276
|
-
mat.
|
|
277
|
-
mat.
|
|
273
|
+
mat.isSymmetric([[1, 2], [2, 1]]); // => true
|
|
274
|
+
mat.isInvertible([[1, 2], [3, 4]]); // => true
|
|
275
|
+
mat.isSquare([[1, 2], [3, 4]]); // => true
|
|
276
|
+
mat.isDiagonal([[1, 0], [0, 2]]); // => true
|
|
277
|
+
mat.isIdentity([[1, 0], [0, 1]]); // => true
|
|
278
278
|
|
|
279
279
|
// Advanced matrix operations
|
|
280
280
|
mat.adj(matrixA); // => [[4, -2], [-3, 1]] (adjugate)
|
|
281
281
|
mat.cofactor(matrixA); // => cofactor matrix
|
|
282
282
|
mat.minor(matrixA, 0, 1); // => minor by removing row 0, col 1
|
|
283
|
-
mat.
|
|
284
|
-
mat.
|
|
285
|
-
mat.
|
|
286
|
-
mat.
|
|
283
|
+
mat.frobeniusNorm(matrixA); // => Frobenius norm
|
|
284
|
+
mat.oneNorm(matrixA); // => 1-norm (max column sum)
|
|
285
|
+
mat.infNorm(matrixA); // => infinity norm (max row sum)
|
|
286
|
+
mat.maxNorm(matrixA); // => max norm (largest absolute element)
|
|
287
287
|
|
|
288
288
|
// Matrix analysis
|
|
289
289
|
mat.rank(matrixA); // => matrix rank
|
|
@@ -320,33 +320,33 @@ Dvala provides predicate functions to check data types at runtime:
|
|
|
320
320
|
|
|
321
321
|
```dvala
|
|
322
322
|
// Basic type predicates
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
323
|
+
isNumber(42); // => true
|
|
324
|
+
isString("hello"); // => true
|
|
325
|
+
isBoolean(true); // => true
|
|
326
|
+
isFunction(x -> x * 2); // => true
|
|
327
|
+
isRegexp(#"[a-z]+"); // => true
|
|
328
|
+
isArray([1, 2, 3]); // => true
|
|
329
|
+
isObject({name: "Alice"}); // => true
|
|
330
|
+
isNull(null); // => true
|
|
331
331
|
|
|
332
332
|
// Specialized array predicates
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
333
|
+
isVector([1, 2, 3]); // => true (non-empty number array)
|
|
334
|
+
isVector([1, "hello", 3]); // => false (mixed types)
|
|
335
|
+
isVector([]); // => false (empty)
|
|
336
336
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
337
|
+
isMatrix([[1, 2], [3, 4]]); // => true (2D number array, consistent rows)
|
|
338
|
+
isMatrix([[1, 2], [3]]); // => false (inconsistent row lengths)
|
|
339
|
+
isMatrix([[]]); // => false (contains empty row)
|
|
340
340
|
|
|
341
341
|
// Collection predicates
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
isSequence([1, 2, 3]); // => true (sequences: strings and arrays)
|
|
343
|
+
isSequence("hello"); // => true
|
|
344
|
+
isSequence({a: 1}); // => false
|
|
345
345
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
346
|
+
isCollection([1, 2, 3]); // => true (collections: strings, arrays, objects)
|
|
347
|
+
isCollection("hello"); // => true
|
|
348
|
+
isCollection({a: 1}); // => true
|
|
349
|
+
isCollection(42); // => false
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
#### Type Hierarchy
|
|
@@ -356,19 +356,19 @@ The type predicates follow a logical hierarchy:
|
|
|
356
356
|
```dvala
|
|
357
357
|
// If something is a matrix, it's also a vector and an array
|
|
358
358
|
let mat = [[1, 2], [3, 4]];
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
359
|
+
isMatrix(mat); // => true
|
|
360
|
+
isVector(mat); // => true (matrix is a special vector)
|
|
361
|
+
isArray(mat); // => true (vector is a special array)
|
|
362
362
|
|
|
363
363
|
// If something is a vector, it's also an array
|
|
364
364
|
let vec = [1, 2, 3];
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
isVector(vec); // => true
|
|
366
|
+
isArray(vec); // => true
|
|
367
367
|
|
|
368
368
|
// But not all arrays are vectors
|
|
369
369
|
let arr = [1, "hello", 3];
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
isArray(arr); // => true
|
|
371
|
+
isVector(arr); // => false (contains non-numbers)
|
|
372
372
|
```
|
|
373
373
|
|
|
374
374
|
Each data type is immutable by design - operations return new values rather than modifying existing ones, ensuring predictable behavior and easier reasoning about code.
|
|
@@ -379,15 +379,11 @@ Dvala provides predefined mathematical constants:
|
|
|
379
379
|
|
|
380
380
|
```dvala
|
|
381
381
|
PI; // => 3.141592653589793
|
|
382
|
-
π; // => 3.141592653589793 (Unicode alternative)
|
|
383
382
|
E; // => 2.718281828459045 (Euler's number)
|
|
384
|
-
ε; // => 2.718281828459045 (Unicode alternative)
|
|
385
383
|
PHI; // => 1.618033988749895 (Golden ratio)
|
|
386
|
-
φ; // => 1.618033988749895 (Unicode alternative)
|
|
387
384
|
|
|
388
385
|
// Infinity values
|
|
389
386
|
POSITIVE_INFINITY; // => Infinity
|
|
390
|
-
∞; // => Infinity (Unicode alternative)
|
|
391
387
|
NEGATIVE_INFINITY; // => -Infinity
|
|
392
388
|
|
|
393
389
|
// Integer and float limits
|
|
@@ -562,10 +558,10 @@ let square = x -> x * x;
|
|
|
562
558
|
let constant = () -> 42;
|
|
563
559
|
|
|
564
560
|
// Positional arguments
|
|
565
|
-
let
|
|
561
|
+
let addV2 = -> $ + $2;
|
|
566
562
|
|
|
567
563
|
// Single positional argument
|
|
568
|
-
let
|
|
564
|
+
let squareV2 = -> $ * $;
|
|
569
565
|
|
|
570
566
|
// Self-reference for recursion
|
|
571
567
|
let factorial = n ->
|
|
@@ -578,7 +574,7 @@ let factorial = n ->
|
|
|
578
574
|
|
|
579
575
|
### Control Flow
|
|
580
576
|
|
|
581
|
-
#### If
|
|
577
|
+
#### If
|
|
582
578
|
|
|
583
579
|
```dvala
|
|
584
580
|
let x = 15; // Fixed value for compilation
|
|
@@ -594,9 +590,9 @@ end;
|
|
|
594
590
|
if false then "never" end;
|
|
595
591
|
// => null
|
|
596
592
|
|
|
597
|
-
//
|
|
593
|
+
// Negated condition
|
|
598
594
|
let y = 8;
|
|
599
|
-
|
|
595
|
+
if not(y > 10) then
|
|
600
596
|
"small"
|
|
601
597
|
else
|
|
602
598
|
"large"
|
|
@@ -604,28 +600,26 @@ end;
|
|
|
604
600
|
// => "small"
|
|
605
601
|
```
|
|
606
602
|
|
|
607
|
-
####
|
|
603
|
+
#### If / Else If
|
|
608
604
|
|
|
609
605
|
```dvala
|
|
610
606
|
let x = 12;
|
|
611
607
|
|
|
612
608
|
// Multi-branch conditional
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
case true then "extra large" // default case
|
|
609
|
+
if x < 5 then "small"
|
|
610
|
+
else if x < 10 then "medium"
|
|
611
|
+
else if x < 15 then "large"
|
|
612
|
+
else "extra large" // default case
|
|
618
613
|
end;
|
|
619
614
|
// => "large"
|
|
620
615
|
|
|
621
|
-
//
|
|
616
|
+
// If/else if with complex conditions
|
|
622
617
|
let urgent = true;
|
|
623
618
|
let important = false;
|
|
624
|
-
let priority =
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
case true then "low"
|
|
619
|
+
let priority = if urgent && important then "critical"
|
|
620
|
+
else if urgent then "high"
|
|
621
|
+
else if important then "medium"
|
|
622
|
+
else "low"
|
|
629
623
|
end;
|
|
630
624
|
// => "high"
|
|
631
625
|
```
|
|
@@ -667,7 +661,7 @@ for (x in [1, 2, 3, 4]) -> x * 2;
|
|
|
667
661
|
// => [2, 4, 6, 8]
|
|
668
662
|
|
|
669
663
|
// With filtering (when clause)
|
|
670
|
-
for (x in [1, 2, 3, 4] when
|
|
664
|
+
for (x in [1, 2, 3, 4] when isOdd(x)) -> x * 2;
|
|
671
665
|
// => [2, 6]
|
|
672
666
|
|
|
673
667
|
// With early termination (while clause)
|
|
@@ -701,12 +695,12 @@ for (entry in { a: 1, b: 2 } let [key, value] = entry) -> key ++ ":" ++ str(valu
|
|
|
701
695
|
// => ["a:1", "b:2"]
|
|
702
696
|
```
|
|
703
697
|
|
|
704
|
-
####
|
|
698
|
+
#### For with Side Effects
|
|
705
699
|
|
|
706
700
|
```dvala
|
|
707
|
-
// For
|
|
708
|
-
|
|
709
|
-
// Prints: 1 2 3, returns null
|
|
701
|
+
// For can also be used for side effects
|
|
702
|
+
for (x in [1, 2, 3]) -> perform(@dvala.io.print, x)
|
|
703
|
+
// Prints: 1 2 3, returns [null, null, null]
|
|
710
704
|
```
|
|
711
705
|
|
|
712
706
|
#### Loop (Tail Recursion)
|
|
@@ -714,7 +708,7 @@ doseq (x in [1, 2, 3]) -> perform(effect(dvala.io.println), x)
|
|
|
714
708
|
```dvala
|
|
715
709
|
// Loop with recur for tail recursion
|
|
716
710
|
loop (n = 5, acc = 1) -> do
|
|
717
|
-
if
|
|
711
|
+
if isZero(n) then
|
|
718
712
|
acc
|
|
719
713
|
else
|
|
720
714
|
recur(n - 1, acc * n)
|
|
@@ -724,7 +718,7 @@ end;
|
|
|
724
718
|
|
|
725
719
|
// Complex loop with multiple variables
|
|
726
720
|
loop (items = [1, 2, 3, 4, 5], acc = 0, cnt = 0) -> do
|
|
727
|
-
if
|
|
721
|
+
if isEmpty(items) then
|
|
728
722
|
{ sum: acc, average: acc / cnt }
|
|
729
723
|
else
|
|
730
724
|
recur(rest(items), acc + first(items), cnt + 1)
|
|
@@ -748,7 +742,7 @@ end;
|
|
|
748
742
|
|
|
749
743
|
// Tail-recursive function
|
|
750
744
|
let sumToN = (n, acc = 0) -> do
|
|
751
|
-
if
|
|
745
|
+
if isZero(n) then
|
|
752
746
|
acc
|
|
753
747
|
else
|
|
754
748
|
recur(n - 1, acc + n)
|
|
@@ -758,59 +752,66 @@ end;
|
|
|
758
752
|
|
|
759
753
|
### Error Handling
|
|
760
754
|
|
|
761
|
-
####
|
|
755
|
+
#### Handle/With Effect Handlers
|
|
762
756
|
|
|
763
757
|
```dvala
|
|
764
|
-
// Basic error handling with
|
|
765
|
-
let riskyOperation = () -> perform(
|
|
766
|
-
|
|
758
|
+
// Basic error handling with handle/with
|
|
759
|
+
let riskyOperation = () -> perform(@dvala.error, "Something went wrong");
|
|
760
|
+
handle
|
|
767
761
|
riskyOperation()
|
|
768
|
-
with
|
|
769
|
-
|
|
770
|
-
|
|
762
|
+
with [(arg, eff, nxt) ->
|
|
763
|
+
if eff == @dvala.error then "Something went wrong"
|
|
764
|
+
else nxt(eff, arg)
|
|
765
|
+
end
|
|
766
|
+
] end;
|
|
771
767
|
|
|
772
768
|
// With error message binding
|
|
773
|
-
|
|
769
|
+
handle
|
|
774
770
|
riskyOperation()
|
|
775
|
-
with
|
|
776
|
-
|
|
777
|
-
|
|
771
|
+
with [(arg, eff, nxt) ->
|
|
772
|
+
if eff == @dvala.error then "Error: " ++ arg
|
|
773
|
+
else nxt(eff, arg)
|
|
774
|
+
end
|
|
775
|
+
] end;
|
|
778
776
|
|
|
779
777
|
// Error handling for graceful degradation
|
|
780
778
|
let parseData = () -> { value: 42 };
|
|
781
779
|
let process = (val) -> val * 2;
|
|
782
|
-
|
|
780
|
+
handle
|
|
783
781
|
let { value } = parseData();
|
|
784
782
|
process(value)
|
|
785
|
-
with
|
|
786
|
-
|
|
787
|
-
|
|
783
|
+
with [(arg, eff, nxt) ->
|
|
784
|
+
if eff == @dvala.error then "Using default value"
|
|
785
|
+
else nxt(eff, arg)
|
|
786
|
+
end
|
|
787
|
+
] end;
|
|
788
788
|
```
|
|
789
789
|
|
|
790
790
|
#### Raising Errors
|
|
791
791
|
|
|
792
792
|
```dvala
|
|
793
793
|
// Raising errors
|
|
794
|
-
|
|
795
|
-
perform(
|
|
796
|
-
with
|
|
797
|
-
|
|
798
|
-
|
|
794
|
+
handle
|
|
795
|
+
perform(@dvala.error, "Custom error message")
|
|
796
|
+
with [(arg, eff, nxt) ->
|
|
797
|
+
if eff == @dvala.error then "Caught an error"
|
|
798
|
+
else nxt(eff, arg)
|
|
799
|
+
end
|
|
800
|
+
] end;
|
|
799
801
|
|
|
800
802
|
// Custom error messages in functions
|
|
801
803
|
let divide = (a, b) ->
|
|
802
|
-
if
|
|
803
|
-
perform(
|
|
804
|
+
if isZero(b) then
|
|
805
|
+
perform(@dvala.error, "Cannot divide by zero")
|
|
804
806
|
else
|
|
805
807
|
a / b
|
|
806
808
|
end;
|
|
807
809
|
|
|
808
810
|
// Conditional error raising
|
|
809
811
|
let validateAge = (age) ->
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
case true then age
|
|
812
|
+
if age < 0 then perform(@dvala.error, "Age cannot be negative")
|
|
813
|
+
else if age > 150 then perform(@dvala.error, "Age seems unrealistic")
|
|
814
|
+
else age
|
|
814
815
|
end;
|
|
815
816
|
```
|
|
816
817
|
|
|
@@ -834,10 +835,10 @@ let loadData = () -> [1, 2, 3];
|
|
|
834
835
|
let processData = (data) -> data map -> $ * 2;
|
|
835
836
|
|
|
836
837
|
do
|
|
837
|
-
perform(
|
|
838
|
+
perform(@dvala.io.print, "Starting process...");
|
|
838
839
|
let data = loadData();
|
|
839
840
|
let processed = processData(data);
|
|
840
|
-
perform(
|
|
841
|
+
perform(@dvala.io.print, "Process completed");
|
|
841
842
|
processed
|
|
842
843
|
end
|
|
843
844
|
```
|
|
@@ -854,8 +855,8 @@ end
|
|
|
854
855
|
array(1, 2, 3, 4);
|
|
855
856
|
|
|
856
857
|
// With spread
|
|
857
|
-
let
|
|
858
|
-
[1, 2, ...
|
|
858
|
+
let smallSet = [3, 4, 5];
|
|
859
|
+
[1, 2, ...smallSet, 6];
|
|
859
860
|
// => [1, 2, 3, 4, 5, 6]
|
|
860
861
|
```
|
|
861
862
|
|
|
@@ -958,134 +959,61 @@ true || "never reached"; // => true
|
|
|
958
959
|
```dvala
|
|
959
960
|
// Null coalescing operator
|
|
960
961
|
null ?? "default"; // => "default"
|
|
961
|
-
0 ?? "default"; // => 0 (only null
|
|
962
|
+
0 ?? "default"; // => 0 (only null is coalesced)
|
|
962
963
|
false ?? "default"; // => false
|
|
963
964
|
"" ?? "default"; // => ""
|
|
964
965
|
```
|
|
965
966
|
|
|
966
|
-
###
|
|
967
|
+
### Conditional Expression
|
|
967
968
|
|
|
968
969
|
```dvala
|
|
969
|
-
// Conditional expression
|
|
970
|
+
// Conditional expression (if/then/else/end)
|
|
970
971
|
let age = 25;
|
|
971
|
-
let result = age >= 18
|
|
972
|
+
let result = if age >= 18 then "adult" else "minor" end;
|
|
972
973
|
|
|
973
|
-
// Nested
|
|
974
|
+
// Nested conditional
|
|
974
975
|
let score = 85;
|
|
975
|
-
let category = score >= 90
|
|
976
|
+
let category = if score >= 90 then "A" else if score >= 80 then "B" else "C" end;
|
|
976
977
|
|
|
977
978
|
// With complex expressions
|
|
978
979
|
let isLoggedIn = () -> true;
|
|
979
980
|
let hasPermission = () -> true;
|
|
980
|
-
let status = isLoggedIn() && hasPermission()
|
|
981
|
+
let status = if isLoggedIn() && hasPermission() then "authorized" else "unauthorized" end;
|
|
981
982
|
```
|
|
982
983
|
|
|
983
984
|
## Variable Names
|
|
984
985
|
|
|
985
|
-
Dvala
|
|
986
|
+
Dvala uses JavaScript-style identifiers for variable names.
|
|
986
987
|
|
|
987
988
|
### Basic Rules
|
|
988
989
|
|
|
989
|
-
Variable names
|
|
990
|
-
|
|
991
|
-
**Illegal characters anywhere in a variable name:**
|
|
992
|
-
- Parentheses: `(` `)`
|
|
993
|
-
- Brackets: `[` `]`
|
|
994
|
-
- Braces: `{` `}`
|
|
995
|
-
- Quotes: `'` `"` `` ` ``
|
|
996
|
-
- Punctuation: `,` `.` `;`
|
|
997
|
-
- Whitespace: spaces, newlines, tabs
|
|
998
|
-
|
|
999
|
-
**Additional restrictions for the first character:**
|
|
1000
|
-
- Cannot start with digits `0-9`
|
|
990
|
+
Variable names must match the pattern `[a-zA-Z_$][a-zA-Z0-9_$]*`:
|
|
1001
991
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
Beyond these minimal restrictions, Dvala supports Unicode characters, including emojis, in variable names:
|
|
992
|
+
- **First character:** a letter (`a-z`, `A-Z`), underscore (`_`), or dollar sign (`$`)
|
|
993
|
+
- **Subsequent characters:** letters, digits (`0-9`), underscores, or dollar signs
|
|
1005
994
|
|
|
1006
995
|
```dvala
|
|
1007
|
-
|
|
1008
|
-
let
|
|
1009
|
-
let
|
|
1010
|
-
let
|
|
1011
|
-
|
|
1012
|
-
// Emojis work too!
|
|
1013
|
-
let 😅 = "grinning face with sweat";
|
|
1014
|
-
let 🚀 = "rocket ship";
|
|
1015
|
-
let result = 😅 ++ " " ++ 🚀;
|
|
1016
|
-
// => "grinning face with sweat rocket ship"
|
|
996
|
+
let userName = "alice";
|
|
997
|
+
let isValid = true;
|
|
998
|
+
let _private = 42;
|
|
999
|
+
let $special = "dollar";
|
|
1000
|
+
let counter2 = 0;
|
|
1017
1001
|
```
|
|
1018
1002
|
|
|
1019
1003
|
### Quoted Variable Names
|
|
1020
1004
|
|
|
1021
|
-
For cases where you need
|
|
1005
|
+
For cases where you need characters outside the normal rules, Dvala supports quoted variable names using single quotes:
|
|
1022
1006
|
|
|
1023
1007
|
```dvala
|
|
1024
1008
|
// Variables with spaces and special characters
|
|
1025
1009
|
let 'A strange variable' = 42;
|
|
1026
1010
|
let 'user.name' = "John Doe";
|
|
1027
1011
|
let 'data[0]' = "first element";
|
|
1028
|
-
let 'function()' = "callable";
|
|
1029
1012
|
|
|
1030
1013
|
// Access them the same way
|
|
1031
1014
|
'A strange variable' + 8;
|
|
1032
1015
|
// => 50
|
|
1033
1016
|
```
|
|
1034
|
-
|
|
1035
|
-
### Practical Examples
|
|
1036
|
-
|
|
1037
|
-
Here are some examples showcasing the flexibility of Dvala variable naming:
|
|
1038
|
-
|
|
1039
|
-
```dvala
|
|
1040
|
-
// Mathematical notation with Greek letters (avoiding reserved symbols)
|
|
1041
|
-
let α = 0.5;
|
|
1042
|
-
let β = 1.2;
|
|
1043
|
-
let γ = 2.0;
|
|
1044
|
-
let Δ = β - α;
|
|
1045
|
-
|
|
1046
|
-
// Descriptive names with special characters
|
|
1047
|
-
let user-name = "alice";
|
|
1048
|
-
let is-valid? = true;
|
|
1049
|
-
let counter! = 0;
|
|
1050
|
-
|
|
1051
|
-
// Mixed styles
|
|
1052
|
-
let dataSet₁ = [1, 2, 3];
|
|
1053
|
-
let dataSet₂ = [4, 5, 6];
|
|
1054
|
-
let 🔧config = { debug: true };
|
|
1055
|
-
```
|
|
1056
|
-
|
|
1057
|
-
### Important: Operator Spacing
|
|
1058
|
-
|
|
1059
|
-
Due to Dvala' flexible variable naming, **operators must be separated by whitespace**. This is crucial to understand:
|
|
1060
|
-
|
|
1061
|
-
```dvala
|
|
1062
|
-
// This is a variable name, NOT addition!
|
|
1063
|
-
let x+1 = 42;
|
|
1064
|
-
let result1 = x+1; // => 42
|
|
1065
|
-
|
|
1066
|
-
// To perform addition, use spaces
|
|
1067
|
-
let x = 5;
|
|
1068
|
-
let result2 = x + 1; // => 6
|
|
1069
|
-
|
|
1070
|
-
// More examples of what looks like operations but are actually variable names
|
|
1071
|
-
let a-b = "subtraction variable";
|
|
1072
|
-
let c*d = "multiplication variable";
|
|
1073
|
-
let e/f = "division variable";
|
|
1074
|
-
let g<h = "comparison variable";
|
|
1075
|
-
|
|
1076
|
-
// To use these as actual operations, add spaces
|
|
1077
|
-
let a = 10;
|
|
1078
|
-
let b = 3;
|
|
1079
|
-
let a-sum = a + b; // Addition
|
|
1080
|
-
let a-diff = a - b; // Subtraction
|
|
1081
|
-
let a-prod = a * b; // Multiplication
|
|
1082
|
-
let a-quot = a / b; // Division
|
|
1083
|
-
let a-comp = a < b; // Comparison
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
Without whitespace, Dvala treats the entire sequence as a single variable identifier. This applies to all operators, including comparison operators, logical operators, and arithmetic operators.
|
|
1087
|
-
|
|
1088
|
-
This flexibility allows for expressive and readable code while maintaining the functional programming paradigm that Dvala embodies.
|
|
1089
1017
|
## Operators and Functions
|
|
1090
1018
|
|
|
1091
1019
|
### Algebraic Notation
|
|
@@ -1248,10 +1176,10 @@ Dvala favors subject-first parameter order for better operator chaining:
|
|
|
1248
1176
|
|
|
1249
1177
|
```dvala
|
|
1250
1178
|
// Function style
|
|
1251
|
-
filter([1, 2, 3, 4],
|
|
1179
|
+
filter([1, 2, 3, 4], isOdd); // => [1, 3]
|
|
1252
1180
|
|
|
1253
1181
|
// Operator style (more readable)
|
|
1254
|
-
[1, 2, 3, 4] filter
|
|
1182
|
+
[1, 2, 3, 4] filter isOdd; // => [1, 3]
|
|
1255
1183
|
```
|
|
1256
1184
|
|
|
1257
1185
|
### Pipe Operator
|
|
@@ -1260,18 +1188,18 @@ The pipe operator `|>` passes the result of the left expression as the first arg
|
|
|
1260
1188
|
|
|
1261
1189
|
```dvala
|
|
1262
1190
|
// Without pipe operator
|
|
1263
|
-
reduce(map(filter([1, 2, 3, 4, 5, 6],
|
|
1191
|
+
reduce(map(filter([1, 2, 3, 4, 5, 6], isOdd), -> $ * $), +, 0);
|
|
1264
1192
|
|
|
1265
1193
|
// With pipe operator (much more readable)
|
|
1266
1194
|
[1, 2, 3, 4, 5, 6]
|
|
1267
|
-
|> filter(_,
|
|
1195
|
+
|> filter(_, isOdd)
|
|
1268
1196
|
|> map(_, -> $ * $)
|
|
1269
1197
|
|> reduce(_, +, 0);
|
|
1270
1198
|
// => 35
|
|
1271
1199
|
|
|
1272
1200
|
// Simple transformations
|
|
1273
1201
|
"hello world"
|
|
1274
|
-
|>
|
|
1202
|
+
|> upperCase
|
|
1275
1203
|
|> split(_, " ")
|
|
1276
1204
|
|> reverse
|
|
1277
1205
|
|> join(_, "-");
|
|
@@ -1287,7 +1215,7 @@ reduce(map(filter([1, 2, 3, 4, 5, 6], odd?), -> $ * $), +, 0);
|
|
|
1287
1215
|
// Data processing pipeline
|
|
1288
1216
|
{ numbers: [1, 2, 3, 4, 5], multiplier: 3 }
|
|
1289
1217
|
|> get(_, "numbers")
|
|
1290
|
-
|> filter(_,
|
|
1218
|
+
|> filter(_, isEven)
|
|
1291
1219
|
|> map(_, *(_, 3))
|
|
1292
1220
|
|> reduce(_, +, 0);
|
|
1293
1221
|
// => 18 (even numbers [2, 4] -> [6, 12] -> sum = 18)
|
|
@@ -1311,8 +1239,7 @@ Here's the complete precedence table, from highest to lowest:
|
|
|
1311
1239
|
| 5 | `&` `xor` `\|` | Bitwise operations | `4 \| 2 & 1` → `4 \| 0` → `4` |
|
|
1312
1240
|
| 4 | `&&` `\|\|` `??` | Logical operations | `true && false \|\| true` → `false \|\| true` → `true` |
|
|
1313
1241
|
| 3 | *function operators* | Binary functions used as operators | `5 max 3 + 2` → `5 max 5` → `5` |
|
|
1314
|
-
| 2 | `\|>` | Pipe operator | `[1,2] \|> map(_, inc) \|>
|
|
1315
|
-
| 1 | `?` `:` | Conditional (ternary) operator | `true ? 1 + 2 : 3` → `true ? 3 : 3` → `3` |
|
|
1242
|
+
| 2 | `\|>` | Pipe operator | `[1,2] \|> map(_, inc) \|> reduce(_, 0, +)` |
|
|
1316
1243
|
|
|
1317
1244
|
#### Examples of Precedence in Action
|
|
1318
1245
|
|
|
@@ -1330,11 +1257,11 @@ Here's the complete precedence table, from highest to lowest:
|
|
|
1330
1257
|
3 > 2 && 1 < 2; // => true && true = true
|
|
1331
1258
|
|
|
1332
1259
|
// Pipe has very low precedence
|
|
1333
|
-
let
|
|
1260
|
+
let { sum } = import(vector);
|
|
1334
1261
|
[1, 2, 3] |> map(_, inc) |> sum; // Evaluates left to right
|
|
1335
1262
|
|
|
1336
|
-
// Conditional
|
|
1337
|
-
true
|
|
1263
|
+
// Conditional expression
|
|
1264
|
+
if true then 2 + 3 else 4 + 5 end; // => 5
|
|
1338
1265
|
```
|
|
1339
1266
|
|
|
1340
1267
|
#### Using Parentheses
|
|
@@ -1356,7 +1283,7 @@ let d = true;
|
|
|
1356
1283
|
let e = false;
|
|
1357
1284
|
let f = 10;
|
|
1358
1285
|
let g = 5;
|
|
1359
|
-
((a + b) * c) > (d && e
|
|
1286
|
+
((a + b) * c) > (if d && e then f else g end) // => (5 * 4) > (if false then 10 else 5 end) = 20 > 5 = true;
|
|
1360
1287
|
```
|
|
1361
1288
|
|
|
1362
1289
|
#### Associativity
|
|
@@ -1427,7 +1354,7 @@ let square = x -> x * x;
|
|
|
1427
1354
|
### Factorial
|
|
1428
1355
|
|
|
1429
1356
|
```dvala
|
|
1430
|
-
let factorial = n -> n <= 1
|
|
1357
|
+
let factorial = (n) -> if n <= 1 then 1 else n * self(n - 1) end;
|
|
1431
1358
|
|
|
1432
1359
|
factorial(5); // => 120
|
|
1433
1360
|
```
|
|
@@ -1439,13 +1366,13 @@ let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
|
1439
1366
|
|
|
1440
1367
|
// Get even numbers squared
|
|
1441
1368
|
let evenSquares = numbers
|
|
1442
|
-
|> filter(_,
|
|
1369
|
+
|> filter(_, isEven)
|
|
1443
1370
|
|> map(_, -> $ * $);
|
|
1444
1371
|
// => [4, 16, 36, 64, 100]
|
|
1445
1372
|
|
|
1446
1373
|
// Sum of odd numbers
|
|
1447
1374
|
let oddSum = numbers
|
|
1448
|
-
|> filter(_,
|
|
1375
|
+
|> filter(_, isOdd)
|
|
1449
1376
|
|> reduce(_, +, 0);
|
|
1450
1377
|
// => 25
|
|
1451
1378
|
```
|
|
@@ -1465,7 +1392,7 @@ let wordCount = text
|
|
|
1465
1392
|
let longWords = text
|
|
1466
1393
|
|> split(_, #"\s+")
|
|
1467
1394
|
|> filter(_, -> count($) > 4)
|
|
1468
|
-
|> map(_,
|
|
1395
|
+
|> map(_, upperCase);
|
|
1469
1396
|
// => ["HELLO,", "WORLD!", "TODAY?"]
|
|
1470
1397
|
```
|
|
1471
1398
|
|
|
@@ -1480,7 +1407,7 @@ let users = [
|
|
|
1480
1407
|
];
|
|
1481
1408
|
|
|
1482
1409
|
// Group by department and get average age
|
|
1483
|
-
let grouped = users |> su.
|
|
1410
|
+
let grouped = users |> su.groupBy(_, "department");
|
|
1484
1411
|
let departmentAges = grouped
|
|
1485
1412
|
|> entries(_)
|
|
1486
1413
|
|> map(_, ([dept, people]) -> do
|