9. Trait System¶
9.1 What are Traits¶
Traits define behavioral contracts - they specify what operations a type must support without dictating how those operations are implemented.
Why Traits Exist:
- Define common behavior across different types
- Enable generic programming with constraints
- Back every operator in the language
- Allow user-defined operators through trait implementation
Standard Traits Overview:
The language provides many built-in traits:
::Stackable- Stack manipulation operations::Addable,::Multiplyable- Arithmetic operations::Comparable,::Equatable- Comparison operations::Logical,::Bitwise- Boolean and bit operations::Sized,::Selectable<T>,::Sliceable- Container operations::Math- Mathematical functions::Number- Composite numeric operations- And many more...
Complete Reference: See Appendix B for all standard trait definitions with complete documentation.
9.2 Defining Traits¶
Syntax: { method_signatures } ::identifier<type_params>? trait
Traits can have methods or be empty (marker traits). Empty traits are typically used with inheritance.
Examples:
// Trait with methods
{
(Self -- ) draw:
} ::Drawable trait
// Trait with multiple methods
{
(Self Self -- Self) add:
(Self Self -- Self) sub:
(Self -- Self) neg:
} ::Numeric trait
// Generic trait
{
(Self T -- Self) append:
(Self -- T) pop:
} ::Container<T> trait
// Empty marker trait
{ } ::Serializable trait
Method Signatures: Within the TokenString, identifiers are method names and should not use the :: prefix.
9.3 Implementing Traits¶
Syntax: ::trait_identifier { method_implementations } ::type_identifier impl
Implementation Rules:
- Implementing a trait for itself (
::Trait { ... } ::Trait impl) creates a default implementation for all types - A trait must be defined before it can be implemented
- Method implementations can be split across multiple
implblocks - Later implementations can override earlier ones for the same type
Examples:
// Implement Addable for i32
::Addable {
(Self Self -- Self) {
// Native addition implementation
} +:
(Self Self -- Self) {
// Native subtraction implementation
} -:
} ::i32 impl
// Implement Drawable for Rectangle
::Drawable {
(Self -- ) {
"Drawing rectangle" print
dup ::width get print
::height get print
} draw:
} ::Rectangle impl
More Examples: See Appendix G for complete implementation examples and tutorials.
9.4 Trait Inheritance¶
Syntax: [ identifier_list ] ::identifier<type_params>? inher { methods } ::identifier<type_params>? trait
Trait inheritance allows a trait to include all methods from parent traits, optionally adding new methods.
Examples:
// Combine multiple arithmetic traits
[ ::Addable ::Multiplyable ] ::BasicNumber inher
{ } ::BasicNumber trait
// Full Number inherits everything numeric
[ ::Addable ::Multiplyable ::Exponentiable ::Comparable ::Logarithmic ] ::Number inher
{ } ::Number trait
// Inheritance with additional methods
[ ::Drawable ::Transformable ::Collidable ] ::GameObject inher
{
(Self -- ) update:
(Self -- ) destroy:
} ::GameObject trait
Generic Trait Inheritance:
When inheriting from generic traits, you must either make the inheriting trait similarly generic or specify concrete types:
// Inheriting trait is also generic
[ ::Container<T> ] ::Stack<T> inher
{
(Self -- T) pop:
} ::Stack<T> trait
// Inheriting trait specifies concrete type
[ ::Container<i32> ] ::IntStack inher
{
(Self -- i32) pop:
} ::IntStack trait
9.5 Using Traits in Functions¶
Traits can be used as type constraints in function signatures:
Examples:
// Function requiring Drawable trait
(Drawable -- ) {
draw
} ::draw_object fn
// Function requiring Number trait
(Number Number -- Number) {
dup * swap dup * + // Pythagorean: a² + b²
} ::sum_of_squares fn
// Generic function with trait constraint
(Multiplyable -- Multiplyable) {
dup *
} ::square fn
Multiple Constraints: Use specific traits or composite traits that inherit from multiple parents:
// Requires both Addable and Comparable
(Number -- Number) { ... } ::some_function fn
// Number trait inherits from both, so this works
9.6 Standard Traits Overview¶
This section provides a brief overview of all standard traits. For complete definitions with all methods and documentation, see Appendix B.
Stack Operations:
::Stackable- Fundamental stack manipulation (dup, drop, swap, over, rot, pick, roll, depth)
Arithmetic:
::Addable- Addition and subtraction (+, -)::Multiplyable- Multiplication, division, modulo (*, /, %)::Exponentiable- Exponentiation (^)::Logarithmic- Logarithm operations (log, ln, logb)::Math- Mathematical functions (sqrt, abs, sin, cos, tan, asin, acos, atan, atan2, floor, ceil, round, min, max)::Number- Composite trait combining all arithmetic and comparison
Comparison:
::Orderable- Ordering comparisons (>, >=, <, <=)::Equatable- Equality comparisons (==, !=)::Comparable- Composite trait combining Orderable and Equatable
Logical and Bitwise:
::Logical- Boolean operations (and, or, not, truthy)::Bitwise- Bit manipulation (bitand, bitor, bitxor, bitnot, shl, shr)
Containers:
::Sized- Length information (length)::Selectable<T>- Element access (at)::Sliceable- Slicing operations (slice)::Concatenable- Concatenation (concat)::ArrayOf<T>- Composite array trait::Iterable<T>- Iteration support (next)
Conversion:
::Convertible- Type conversions (to_i8, to_i16, ..., to_f32, to_f64)::Stringifiable- String conversion (to_str)::Parseable- Parse from string (parse)
String Operations:
::String- String-specific operations (substr, split, replace, trim, find, starts_with, ends_with) - inherits from Concatenable
Utilities:
::Size- Types suitable for indexing (inherits Addable, Comparable, Convertible)::Identifier- Marks identifiers::Implementable- Meta-trait for defining language constructs (trait, impl, inher)
Complete Reference: See Appendix B for full trait definitions with all methods, examples, and implementation details.