diff options
Diffstat (limited to 'js/scripting-lang/tutorials/02_Function_Composition.md')
-rw-r--r-- | js/scripting-lang/tutorials/02_Function_Composition.md | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/js/scripting-lang/tutorials/02_Function_Composition.md b/js/scripting-lang/tutorials/02_Function_Composition.md new file mode 100644 index 0000000..a6137b4 --- /dev/null +++ b/js/scripting-lang/tutorials/02_Function_Composition.md @@ -0,0 +1,138 @@ +# 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 */ +``` \ No newline at end of file |