# Function Composition ## What is the `via` Operator? The `via` operator is a function composition operator that combines functions from right to left. ```plaintext /* f via g = compose(f, g) */ /* f via g via h = compose(f, compose(g, h)) */ ``` The `via` operator is right-associative and matches mathematical notation where `(f ∘ g ∘ h)(x) = f(g(h(x)))`. ```plaintext /* Define simple functions */ double : x -> x * 2; increment : x -> x + 1; square : x -> x * x; /* Using via composition */ result1 : double via increment 5; /* Result: 12 (5+1=6, 6*2=12) */ /* Chained via composition */ result2 : double via increment via square 3; /* Result: 20 (3^2=9, 9+1=10, 10*2=20) */ ``` The key insight is that `via` groups from right to left. ```plaintext /* This expression: */ double via increment via square 3 /* Groups as: */ double via (increment via square) 3 /* Which translates to: */ compose(double, compose(increment, square))(3) /* With the execution order of: */ /* 1. square(3) = 9 */ /* 2. increment(9) = 10 */ /* 3. double(10) = 20 */ ``` ## Precedence rules and `via` The `via` operator has higher precedence than function application: ```plaintext /* via binds tighter than juxtaposition */ double via increment 5 /* This is parsed as: */ (double via increment) 5 ``` ## More examples ```plaintext /* Data processing pipeline */ data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; is_even : x -> x % 2 = 0; double : x -> x * 2; sum : x -> reduce add 0 x; /* Pipeline using via */ process_pipeline : sum via map double via filter is_even; result : process_pipeline data; /* Reads: sum via (map double via filter is_even) */ /* Result: 60 */ ``` You'll note that we don't need to use `@` here -- `via` is kinda special-cased because it is an ergonomic feature. It can work with function names directly because it's specifically for function composition. Higher-order functions like `map`, `filter`, and `reduce` require explicit function references using `@` because they need a way to distinguish between calling a function immediately vs passing it as an argument while `via` only ever takes in functions. A goal with the `via` operator is to align with mathematical function composition: ```plaintext /* Mathematical: (f ∘ g ∘ h)(x) = f(g(h(x))) */ /* Baba Yaga: f via g via h x = f(g(h(x))) */ ``` ## When to Use `via` **Use `via` when you want:** - Natural reading: `f via g via h` reads as "f then g then h" - Mathematical notation: Matches `(f ∘ g ∘ h)` notation - Concise syntax: Shorter than nested `compose` calls - Right-to-left flow: When you think of data flowing right to left **Don't use `via` when:** - You need left-to-right composition (use `pipe`) - You want explicit mathematical style (use `compose`) - You're working with simple function calls (use juxtaposition) - If you don't wanna ## Common Patterns ```plaintext /* Data transformation pipeline */ data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; is_even : x -> x % 2 = 0; double : x -> x * 2; sum : x -> reduce add 0 x; /* Pipeline: filter → map → reduce */ process_pipeline : sum via map double via filter is_even; result : process_pipeline data; /* Result: 60 (filter evens: {2,4,6,8,10}, double: {4,8,12,16,20}, sum: 60) */ /* Validation chain */ validate_positive : x -> x > 0; validate_even : x -> x % 2 = 0; validate_small : x -> x < 10; /* Chain validations */ all_validations : validate_small via validate_even via validate_positive; result : all_validations 6; /* 6 > 0, 6 % 2 = 0, 6 < 10 */ /* Result: true */ ``` ## Debugging `via` Chains To understand execution order, break down the chain: ```plaintext /* Complex chain: */ result : square via double via increment via square 2; /* Break it down: */ /* 1. square(2) = 4 */ /* 2. increment(4) = 5 */ /* 3. double(5) = 10 */ /* 4. square(10) = 100 */ /* Result: 100 */ ```