Documentation structure inspired by Rust Book, Elm Guide, and others: Guide (10 chapters): - Introduction and setup - Basic types (Int, String, Bool, List, Option, Result) - Functions (closures, higher-order, composition) - Data types (ADTs, pattern matching, records) - Effects (the core innovation) - Handlers (patterns and techniques) - Modules (imports, exports, organization) - Error handling (Fail, Option, Result) - Standard library reference - Advanced topics (traits, generics, optimization) Reference: - Complete syntax reference Tutorials: - Calculator (parsing, evaluation, REPL) - Dependency injection (testing with effects) - Project ideas (16 projects by difficulty) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.7 KiB
4.7 KiB
Chapter 2: Basic Types
Lux is statically typed with full type inference. You rarely need to write types—the compiler figures them out—but understanding them helps.
Primitive Types
Int
64-bit signed integers:
let x = 42
let y = -17
let big = 9_223_372_036_854_775_807 // Underscores for readability
// Arithmetic
x + y // 25
x - y // 59
x * y // -714
x / y // -2 (integer division)
x % y // 8 (remainder)
Float
64-bit floating point (IEEE 754):
let pi = 3.14159
let e = 2.718
pi * 2.0 // 6.28318
e / 2.0 // 1.359
Bool
Boolean values:
let yes = true
let no = false
// Operators
true && false // false (and)
true || false // true (or)
!true // false (not)
// Comparison
5 > 3 // true
5 == 5 // true
5 != 3 // true
5 <= 5 // true
String
UTF-8 strings:
let greeting = "Hello"
let name = "World"
// Concatenation
greeting + ", " + name + "!" // "Hello, World!"
// String interpolation
let message = "The answer is ${40 + 2}" // "The answer is 42"
// Multiline
let poem = "
Roses are red,
Violets are blue,
Lux has effects,
And so can you.
"
Char
Single Unicode characters:
let letter = 'A'
let emoji = '🎉'
Unit
The type with only one value, (). Used when a function doesn't return anything meaningful:
fn printHello(): Unit with {Console} =
Console.print("Hello")
let nothing: Unit = ()
Type Annotations
Usually optional, but sometimes helpful:
// Inferred
let x = 42 // Int
let s = "hello" // String
// Explicit
let x: Int = 42
let s: String = "hello"
// Required when ambiguous
let empty: List<Int> = []
Lists
Ordered collections of the same type:
let numbers = [1, 2, 3, 4, 5]
let words = ["hello", "world"]
let empty: List<Int> = []
// Operations (from List module)
List.length(numbers) // 5
List.head(numbers) // Some(1)
List.tail(numbers) // [2, 3, 4, 5]
List.map(numbers, fn(x: Int): Int => x * 2) // [2, 4, 6, 8, 10]
List.filter(numbers, fn(x: Int): Bool => x > 2) // [3, 4, 5]
List.fold(numbers, 0, fn(acc: Int, x: Int): Int => acc + x) // 15
Option
For values that might not exist:
let some_value: Option<Int> = Some(42)
let no_value: Option<Int> = None
// Pattern matching
fn describe(opt: Option<Int>): String =
match opt {
Some(n) => "Got: " + toString(n),
None => "Nothing"
}
// Option operations
Option.map(Some(5), fn(x: Int): Int => x * 2) // Some(10)
Option.map(None, fn(x: Int): Int => x * 2) // None
Option.getOrElse(Some(5), 0) // 5
Option.getOrElse(None, 0) // 0
Result
For operations that can fail:
let success: Result<Int, String> = Ok(42)
let failure: Result<Int, String> = Err("Something went wrong")
// Pattern matching
fn handle(r: Result<Int, String>): String =
match r {
Ok(n) => "Success: " + toString(n),
Err(e) => "Error: " + e
}
// Result operations
Result.map(Ok(5), fn(x: Int): Int => x * 2) // Ok(10)
Result.map(Err("oops"), fn(x: Int): Int => x * 2) // Err("oops")
Tuples
Fixed-size collections of different types:
let pair = (1, "hello")
let triple = (true, 42, "world")
// Access by pattern matching
let (x, y) = pair
// x = 1, y = "hello"
Records
Named fields:
let person = { name: "Alice", age: 30 }
// Access
person.name // "Alice"
person.age // 30
// With type annotation
type Person = { name: String, age: Int }
let bob: Person = { name: "Bob", age: 25 }
Type Conversion
// To String
toString(42) // "42"
toString(true) // "true"
toString([1,2,3]) // "[1, 2, 3]"
// String to Int (via Console effect)
let n = Console.readInt()
Type Checking
The compiler catches type errors:
let x: Int = "hello" // Error: expected Int, got String
fn add(a: Int, b: Int): Int = a + b
add(1, "two") // Error: expected Int, got String
let nums = [1, 2, "three"] // Error: list elements must have same type
Summary
| Type | Example | Description |
|---|---|---|
Int |
42 |
64-bit integer |
Float |
3.14 |
64-bit float |
Bool |
true |
Boolean |
String |
"hello" |
UTF-8 string |
Char |
'A' |
Unicode character |
Unit |
() |
No meaningful value |
List<T> |
[1, 2, 3] |
Ordered collection |
Option<T> |
Some(42) |
Optional value |
Result<T, E> |
Ok(42) |
Success or failure |
(A, B) |
(1, "hi") |
Tuple |
{...} |
{x: 1} |
Record |
Next
Chapter 3: Functions - Learn to define and compose functions.