YREA-SLS/docs/generic_programming.md

174 lines
3.9 KiB
Markdown

## 10. Generic Programming
### 10.1 Type Parameters
Type parameters allow functions, structs, and traits to work with multiple types.
**Generic Syntax**: `<T>` where T is a type parameter
**Examples**:
```
// Generic struct
(T T --) { x: y: } ::Point<T> struct
// Generic union
(T --) { Some(T) None } ::Option<T> union
// Generic trait
{
(Self T -- Self) append:
} ::Container<T> 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<T E> 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<T> struct
// Use with different types
3.0 4.0 Point // Point<f64>
3 4 Point // Point<i64>
// Multiple type parameters
(T U --) { first: second: } ::Pair<T U> struct
5 "hello" Pair // Pair<i64 String>
```
**Generic Unions**:
```
// Option is generic over contained type
(T --) { Some(T) None } ::Option<T> union
42 Option::Some // Option<i64>::Some
"text" Option::Some // Option<String>::Some
Option::None // Option<T>::None (T inferred from context)
// Result with two type parameters
(T E --) { Ok(T) Err(E) } ::Result<T E> union
```
**Nested Generics**:
```
// Array of Options
[Option::Some Option::None] // Array of Option<T>
// Option of array
[1 2 3] Option::Some // Option<Array<i64>>
```
### 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<T> trait
// Map generic over key and value types
{
(Self K -- V) get:
(Self K V -- Self) insert:
} ::Map<K V> 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<T> ] ::Stack<T> inher
{
(Self -- T) peek:
} ::Stack<T> trait
// Inheriting trait specifies concrete type
[ ::Container<i32> ] ::IntStack inher
{
(Self -- i32) peek:
} ::IntStack trait
// Multiple generic inheritance
[ ::Selectable<T> ::Sized ::Sliceable ] ::ArrayOf<T> inher
{ } ::ArrayOf<T> 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.
---