diff options
Diffstat (limited to 'js/scripting-lang/tutorials/14_Advanced_Combinators.md')
-rw-r--r-- | js/scripting-lang/tutorials/14_Advanced_Combinators.md | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/js/scripting-lang/tutorials/14_Advanced_Combinators.md b/js/scripting-lang/tutorials/14_Advanced_Combinators.md new file mode 100644 index 0000000..28937d1 --- /dev/null +++ b/js/scripting-lang/tutorials/14_Advanced_Combinators.md @@ -0,0 +1,295 @@ +# Advanced Combinators + +## What are Advanced Combinators? + +Advanced combinators are powerful patterns that combine multiple functions and operations to solve complex problems. They build on the basic combinators you've already learned. + +## Partial Application and Currying + +### Creating Specialized Functions +```plaintext +/* Basic partial application */ +add : x y -> x + y; +add_ten : add 10; +result : add_ten 5; /* 15 */ + +/* Complex partial application */ +format_with_prefix : prefix value -> prefix + ": " + value; +format_name : format_with_prefix "Name"; +format_age : format_with_prefix "Age"; + +person : {name: "Alice", age: 30}; +formatted_name : format_name person.name; /* "Name: Alice" */ +formatted_age : format_age person.age; /* "Age: 30" */ +``` + +### Currying with Combinators +```plaintext +/* Create specialized functions */ +multiply_by : x y -> x * y; +double : multiply_by 2; +triple : multiply_by 3; + +numbers : {1, 2, 3, 4, 5}; +doubled : map @double numbers; /* {2, 4, 6, 8, 10} */ +tripled : map @triple numbers; /* {3, 6, 9, 12, 15} */ +``` + +## Higher-Order Combinators + +### Combinators that Work with Other Combinators +```plaintext +/* Apply a combinator to multiple collections */ +apply_to_all : combinator collections -> + reduce @t.merge {} (map @combinator collections); + +/* Example usage */ +add_one : x -> x + 1; +collections : {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; +all_incremented : apply_to_all @map @add_one collections; +/* Result: {1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10} */ +``` + +### Composing Multiple Functions +```plaintext +/* Compose many functions together */ +compose_many : functions -> + reduce @compose @identity functions; + +/* Example usage */ +double_then_increment : compose @increment @double; +complex_transform : compose @double_then_increment @square; +result : complex_transform 3; +/* Result: 19 (3^2=9, 9*2=18, 18+1=19) */ +``` + +## Memoization Pattern + +### Caching Function Results +```plaintext +/* Simple memoization */ +memoize : f -> { + cache: {}, + compute: x -> + when t.has cache x then t.get cache x + _ then { + result: f x, + new_cache: t.set cache x (f x) + } +}; + +/* Using memoized function */ +expensive_calc : x -> x * x * x; /* Simulate expensive computation */ +memoized_calc : memoize @expensive_calc; +result1 : memoized_calc.compute 5; /* Computes 125 */ +result2 : memoized_calc.compute 5; /* Uses cached result */ +``` + +## Real-World Problem Solving + +### E-commerce Order Processing +```plaintext +/* Process customer orders */ +orders : { + order1: {customer: "Alice", items: {book: 2, pen: 5}, status: "pending"}, + order2: {customer: "Bob", items: {laptop: 1}, status: "shipped"}, + order3: {customer: "Charlie", items: {book: 1, pen: 3}, status: "pending"} +}; + +prices : {book: 15, pen: 2, laptop: 800}; + +/* Calculate order totals */ +calculate_total : order -> { + customer: order.customer, + total: reduce @add 0 (map @calculate_item_total order.items), + status: order.status +}; + +calculate_item_total : item quantity -> + when item is + "book" then 15 * quantity + "pen" then 2 * quantity + "laptop" then 800 * quantity + _ then 0; + +/* Process all orders */ +processed_orders : map @calculate_total orders; +..out processed_orders; +``` + +### Data Transformation Pipeline +```plaintext +/* Transform user data through multiple stages */ +users : { + alice: {name: "Alice", age: 25, city: "NYC", active: true}, + bob: {name: "Bob", age: 30, city: "LA", active: false}, + charlie: {name: "Charlie", age: 35, city: "NYC", active: true} +}; + +/* Pipeline stages */ +filter_active : users -> filter @is_active users; +add_greeting : users -> map @add_greeting_to_user users; +format_output : users -> map @format_user_output users; + +is_active : user -> user.active; +add_greeting_to_user : user -> t.merge user {greeting: "Hello, " + user.name}; +format_user_output : user -> { + name: user.name, + greeting: user.greeting, + location: user.city +}; + +/* Execute pipeline */ +active_users : filter_active users; +greeted_users : add_greeting active_users; +formatted_users : format_output greeted_users; + +..out formatted_users; +``` + +## Advanced Patterns + +### Lazy Evaluation +```plaintext +/* Lazy evaluation with thunks */ +lazy : computation -> { + compute: computation, + evaluated: false, + result: null, + get: -> + when evaluated then result + _ then { + computed_result: compute, + new_lazy: { + compute: computation, + evaluated: true, + result: computed_result, + get: -> computed_result + } + } +}; + +/* Use lazy evaluation */ +expensive_operation : -> { + /* Simulate expensive computation */ + ..out "Computing..."; + 42 +}; + +lazy_result : lazy expensive_operation; +/* Computation hasn't happened yet */ + +actual_result : lazy_result.get; +/* Now computation happens */ +``` + +### Continuation-Passing Style +```plaintext +/* Continuation-passing style for complex control flow */ +process_with_continuation : data success_cont error_cont -> + when data = null then error_cont "No data provided" + _ then + processed : transform data; + when processed.error is + true then error_cont processed.message + false then success_cont processed.result; + +/* Use continuations */ +success_handler : result -> ..out "Success: " + result; +error_handler : error -> ..out "Error: " + error; + +process_with_continuation "valid data" success_handler error_handler; +process_with_continuation null success_handler error_handler; +``` + +## Performance Optimization + +### Avoiding Redundant Computations +```plaintext +/* Cache expensive computations */ +expensive_transform : data -> + /* Simulate expensive operation */ + data * data * data; + +/* With caching */ +transform_with_cache : { + cache: {}, + transform: data -> + when t.has cache data then t.get cache data + _ then { + result: expensive_transform data, + new_cache: t.set cache data (expensive_transform data) + } +}; + +/* Use cached version */ +result1 : transform_with_cache.transform 5; /* Computes */ +result2 : transform_with_cache.transform 5; /* Uses cache */ +``` + +### Lazy Collections +```plaintext +/* Lazy collection processing */ +lazy_map : f collection -> { + f: f, + collection: collection, + get: index -> + when index >= t.length collection then null + _ then f (t.get collection index) +}; + +/* Use lazy mapping */ +numbers : {1, 2, 3, 4, 5}; +expensive_double : x -> { + /* Simulate expensive operation */ + ..out "Doubling " + x; + x * 2 +}; + +lazy_doubled : lazy_map @expensive_double numbers; +/* No computation yet */ + +first_result : lazy_doubled.get 0; /* Only computes for index 0 */ +``` + +## Best Practices + +### Keep Combinators Focused +```plaintext +/* Good: Single responsibility */ +filter_by_age : min_age users -> + filter @(is_older_than min_age) users; + +is_older_than : min_age user -> user.age >= min_age; + +/* Avoid: Multiple responsibilities */ +bad_filter : min_age max_age users -> + filter @(complex_age_check min_age max_age) users; +``` + +### Use Descriptive Names +```plaintext +/* Good: Clear intent */ +process_active_users : users -> + filter @is_active (map @add_user_id users); + +/* Avoid: Generic names */ +process : data -> + filter @check (map @transform data); +``` + +### Compose, Don't Nest +```plaintext +/* Good: Composed functions */ +pipeline : compose @format_output (compose @add_metadata (filter @is_valid data)); + +/* Avoid: Deep nesting */ +nested : format_output (add_metadata (filter @is_valid data)); +``` + +## Next Steps + +Now that you understand advanced combinators, explore: +- [Integration Patterns](15_Integration_Patterns.md) for external system integration +- [Error Handling](13_Error_Handling.md) for robust error management +- [Best Practices](16_Best_Practices.md) for writing clean code \ No newline at end of file |