# Chapter 10: Advanced Topics This chapter covers advanced features for building larger applications. ## Traits Traits define shared behavior across types: ```lux trait Show { fn show(self): String } impl Show for Int { fn show(self): String = toString(self) } impl Show for Bool { fn show(self): String = if self then "true" else "false" } impl Show for List where T: Show { fn show(self): String = { let items = List.map(self, fn(x: T): String => x.show()) "[" + String.join(items, ", ") + "]" } } ``` Using traits: ```lux fn display(value: T): Unit with {Console} where T: Show = Console.print(value.show()) display(42) // "42" display(true) // "true" display([1, 2, 3]) // "[1, 2, 3]" ``` ## Generic Types Types with parameters: ```lux type Pair = | MkPair(A, B) fn first(p: Pair): A = match p { MkPair(a, _) => a } fn second(p: Pair): B = match p { MkPair(_, b) => b } let p = MkPair(1, "one") first(p) // 1 second(p) // "one" ``` ## Type Constraints Restrict generic types: ```lux fn maximum(list: List): Option where T: Ord = { match list { [] => None, [x] => Some(x), [x, ...rest] => { match maximum(rest) { None => Some(x), Some(y) => Some(if x > y then x else y) } } } } ``` ## Tail Call Optimization Lux optimizes tail-recursive functions: ```lux // Not tail-recursive - stack grows with each call fn sumBad(n: Int): Int = if n <= 0 then 0 else n + sumBad(n - 1) // Addition happens AFTER recursive call // Tail-recursive - constant stack space fn sumGood(n: Int, acc: Int): Int = if n <= 0 then acc else sumGood(n - 1, acc + n) // Recursive call is the LAST operation fn sum(n: Int): Int = sumGood(n, 0) ``` The compiler transforms tail calls into loops, preventing stack overflow. ## Effect Polymorphism Functions can be polymorphic over effects: ```lux fn withLogging(action: fn(): Int with {E}): Int with {E, Console} = { Console.print("Starting action") let result = action() Console.print("Action returned: " + toString(result)) result } // Works with any effect set fn pureAction(): Int = 42 fn randomAction(): Int with {Random} = Random.int(1, 100) withLogging(pureAction) // Works withLogging(randomAction) // Works ``` ## Behavioral Properties Annotate functions with properties: ```lux // Pure function - no effects fn add(a: Int, b: Int): Int is pure = a + b // Total function - always terminates fn factorial(n: Int): Int is total = if n <= 1 then 1 else n * factorial(n - 1) // Idempotent - same result if called multiple times fn setConfig(key: String, value: String): Unit with {State} is idempotent = State.put(value) ``` These are currently documentation, but future versions may verify them. ## Documentation Comments Use `///` for documentation: ```lux /// Calculates the factorial of a non-negative integer. /// /// # Arguments /// * `n` - A non-negative integer /// /// # Returns /// The factorial of n (n!) /// /// # Example /// ``` /// factorial(5) // Returns 120 /// ``` pub fn factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) ``` ## Performance Tips ### 1. Use Tail Recursion ```lux // Slow - builds up stack fn lengthSlow(list: List): Int = match list { [] => 0, [_, ...rest] => 1 + lengthSlow(rest) } // Fast - constant stack fn lengthFast(list: List, acc: Int): Int = match list { [] => acc, [_, ...rest] => lengthFast(rest, acc + 1) } ``` ### 2. Avoid Repeated Concatenation ```lux // Slow - O(n²) fn buildStringSlow(n: Int): String = if n <= 0 then "" else buildStringSlow(n - 1) + "x" // Fast - use List.join fn buildStringFast(n: Int): String = String.join(List.map(List.range(0, n), fn(_: Int): String => "x"), "") ``` ### 3. Use Built-in Functions ```lux // Slow - manual implementation fn sumManual(nums: List): Int = match nums { [] => 0, [x, ...rest] => x + sumManual(rest) } // Fast - built-in fold fn sumBuiltin(nums: List): Int = List.fold(nums, 0, fn(acc: Int, x: Int): Int => acc + x) ``` ### 4. JIT Compilation For performance-critical numeric code, the JIT compiler provides ~160x speedup: ```lux // In Rust code, use the JIT compiler let mut jit = JitCompiler::new().unwrap(); jit.compile_function(&func).unwrap(); let result = unsafe { jit.call_function("fib", &[30]).unwrap() }; ``` ## Debugging ### Debug Printing ```lux fn debug(label: String, value: T): T with {Console} = { Console.print(label + ": " + toString(value)) value } fn process(x: Int): Int with {Console} = { let step1 = debug("step1", x * 2) let step2 = debug("step2", step1 + 10) step2 } ``` ### The Debugger Run with debugger: ```bash lux --debug program.lux ``` Commands: - `step` / `s` - Step into - `next` / `n` - Step over - `continue` / `c` - Continue - `print ` - Evaluate expression - `break ` - Set breakpoint - `quit` / `q` - Exit ### Effect Tracing ```lux fn traced(action: fn(): T with {E}): T with {E, Console} = { Console.print(">>> Entering action") let result = action() Console.print("<<< Exiting with: " + toString(result)) result } ``` ## IDE Support Lux has LSP support for: - **VS Code**: Install Lux extension - **Neovim**: Configure with nvim-lspconfig Features: - Syntax highlighting - Error diagnostics - Go to definition - Hover for types - Auto-completion Start LSP server: ```bash lux --lsp ``` ## Project Structure Recommended layout for larger projects: ``` my-project/ ├── lux.toml # Project manifest ├── src/ │ ├── main.lux # Entry point │ ├── lib.lux # Library code │ └── modules/ │ ├── users.lux │ └── orders.lux ├── std/ # Custom std extensions ├── tests/ │ ├── users_test.lux │ └── orders_test.lux └── examples/ └── demo.lux ``` ## Summary | Feature | Syntax | |---------|--------| | Trait | `trait Name { fn method(self): T }` | | Impl | `impl Trait for Type { ... }` | | Generic | `fn f(x: T): T` | | Constraint | `where T: Trait` | | Tail recursion | Last expression is recursive call | | Doc comment | `/// Documentation` | ## What's Next? You now know Lux! Try: 1. **Build something**: See [Tutorials](../tutorials/README.md) 2. **Read the reference**: See [Language Reference](../reference/syntax.md) 3. **Explore effects**: See [Effects Cookbook](../tutorials/effects-cookbook.md) 4. **Join the community**: GitHub discussions Happy coding with Lux!