# Functional Programming with Baba Yaga Baba Yaga is expression-oriented, immutable by default, and built around simple, first-class functions. ## Core Concepts - Immutability: lists and tables return new values for every change - First-class functions: functions can be passed, returned, and stored in tables - Expressions: everything is an expression, including `when` ## Anonymous Functions, Currying, Partial Application ```baba // Anonymous function inc : (x -> x + 1); // Curried function (equivalent to x -> (y -> x + y)) add : x -> y -> x + y; // Partial application after5 : add 5; // after5 is a function (y -> 5 + y) result : after5 10; // 15 ``` ## Higher-Order Functions Built-ins for lists: `map`, `filter`, `reduce`. ```baba doubled : map (x -> x * 2) [1, 2, 3]; // [2, 4, 6] evens : filter (x -> x % 2 = 0) [1, 2, 3, 4, 5]; // [2, 4] sum : reduce (acc x -> acc + x) 0 [1, 2, 3, 4]; // 10 ``` ## Advanced Data Operations Enhanced utilities for sorting and grouping: ```baba // Custom sorting with key functions students : [ {name: "Alice", grade: 85}, {name: "Bob", grade: 92}, {name: "Charlie", grade: 78} ]; byGrade : sort.by students (s -> s.grade); // Sorted by grade: Charlie, Alice, Bob // Grouping data by criteria ages : [18, 25, 17, 30, 16, 45]; byCategory : group.by ages (age -> when (age < 18) is true then "minor" _ then when (age < 65) is true then "adult" _ then "senior" ); minors : byCategory."minor"; // [17, 16] adults : byCategory."adult"; // [18, 25, 30, 45] // Array processing utilities data : [1, 2, 3, 4, 5, 6, 7, 8]; chunks : chunk data 3; // [[1, 2, 3], [4, 5, 6], [7, 8]] sequence : range 0 4; // [0, 1, 2, 3, 4] repeated : repeat 3 "x"; // ["x", "x", "x"] ``` ## Local Bindings with `with` Stage local bindings in a function header right after the arrow. Entries are processed left-to-right in an inner scope. You can type locals using the same style as globals. ```baba // Untyped locals addMul : x y -> with (inc : x + 1; prod : inc * y;) -> inc + prod; // Typed parameters + typed locals sumNext : (x: Int, y: Int) -> Int -> with (nx Int; ny Int; nx : x + 1; ny : y + 1;) -> nx + ny; ``` Semicolons - Inside `with ( ... )`: semicolons separate entries; trailing `;` allowed - Between header and body: `->` - After body: same as top-level statements ## Typed Functions in Practice You can annotate parameter and return types. Validation happens at runtime. ```baba // Two typed params, typed return mul : (x: Int, y: Int) -> Int -> x * y; // Curried with types startsWith : (prefix: String, s: String) -> Bool -> str.substring s 0 (str.length prefix) = prefix; // Partially applying a typed function startsWithHello : startsWith "Hello"; isHello : startsWithHello "Hello, world"; // true ``` ## Combinators Combinators are function building blocks without free variables. ```baba // K combinator: K x y = x K : x y -> x; // I combinator: I x = x I : x -> x; // S combinator: S f g x = f x (g x) S : f g x -> f x (g x); // Composition via combinators compose : f g x -> f (g x); res : compose (x -> x + 1) (x -> x * 2) 5; // 11 ``` ## Functions in Tables Tables can hold functions; access properties with dot notation. ```baba math : { add: x y -> x + y, mul: x y -> x * y }; resAdd : math.add 2 3; // 5 ``` ## Advanced Array Programming Baba Yaga includes powerful array programming features inspired by APL, K, and Q: ### Scan Operations (Cumulative Operations) ```baba // General scan operation numbers : [1, 2, 3, 4, 5]; addFunc : acc x -> acc + x; scanned : scan addFunc 0 numbers; // [0, 1, 3, 6, 10, 15] // Built-in utilities cumsum : cumsum numbers; // [0, 1, 3, 6, 10, 15] cumprod : cumprod numbers; // [1, 1, 2, 6, 24, 120] ``` ### Advanced Array Indexing ```baba data : [10, 21, 30, 43, 50]; // Select elements at specific indices indices : [0, 2, 4]; selected : at indices data; // [10, 30, 50] // Find indices where predicate is true evenPredicate : x -> x % 2 = 0; evenIndices : where evenPredicate data; // [0, 2, 4] // Take and drop elements firstThree : take 3 data; // [10, 21, 30] lastTwo : drop 3 data; // [43, 50] ``` ### Array Broadcasting Operations ```baba // Broadcast scalar operation over array addOp : x y -> x + y; numbers : [1, 2, 3, 4]; broadcasted : broadcast addOp 10 numbers; // [11, 12, 13, 14] // Element-wise operations between arrays array1 : [1, 2, 3]; array2 : [10, 20, 30]; zipped : zipWith addOp array1 array2; // [11, 22, 33] // Reshape arrays into matrices flatArray : [1, 2, 3, 4, 5, 6]; matrix : reshape [2, 3] flatArray; // 2x3 matrix ``` ### Enhanced Function Combinators ```baba // Flip function arguments add : x y -> x + y; flippedAdd : flip add; result : flippedAdd 3 5; // 8 (same as 5 + 3) // Apply function to value double : x -> x * 2; result : apply double 7; // 14 // Pipe value through function (reverse apply) result : pipe 5 double; // 10 // Function composition increment : x -> x + 1; composed : compose increment double; result : composed 4; // 9 (double then increment) ``` ### Monadic Operations ```baba // flatMap for flattening mapped results duplicateFunc : x -> [x, x]; original : [1, 2, 3]; duplicated : flatMap duplicateFunc original; // [1, 1, 2, 2, 3, 3] // Chain operations that produce lists rangeFunc : x -> range 1 x; chained : flatMap rangeFunc [2, 3]; // [1, 2, 1, 2, 3] ``` ## Pattern Guards Pattern matching can be enhanced with conditional guards using the `if` keyword. For detailed documentation and examples, see [Pattern Matching](./03_pattern-matching.md#pattern-guards). ```baba // Example: Age categorization with guards categorizeAge : age -> when age is a if (a >= 0 and a < 18) then "minor" a if (a >= 18 and a < 65) then "adult" a if (a >= 65) then "senior" _ then "invalid"; ``` ## On Style - Prefer small, pure functions - Build complex behavior by composing simple functions - Use array programming operations for data transformation - Leverage pattern guards for complex conditional logic - Combine scan, broadcast, and flatMap for powerful data processing pipelines