## 10. Generic Programming ### 10.1 Type Parameters Type parameters allow functions, structs, and traits to work with multiple types. **Generic Syntax**: `` where T is a type parameter **Examples**: ``` // Generic struct (T T --) { x: y: } ::Point struct // Generic union (T --) { Some(T) None } ::Option union // Generic trait { (Self T -- Self) append: } ::Container trait ``` **Type Parameter Constraints**: When operations are performed on type parameters, they must be constrained by traits: ``` // Unconstrained - no operations on T (T -- T) { } ::identity fn // Constrained - T must support multiplication (T:Multiplyable -- T) { dup * } ::square fn ``` **Multiple Type Parameters**: ``` (T E --) { Ok(T) Err(E) } ::Result union ``` ### 10.2 Generic Functions Generic functions work with multiple types by using trait constraints in their type tuples. **Syntax**: `(trait_constraints -- outputs) { body } ::name fn` **Examples**: ``` // Generic identity - works with any type (no operations, no constraint needed) (T -- T) { } ::identity fn // Requires Addable trait (Addable Addable -- Addable) { + } ::add_values fn // Requires Number trait (Number -- Number) { dup 0 > { } { 0 swap - } if } ::abs fn // Multiple constraints (Number Number -- Number) { dup * swap dup * + // a² + b² } ::pythagorean fn ``` **Type Inference**: The compiler infers the actual type from usage: ``` 5 identity // T inferred as i64 "hello" identity // T inferred as String 3 4 add_values // Addable inferred as i64 ``` ### 10.3 Generic Data Structures Structs and unions can be generic over type parameters: **Generic Structs**: ``` // Point is generic over coordinate type (T T --) { x: y: } ::Point struct // Use with different types 3.0 4.0 Point // Point 3 4 Point // Point // Multiple type parameters (T U --) { first: second: } ::Pair struct 5 "hello" Pair // Pair ``` **Generic Unions**: ``` // Option is generic over contained type (T --) { Some(T) None } ::Option union 42 Option::Some // Option::Some "text" Option::Some // Option::Some Option::None // Option::None (T inferred from context) // Result with two type parameters (T E --) { Ok(T) Err(E) } ::Result union ``` **Nested Generics**: ``` // Array of Options [Option::Some Option::None] // Array of Option // Option of array [1 2 3] Option::Some // Option> ``` ### 10.4 Generic Traits Traits can be generic, allowing them to describe behavior parameterized over types. **Generic Trait Syntax**: ``` // Container generic over element type { (Self T -- Self) append: (Self -- T) pop: } ::Container trait // Map generic over key and value types { (Self K -- V) get: (Self K V -- Self) insert: } ::Map trait ``` **Generic Trait Inheritance**: When inheriting from generic traits, you must either: 1. Make the inheriting trait similarly generic 2. Specify concrete types for the generic parameters ``` // Inheriting trait is also generic [ ::Container ] ::Stack inher { (Self -- T) peek: } ::Stack trait // Inheriting trait specifies concrete type [ ::Container ] ::IntStack inher { (Self -- i32) peek: } ::IntStack trait // Multiple generic inheritance [ ::Selectable ::Sized ::Sliceable ] ::ArrayOf inher { } ::ArrayOf trait ``` ### 10.5 Type Parameter Enforcement **Current Behavior**: Type parameters are currently suggestions when parsing code blocks. The compiler does not yet enforce that type parameters actually constrain how operators and functions act at parse time. **Example**: ``` // Currently no error even without Multiplyable constraint (T -- T) { dup * } ::square fn // Should require constraint (Multiplyable -- Multiplyable) { dup * } ::square fn ``` > **Future Enhancement**: See Appendix F for planned type parameter enforcement at parse time. ---