# Baba Yaga Crash Course ## Language Overview Baba Yaga is a functional scripting language emphasizing immutability, pattern matching, and explicit error handling. It features currying, anonymous functions, recursive functions, and a useful `when` expression for control flow. ## Core Syntax Rules ### Comments and Statements ```baba // Single line comments start with // variable : 42; // Variable declaration function : x -> x + 1; // Function declaration ``` ### Data Types and Literals **Numbers:** ```baba integerValue : 42; // Int type floatValue : 3.14; // Float type negativeValue : -10; // Negative numbers ``` **Strings:** ```baba greeting : "Hello World"; // String type concatenated : "Hello" .. " " .. "World"; // String concatenation with .. or str.concat ``` **Booleans:** ```baba isTrue : true; isFalse : false; ``` **Mathematical Constants:** ```baba pi : PI; // Built-in π constant infinity : INFINITY; // Built-in infinity ``` **Lists (Immutable):** ```baba numbers : [1, 2, 3, 4]; mixed : [1, "hello", true]; firstElement : numbers.0; // Zero-based indexing secondElement : numbers.1; ``` **Tables (Immutable Key-Value):** ```baba person : {name: "Lucy Snowe", age: 23, active: true}; userName : person.name; // Property access userAge : person.age; ``` ### Type System and Declarations **Optional Type Annotations:** ```baba // Optional type declaration myNumber Int; myNumber : 42; // Direct assignment with type inference greeting : "Hello"; // Type inferred as String ``` **Type Hierarchy:** - `Int` ⊂ `Float` ⊂ `Number` (`Int` can be used where `Float` expected) - `String`, `Bool`, `List`, `Table`, `Result` are distinct types ## Functions ### Basic Functions ```baba // Simple function add : x y -> x + y; result : add 5 3; // Function call: 8 // Single parameter function square : x -> x * x; squared : square 4; // 16 ``` ### Anonymous Functions ```baba // Anonymous function doubler : x -> x * 2; // Immediately invoked result : (x -> x + 1) 5; // 6 // In table literals calculator : { add: x y -> x + y; multiply: x y -> x * y; }; sum : calculator.add 10 20; // 30 ``` ### Currying and Partial Application ```baba // Curried function (multiple arrows) add : x -> y -> x + y; add5 : add 5; // Partial application result : add5 3; // 8 // Multi-level currying addThree : x -> y -> z -> x + y + z; addTwoMore : addThree 1; // Partially applied addOne : addTwoMore 2; // Partially applied final : addOne 3; // 6 ``` ### Typed Functions ```baba // Function with parameter and return types add : (x: Int, y: Int) -> Int -> x + y; multiply : (x: Float, y: Float) -> Float -> x * y; // Curried typed function curriedAdd : (x: Int) -> (Int -> Int) -> y -> x + y; ``` ### Recursive Functions ```baba // Simple recursion factorial : n -> when n is 0 then 1 1 then 1 _ then n * (factorial (n - 1)); // Fibonacci fibonacci : n -> when n is 0 then 0 1 then 1 _ then (fibonacci (n - 1)) + (fibonacci (n - 2)); ``` ### Local Bindings (`with`/`with rec`) ```baba // Non-recursive local bindings addMul : x y -> with (inc : x + 1; prod : inc * y;) -> inc + prod; // Typed locals sumNext : (x: Int, y: Int) -> Int -> with (nx Int; ny Int; nx : x + 1; ny : y + 1;) -> nx + ny; // Mutually recursive locals evenOdd : z -> with rec ( isEven : n -> when n is 0 then true _ then isOdd (n - 1); isOdd : n -> when n is 0 then false _ then isEven (n - 1); ) -> {even: isEven z, odd: isOdd z}; ``` **Common Patterns and Use Cases:** ```baba // 1. Computed intermediate values (avoiding repetition) quadraticRoots : a b c -> with ( discriminant : b * b - 4 * a * c; sqrtDisc : math.sqrt discriminant; denominator : 2 * a; ) -> { r1: (-b + sqrtDisc) / denominator, r2: (-b - sqrtDisc) / denominator }; // 2. Complex calculations with named steps calculateTax : income deductions -> with ( taxableIncome : income - deductions; taxRate : when (taxableIncome <= 50000) is true then 0.15 _ then when (taxableIncome <= 100000) is true then 0.25 _ then 0.35; baseTax : taxableIncome * taxRate; finalTax : when (baseTax < 1000) is true then 1000 _ then baseTax; ) -> finalTax; // 3. Data transformation pipelines processUserData : user -> with ( normalizedName : str.upper (str.trim user.name); ageGroup : when (user.age < 18) is true then "minor" _ then when (user.age < 65) is true then "adult" _ then "senior"; status : when user.active is true then "active" false then "inactive"; ) -> { id: user.id, displayName: normalizedName, category: ageGroup, status: status }; // 4. Error handling with multiple validations validateOrder : order -> with ( hasItems : (length order.items) > 0; hasValidTotal : order.total > 0; // Note: Baba Yaga doesn't have null, so we'll use a different validation hasValidShipping : (length order.shippingAddress) > 0; allValid : hasItems and hasValidTotal and hasValidShipping; ) -> when allValid is true then Ok order false then Err "Order validation failed"; // 5. Complex pattern matching with computed values classifyTriangle : a b c -> with ( sorted : [math.min a b, math.max a b, math.max (math.max a b) c]; side1 : sorted.0; side2 : sorted.1; side3 : sorted.2; isValid : ((side1 + side2) > side3); isEquilateral : ((a = b) and (b = c)); isIsosceles : ((a = b) or (b = c) or (a = c)); isRight : (math.abs ((side1 * side1 + side2 * side2) - (side3 * side3))) < 0.001; ) -> when isValid is false then "Invalid triangle" true then when isEquilateral is true then "Equilateral" false then when isIsosceles is true then when isRight is true then "Right isosceles" false then "Isosceles" false then when isRight is true then "Right scalene" false then "Scalene"; // 6. Mutually recursive functions (with rec) // Binary tree operations treeOperations : tree -> with rec ( // Count total nodes countNodes : t -> when (isEmptyTable t) is true then 0 false then 1 + (countNodes t.left) + (countNodes t.right); // Calculate tree height treeHeight : t -> when (isEmptyTable t) is true then 0 false then 1 + (math.max (treeHeight t.left) (treeHeight t.right)); // Check if tree is balanced isBalanced : t -> when (isEmptyTable t) is true then true false then (math.abs ((treeHeight t.left) - (treeHeight t.right)) <= 1) and (isBalanced t.left) and (isBalanced t.right); ) -> { nodeCount: countNodes tree, height: treeHeight tree, balanced: isBalanced tree }; // 7. State machine with recursive state transitions trafficLight : initialState -> with rec ( // State transition function nextState : current -> when current is "red" then "green" "green" then "yellow" "yellow" then "red"; // Count transitions until back to start countCycles : start current count -> when current = start is true then count false then countCycles start (nextState current) (count + 1); // Get state after N transitions stateAfter : current n -> when n is 0 then current _ then stateAfter (nextState current) (n - 1); ) -> { cycles: countCycles initialState initialState 0, after10: stateAfter initialState 10, next: nextState initialState }; // 8. Combinatorial functions with shared helpers combinatorics : n r -> with rec ( // Factorial function factorial : k -> when k is 0 then 1 1 then 1 _ then k * (factorial (k - 1)); // Permutation: P(n,r) = n! / (n-r)! permutation : n r -> factorial n / (factorial (n - r)); // Combination: C(n,r) = n! / (r! * (n-r)!) combination : n r -> factorial n / ((factorial r) * (factorial (n - r))); ) -> { n: n, r: r, permutations: permutation n r, combinations: combination n r }; ``` **Key Benefits of `with` and `with rec`:** 1. **Avoid Repetition**: Compute values once and reuse them 2. **Improve Readability**: Give meaningful names to intermediate calculations 3. **Enable Complex Logic**: Break down complex operations into clear steps 4. **Mutual Recursion**: `with rec` allows local functions to call each other 5. **Scoped Variables**: Local bindings don't pollute global scope 6. **Type Safety**: Can declare types for local variables 7. **Performance**: Avoid recalculating expensive operations 8. **Maintainability**: Centralize related logic in one place **When to Use `with` vs `with rec`:** - **Use `with`** when you need local bindings for computed values, intermediate results, or simple helper functions that don't call each other - **Use `with rec`** when you need mutually recursive functions or when local functions need to reference each other **Best Practices:** ```baba // Good: Clear, focused with blocks processData : data -> with ( cleaned : str.trim data; normalized : str.lower cleaned; validated : (length normalized) > 0; ) -> when validated is true then Ok normalized false then Err "Empty data"; // Love it: Logical grouping of related operations analyzeNumbers : numbers -> with ( count : length numbers; sum : reduce (acc x -> acc + x) 0 numbers; average : when count > 0 then sum / count _ else 0; sorted : sort numbers; median : when count % 2 = 0 then (sorted.(count / 2 - 1) + sorted.(count / 2)) / 2 _ else sorted.(count / 2); ) -> {count, sum, average, median}; // Oh no! Avoid: Overly complex with blocks // Instead, break into smaller functions processUser : user -> with ( // Too many bindings - consider breaking into helper functions nameValid : (length user.name) > 0; emailValid : (length user.email) > 0; // Simplified validation ageValid : (user.age >= 0) and (user.age <= 150); phoneValid : (length user.phone) >= 10; addressValid : (length user.address) > 0; // Simplified validation preferencesValid : (length user.preferences) > 0; allValid : (nameValid and emailValid and ageValid and phoneValid and addressValid and preferencesValid); ) -> when allValid is true then Ok user _ then Err "Validation failed"; // Better: Break into focused functions validateUserBasic : user -> with ( nameValid : (length user.name) > 0; emailValid : (length user.email) > 0; // Simplified validation ageValid : (user.age >= 0) and (user.age <= 150); ) -> (nameValid and emailValid and ageValid); validateUserContact : user -> with ( phoneValid : (length user.phone) >= 10; // Note: Baba Yaga doesn't have null, so we'll use a different validation addressValid : (length user.address) > 0; ) -> (phoneValid and addressValid); processUser : user -> when ((validateUserBasic user) and (validateUserContact user)) is true then Ok user _ then Err "Validation failed"; ``` **Common Anti-patterns to Avoid:** ```baba // Don't: Use with for simple expressions badExample : x -> with (result : x + 1;) -> result; // Just use: x -> x + 1 // Don't: Nest with blocks unnecessarily nestedBad : x -> with (a : x + 1;) -> with (b : a * 2;) -> with (c : b + 3;) -> c; // Use: with (a: x+1; b: a*2; c: b+3;) -> c // Don't: Use with rec when simple recursion will do the trick simpleRecursion : n -> when n is 0 then 1 _ then n * (simpleRecursion (n - 1)); // No need for with rec // Do: Use with rec for mutual recursion mutualRecursion : n -> with rec ( isEven : x -> when x is 0 then true _ then isOdd (x - 1); isOdd : x -> when x is 0 then false _ then isEven (x - 1); ) -> isEven n; ``` ## Pattern Matching with `when` ### Basic Pattern Matching ```baba // Literal patterns checkNumber : num -> when num is 0 then "Zero" 1 then "One" 2 then "Two" _ then "Other"; // Wildcard matches anything ``` ### Multiple Discriminants ```baba checkCoords : x y -> when x y is 0 0 then "Origin" 1 1 then "Diagonal" _ _ then "Somewhere else"; ``` ### Type Patterns ```baba checkType : value -> when value is Int then "It's an integer" String then "It's a string" Bool then "It's a boolean" _ then "Unknown type"; ``` ### Result Pattern Matching ```baba processResult : result -> when result is Ok value then value * 2 // 'value' binds to inner data Err message then 0; // 'message' binds to error string ``` ## Error Handling with Result Type Baba Yaga uses the `Result` type for explicit error handling instead of exceptions. See [Error Handling](./06_error-handling.md) for comprehensive coverage. ```baba // Function returning Result divide : x y -> when y is 0 then Err "Division by zero" _ then Ok (x / y); // Using Result result : divide 10 2; // Ok 5 errorResult : divide 5 0; // Err "Division by zero" // Pattern matching on Result handleDivision : x y -> when (divide x y) is Ok value then value Err msg then 0; ``` ## Operators and Precedence ### Arithmetic Operators ```baba addition : 5 + 3; // 8 subtraction : 10 - 4; // 6 multiplication : 6 * 7; // 42 division : 15 / 3; // 5 modulo : 17 % 5; // 2 unaryMinus : -42; // -42 ``` ### Comparison Operators ```baba equal : 5 = 5; // true notEqual : 5 != 3; // true greater : 5 > 3; // true less : 3 < 5; // true greaterEqual : 5 >= 5; // true lessEqual : 3 <= 5; // true ``` ### Logical Operators ```baba andResult : true and false; // false orResult : true or false; // true xorResult : true xor true; // false ``` ### String Concatenation ```baba combined : "Hello" .. " " .. "World"; // "Hello World" ``` ### Operator Precedence (highest to lowest) 1. `*`, `/`, `%` (multiplication, division, modulo) 2. `+`, `-` (addition, subtraction) 3. `=`, `!=`, `>`, `<`, `>=`, `<=` (comparison) 4. `xor` 5. `and` 6. `or` 7. `..` (string concatenation) ## Built-in Functions ### Higher-Order List Functions ```baba numbers : [1, 2, 3, 4, 5]; // map: apply function to each element doubled : map (x -> x * 2) numbers; // [2, 4, 6, 8, 10] // filter: keep elements matching predicate evens : filter (x -> x % 2 = 0) numbers; // [2, 4] // reduce: fold list to single value sum : reduce (acc x -> acc + x) 0 numbers; // 15 ``` ### Immutable List Operations ```baba original : [1, 2, 3]; // append: add to end withFour : append original 4; // [1, 2, 3, 4] // prepend: add to beginning withZero : prepend 0 original; // [0, 1, 2, 3] // concat: combine lists combined : concat [1, 2] [3, 4]; // [1, 2, 3, 4] // update: replace at index updated : update original 1 99; // [1, 99, 3] // removeAt: remove at index removed : removeAt original 0; // [2, 3] // slice: extract sublist sublist : slice original 0 2; // [1, 2] // Note: original list is never modified! ``` ### Immutable Table Operations ```baba user : {name: "Alice", age: 30}; // set: add/update property updated : set user "city" "Boston"; // {name: "Alice", age: 30, city: "Boston"} // remove: delete property minimal : remove user "age"; // {name: "Alice"} // merge: combine tables (second overrides first) merged : merge user {country: "USA"}; // {name: "Alice", age: 30, country: "USA"} // keys: get all keys as list keyList : keys user; // ["name", "age"] // values: get all values as list valueList : values user; // ["Alice", 30] ``` ### String Operations ```baba // String concatenation combined : str.concat "Hello" " " "World"; // "Hello World" // Split string into list words : str.split "a,b,c" ","; // ["a", "b", "c"] // Join list into string sentence : str.join ["Hello", "World"] " "; // "Hello World" // String length len : str.length "Hello"; // {value: 5, isFloat: false} // Substring part : str.substring "Hello World" 0 5; // "Hello" // Replace replaced : str.replace "Hello World" "World" "Universe"; // "Hello Universe" // Trim whitespace clean : str.trim " Hello "; // "Hello" // Case conversion upper : str.upper "hello"; // "HELLO" lower : str.lower "WORLD"; // "world" ``` ### Math Operations ```baba // Basic math functions absolute : math.abs -5; // {value: 5, isFloat: true} minimum : math.min 3 7; // {value: 3, isFloat: true} maximum : math.max 3 7; // {value: 7, isFloat: true} clamped : math.clamp 10 0 5; // {value: 5, isFloat: true} // Rounding floored : math.floor 3.7; // {value: 3, isFloat: true} ceiled : math.ceil 3.2; // {value: 4, isFloat: true} rounded : math.round 3.5; // {value: 4, isFloat: true} // Powers and roots powered : math.pow 2 3; // {value: 8, isFloat: true} squareRoot : math.sqrt 16; // {value: 4, isFloat: true} // Trigonometry (radians) sine : math.sin 0; // {value: 0, isFloat: true} cosine : math.cos 0; // {value: 1, isFloat: true} // Random numbers random : math.random; // Random float 0 <= x < 1 randomInt : math.randomInt 1 6; // Random integer 1-6 inclusive ``` ### Enhanced Random Operations ```baba // Enhanced random utilities numbers : [1, 2, 3, 4, 5]; choice : random.choice numbers; // Random element from list shuffled : random.shuffle numbers; // Shuffled copy of list randomNum : random.range 1 10; // Random integer 1-10 random.seed 42; // Set random seed (placeholder) ``` ### Data Validation ```baba // Input validation utilities isValid : validate.notEmpty "hello"; // true isEmpty : validate.notEmpty ""; // false inRange : validate.range 1 10 5; // true validEmail : validate.email "user@domain.com"; // true correctType : validate.type "Int" 42; // true ``` ### Text Processing ```baba // Enhanced text utilities multiline : "line1\nline2\nline3"; // Note: \n is literal, not newline lines : text.lines multiline; // ["line1\\nline2\\nline3"] (single item) words : text.words "hello world test"; // ["hello", "world", "test"] padded : text.padLeft 10 "hi"; // " hi" aligned : text.padRight 10 "hi"; // "hi " ``` ### Data Transformation ```baba // Sorting with custom criteria people : [ {name: "Alice", age: 30}, {name: "Bob", age: 25}, {name: "Charlie", age: 35} ]; byAge : sort.by people (p -> p.age); // Sorted by age: Bob, Alice, Charlie // Grouping data numbers : [1, 2, 3, 4, 5, 6]; grouped : group.by numbers (x -> x % 2 = 0); // Groups by even/odd evenNums : grouped."true"; // [2, 4, 6] oddNums : grouped."false"; // [1, 3, 5] ``` ### Utility Functions ```baba // Array chunking (APL-style windowing) data : [1, 2, 3, 4, 5, 6]; chunks : chunk data 2; // [[1, 2], [3, 4], [5, 6]] // Range generation sequence : range 1 5; // [1, 2, 3, 4, 5] countdown : range 5 1; // [5, 4, 3, 2, 1] // Value repetition repeated : repeat 3 "hello"; // ["hello", "hello", "hello"] ``` ### Debug and Development Tools ```baba // Enhanced debugging with type information debug.print 42; // [DEBUG] 42 (Int) debug.print (x -> x * 2); // [DEBUG] ...> (Unknown) // Detailed value inspection myFunc : x -> x + 1; details : debug.inspect myFunc; // Returns detailed type information // Assertions with custom messages assert (2 + 2 = 4) "Math should work"; // Passes silently // assert (2 + 2 = 5) "This fails"; // Throws: "Assertion failed: This fails" ``` ### I/O Operations **Basic Output:** ```baba // Output to console io.out "Hello World"; io.out 42; io.out [1, 2, 3]; // Read input (returns string) input : io.in; ``` **Enhanced Output with `io.print`:** The `io.print` function provides formatting for different data types, making output more easily readable: ```baba // Automatic grid detection for 2D arrays gameBoard : [ [1, 0, 1], [0, 1, 0], [1, 0, 1] ]; io.print gameBoard; // Output: // █·█ // ·█· // █·█ // Labeled output with format strings io.print "Game Board" gameBoard; io.print "Score" 1500; io.print "Player" "Alice"; // Perfect for Conway's Game of Life, chess boards, mazes, etc. glider : [ [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0] ]; io.print "Glider Pattern Evolution:"; io.print "Step 0:"; io.print glider; // Output: // Glider Pattern Evolution: // Step 0: // ·█··· // ··█·· // ███·· // ····· // ····· // Enhanced display of other data types myFunction : x -> x * 2; result : Ok 42; error : Err "Something went wrong"; io.print "Function" myFunction; // Function: io.print "Success" result; // Success: Ok(42) io.print "Failure" error; // Failure: Err(Something went wrong) ``` **Key `io.print` Features:** - **Automatic Grid Detection**: 2D numeric arrays display as visual grids with `█` (alive/1) and `·` (dead/0) - **Clean Function Display**: Shows `` instead of complex internal representations - **Enhanced Result Types**: Displays `Ok(value)` and `Err(message)` in readable format - **Labeled Output**: Use format strings like `io.print "Label" data` for organized output - **Educational Value**: Perfect for teaching algorithms, game development, data visualization - **Backward Compatible**: Works as a drop-in replacement for `io.out` in most cases ### Introspection ```baba // Get shape information about values listInfo : shape [1, 2, 3]; // Returns: {kind: "List", rank: 1, shape: [3], size: 3, isEmpty: false} stringInfo : shape "hello"; // Returns: {kind: "String", rank: 1, shape: [5], size: 5, isEmpty: false} tableInfo : shape {a: 1, b: 2}; // Returns: {kind: "Table", rank: 1, shape: [2], size: 2, keys: ["a", "b"], isEmpty: false} ``` ## Complete Examples ### Calculator with Pattern Matching ```baba calculate : op x y -> when op is "add" then (x + y) "subtract" then (x - y) "multiply" then (x * y) "divide" then when y is 0 then Err "Division by zero" _ then Ok (x / y) _ then Err "Unknown operation"; result1 : calculate "add" 5 3; // 8 result2 : calculate "divide" 10 0; // Err "Division by zero" ``` ### List Processing Pipeline ```baba numbers : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Find sum of squares of even numbers evenSquareSum : reduce (acc x -> acc + x) 0 (map (x -> x * x) (filter (x -> x % 2 = 0) numbers)); // Result: 220 (4 + 16 + 36 + 64 + 100) ``` ### Tree Processing with Recursion ```baba isEmptyTable : t -> (length (keys t)) = 0; treeHeight : tree -> when (isEmptyTable tree) is true then 0 false then when (isEmptyTable tree.left) (isEmptyTable tree.right) is true true then 1 _ _ then 1 + (math.max (treeHeight tree.left) (treeHeight tree.right)); myTree : { value: 1, left: {value: 2, left: {}, right: {}}, right: {value: 3, left: {}, right: {}} }; height : treeHeight myTree; // 2 ``` ### Error Handling Chain ```baba // Chain of operations that might fail processData : input -> when (parseNumber input) is Err msg then Err msg Ok num then when (num / 2) > 10 is true then Ok (num / 2) false then Err "Result too small"; parseNumber : str -> when str is "0" then Ok 0 "10" then Ok 10 "20" then Ok 20 _ then Err "Invalid number"; result : processData "20"; // Returns Err "Result too small" (10 is not > 10) ``` ## Key Patterns 1. **Immutability**: All data structures are immutable. Use built-in functions like `append`, `set`, etc. 2. **Pattern Matching**: Use `when` expressions for control flow instead of if/else chains. 3. **Error Handling**: Use `Result` type with `Ok`/`Err` variants instead of exceptions. 4. **Function Composition**: Build complex behavior by composing simple functions. 5. **Recursion**: Use recursive functions with pattern matching for iteration-like behavior. 6. **Type Safety**: Use optional type annotations for better error detection. ## Function Call Syntax - Parentheses are optional: `add 5 3` or `(add 5 3)` - Function calls are left-associative: `f x y z` means `((f x) y) z` - Use parentheses to group: `f (g x) y` applies `g` to `x` first ## Misc. Important Notes - **Whitespace**: Significant for function calls (spaces separate arguments) - **Mutability**: Everything is immutable - operations return new values - **Type Coercion**: `Int` automatically promotes to Float when needed - **Error Strategy**: Use `Result` type, not exceptions - **Recursion**: Preferred over loops for iteration - **Variables**: Actually immutable bindings, not mutable variables ## Execution Model and Environment - **Entry point**: Programs execute top-to-bottom at the file’s top level. There is no required `main` function; define and call one yourself if needed or if you like them. - **Modules**: No built-in import/export system. Larger programs are typically single-file or orchestrated by a host embedding (see `../IO.md`, WIP). - **Standard library scope**: - In addition to items earlier, available built-ins include: - **General**: `length` (works on lists and strings), `chunk`, `range`, `repeat`, `assert` - **Array Programming**: `scan`, `cumsum`, `cumprod`, `at`, `where`, `take`, `drop`, `broadcast`, `zipWith`, `reshape`, `flatMap` - **Function Combinators**: `flip`, `apply`, `pipe`, `compose` - **String namespace `str`**: `concat`, `split`, `join`, `length`, `substring`, `replace`, `trim`, `upper`, `lower` - **Text namespace `text`**: `lines`, `words`, `padLeft`, `padRight` - **Math namespace `math`**: `abs`, `sign`, `floor`, `ceil`, `round`, `trunc`, `min`, `max`, `clamp`, `pow`, `sqrt`, `exp`, `log`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `deg`, `rad`, `random`, `randomInt` - **Random namespace `random`**: `choice`, `shuffle`, `range`, `seed` - **Validation namespace `validate`**: `notEmpty`, `range`, `email`, `type` - **Sorting namespace `sort`**: `by` - **Grouping namespace `group`**: `by` - **Debug namespace `debug`**: `print`, `inspect` - **IO namespace `io`**: `out`, `in`, `print`, and (host-enabled) event functions `io.emit`, `io.listen` ## Syntax Clarifications - **Statement termination**: Top-level statements, table fields, and parentheses bodies accept a trailing `;` if present. - **Whitespace**: Only significant for function calls (spaces separate arguments). Indentation/newlines do not affect `when` or other constructs. - **Operator associativity**: All binary operators (arithmetic, comparison, logical, `..`) are left-associative. Precedence is described earlier in this document, and also in the [Types](./04_types.md) and [Gotchyas](./07_gotchyas.md) documentation. ## Type System Details - **Type inference**: Type annotations are optional everywhere. They provide runtime validation; without them, code is dynamically typed. - **Numeric hierarchy**: `Int ⊂ Float ⊂ Number` (widening permitted). - **Generics**: No type parameters/generics. Achieve polymorphism by leaving parameters unannotated. - **Type aliases**: Not supported. ## Advanced Pattern Matching - **Nested patterns**: Supported for lists and tables. You can match deep structures, e.g. `{user: {name: "Tziporah"}}`. - **Pattern Guards**: Use `if` keyword to add conditions to patterns: ```baba classify : x -> when x is n if (n > 0) then "positive" n if (n < 0) then "negative" 0 then "zero"; ``` - **Lists/strings**: List patterns match exact shapes (no head/tail cons syntax). Strings can be matched by literal or `String` type. ## Function Behavior Edge Cases - **Partial application**: Supported for all functions; supplying fewer args returns a new function. Supplying more than arity is an error. - **Recursion optimization**: Tail-call optimization is not performed. - **Closures and `with`**: - Functions capture a snapshot of surrounding scope at definition time. - `with rec` creates function bindings that close over a shared scope (by reference) to enable mutual recursion. ## Error Handling Patterns - **Result chaining**: No built-ins like `andThen`/`mapError`. Idiomatically, compose with helper functions or use nested `when`. - **Runtime errors**: Thrown as plain errors with standard messages (e.g., `Division by zero`, `Index out of bounds`, `Undefined variable`, `Undefined property`, `Unknown operator`). ## Performance & Limits - **Stack limits**: Recursion depth is limited by the host JS engine’s stack (no TCO). - **Data sizes**: Lists are JS arrays; tables are proxied maps/objects. Limits are memory-bound. - **Immutability costs**: Operations return new arrays/maps (no structural sharing). Favor `map`/`filter`/`reduce` and careful composition for large data.